帐前卒专栏

code, software architect, articles and novels.
代码,软件架构,博客和小说

源代码工程文件(vs2005) http://d.download.csdn.net/down/1018461/cctt_1

过去在网上找了段代码,发现写的代码要改些地方,而且也想顺便练习下自己的c++编码。

首先我要建立一个真正的树形结构。于是使用了自己过去的 GeneralTree.h

(当然这里还是改动些GeneralTree的代码例如增添了些函数,另外把有些私有函数变成了公有函数)。

训练文本格式如下:并命名为decision2.txt 并发在自己的工程目录下。当然你也可以改改相关源代码
概念  颜色 形状 轻重
苹果   红   球   一般
苹果   绿   球   一般
香蕉   黄   弯月  一般
草莓   红   球    轻
草莓   绿   球    轻
西瓜   绿   椭球  重
西瓜   绿   球    重
桔子   桔黄 椭球  轻

测试格式文本格式如下:命名为test.txt并放在工程目录下(试试改改源代码)

颜色 形状 轻重
红   球   一般
绿   球   一般
黄   弯月  一般

这里应该考虑各个类分开的。不过为了看起来方便,就合在一起了。
下面是具体代码:

/* created by chico chen * date 2009/02/02 * 如需转载注明出处 */ #include “stdafx.h”
#include #include #include #include
#include #include #include #include “D://Tools//not
Finished//TreeTest//TreeTest//GeneralTree.h” using namespace std; // this
class is for computing attribute entropy class AttribDiff { public: string
attribName; // 属性名 map<string,int> attribNum; //具体属性和个数对
map<string,map<string,int>> typeNumber; // 第一个string为具体属性名,第二个为类型, //
int是类型在具体属性中的个数. // 例如:是否可见 类型 形状 // 1 西瓜 圆 // 1 冬瓜 扁 // 0 橘子 圆 //
其中具体属性为圆,类型为西瓜等个数为形状为圆的类型为西瓜的个数 AttribDiff(string& attribName) {
this->attribName = attribName; } // in order to computer entropy of an
attribute double AttribDifferComputer(vector<vector> infos,int
i_attrib,int i_types, vector& visible) { double probability = 0; double
entropy = 0; double attribG = 0; map<string,int> temp; int tempNum = 0;
for(int i =0 ; i < infos.size(); i++) { if(visible[i] != 0 ) { tempNum =
attribNum[infos[i][i_attrib]]; attribNum[infos[i][i_attrib]] = tempNum; temp
= typeNumber[infos[i][i_attrib]]; tempNum = temp[infos[i][i_types]];
temp[infos[i][i_types]] = tempNum; typeNumber[infos[i][i_attrib]] = temp; }
} map<string,int>::iterator i_number; map<string,int>::iterator i_type;
for(i_number = attribNum.begin(); i_number != attribNum.end(); i_number
) {
probability = (*i_number).second/(double)infos.size(); cout
<<(*i_number).first <<“概率为:”<< probability<<endl; entropy = 0; for(i_type =
typeNumber[(*i_number).first].begin(); i_type !=
typeNumber[(*i_number).first].end(); i_type
) { entropy +=
ComputerEntropyHelp((*i_type).second/(double)(*i_number).second); } attribG +=
(-1)probability * entropy; } return attribG; } // compute the entropy double
ComputerEntropyHelp(double pi) { return pi
log(pi)/log((double)2); } }; //
this class is create a data struct for general tree node class NodeInfo {
public: // 颜色 // 红 // 蓝 string attribName; // the attribute name, such as 颜色
vector detailAttrib; // all of detail attributes under one of
attribute name, for example, 红 NodeInfo() { attribName = “”; } NodeInfo(string
& attribName) { this->attribName = attribName; } NodeInfo(NodeInfo & ni) {
this->attribName = ni.attribName; this->detailAttrib = ni.detailAttrib; } //
add detail attributes in NodeInfo void NodeDetailInfoAdd(string & detailA) {
if(!CheckIsHas(detailA)) { this->detailAttrib.push_back(detailA); } } // If
detail attribute is in the detailAttrib list, return true; // else return
false; bool CheckIsHas(string & name) { for(int i = 0; i <
detailAttrib.size(); i++) { if(strcmp(name.c_str(),detailAttrib[i].c_str())
==0) { // the same attribute return true; } } return false; } // this is print
control for printing NodeInfo static void Print(NodeInfo& info) { cout <<
info.attribName<< “(”; for(int i = 0; i < info.detailAttrib.size() ; i++) {
cout << info.detailAttrib[i]<<" "; } cout << “)/n”; } }; // this class is
decision tree class DT { protected: const string filename; // the data file
name vector<vector> infos; // the array for storing information
vector attribs; // the array for storing the attributes
GeneralTreegt; // the general tree for storing the decision tree
const int START; // which column is the start attribute, except the type
column const int I_TYPE;// the column index of type const int MAX_ENTROPY; //
set an max entropy to find the minimal entropy private: // to help print void
PrintHelp(int helpPrint) { for(int i = 0; i < helpPrint; i++) { cout << “…”;
} } // to find the index of the attribName in attribs array int Find(string&
attribName,vector& attribs) { for(int i = 0; i < attribs.size(); i++)
{ if(strcmp(attribName.c_str(),attribs[i].c_str()) == 0) { // the same return
i; } } return -1; } // this function is used for detecting if the arithmetic
is over bool CheckOver(vector& visible,string& type) { map<string,int>
types; int temp = 0; for(int i = 0; i < infos.size(); i++) { if(visible[i] !=
0) { type = infos[i][I_TYPE]; temp = types[infos[i][I_TYPE]]; if(temp == 0) {
types[infos[i][I_TYPE]] = 1; } if(types.size() > 1) { return false; // there
are more than one types } } } return true; // there is only one type } // to
create a Decision Tree void DTCreate(GeneralTreeNode *parent,
vector visible,vector visibleA, int i_attrib,string& detailA, int
helpPrint) { if(i_attrib >= START) { for(int i = 0; i < infos.size(); i++) {
if(strcmp(infos[i][i_attrib].c_str(),detailA.c_str()) !=0) { // not same
detail attribute visible[i] = 0; } } } string type = “”;
if(CheckOver(visible,type)) { // the arithmetic is over and add the type node
into the general tree NodeInfo n(type); GeneralTreeNode * node = new
GeneralTreeNode(n); gt.Insert(node,parent); PrintHelp(helpPrint);
cout << “decision type:”<<n.attribName<<endl; return; } map<string,double>
attribGs; // this is for deciding which attrib should be used for(int i =
START; i < attribs.size(); i++) { // iterate attribs if(visibleA[i] != 0) {
AttribDiff ad(attribs[i]); attribGs[attribs[i]] =
ad.AttribDifferComputer(infos,i,I_TYPE,visible); cout <<attribs[i] <<“的G为:”<<
attribGs[attribs[i]]<<endl; } } // to find the decision attribute double min =
MAX_ENTROPY; string attributeName; for(map<string,double>::iterator i =
attribGs.begin(); i != attribGs.end(); i++) { if(min >= (*i).second) {
attributeName = (*i).first; min = (*i).second; } } NodeInfo n(attributeName);
int i_max = Find(attributeName,attribs); for(int i = 0; i<infos.size() ; i++)
{ n.NodeDetailInfoAdd(infos[i][i_max]); } GeneralTreeNode * node =
new GeneralTreeNode(n); gt.Insert(node,parent); visibleA[i_max] = 0;
PrintHelp(helpPrint); cout << “choose attribute:”<< attributeName<<endl;
for(int i = 0; i < node->data.detailAttrib.size(); i++) {
PrintHelp(helpPrint); cout << “go into the
branch:”<data.detailAttrib[i]<<endl; // go to every branch to decision
DTCreate(node,visible,visibleA,i_max,node->data.detailAttrib[i],helpPrint+1);
} } public: // 要注意的一点是这里的decision2.txt要放在工程目录下。当然如果你愿意可以写绝对路径 // 注意文件的格式: //
首先一列为类别,然后是各个属性 // 例如: 类型 形状 // 西瓜 圆 // 冬瓜 扁 // 橘子 圆
DT():filename(“decision2.txt”),START(1),I_TYPE(0),MAX_ENTROPY(10000) {
GetInfo(attribs,infos,filename); DTCreate(); } // this function is used for
read data from the file // and create the attribute array and all information
array // post: attribs has at least one element // infos has at least one
element // pre: filename is not empty and the file is exist void
GetInfo(vector& attribs,vector<vector>& infos,const string&
filename) { ifstream read(filename.c_str()); int start = 0; int end = 0;
string info = “”; getline(read,info); istringstream iss(info); string attrib;
while(iss >> attrib) { attribs.push_back(attrib); } while(true) { info = “”;
getline(read,info); if(info == “” || info.length() <= 1) { break; }
vector infoline; istringstream stream(info); while(stream >> attrib) {
infoline.push_back(attrib); } infos.push_back(infoline); } read.close(); } //
create the DT void DTCreate() { vector visible(infos.size(),1);
vector visibleA(attribs.size(),1); // to judge which attribute is useless
string temp = “”; DTCreate(NULL,visible,visibleA,START-1,temp,0); } // print
the DT void Print() { gt.LevelPrint(NodeInfo::Print); } void Judge(const
string& testFilename,vector& types,const string& testResultFileName) {
vector attribs_test; vector<vector> infos_test;
GetInfo(attribs_test,infos_test,testFilename);
if(!CheckFileFormat(attribs_test)) { throw “file format error”; }
GeneralTreeNode * root = gt.GetRoot(); for(int i = 0; i <
infos_test.size(); i++) {
types.push_back(JudgeType(root,infos_test[i],attribs_test)); }
WriteTestTypesInfo(testResultFileName,types); } void WriteTestTypesInfo(const
string& filename, vector& types) { ofstream out(filename.c_str()); out
<< “类别”<<endl; for(int i = 0 ; i < types.size(); i++) { out << types[i]<<endl;
} out.close(); } string JudgeType(GeneralTreeNode * node,
vector& info,vector& attribs_test) {
if(gt.GetChildNodeNum(node) == 0) { return node->getData().attribName; } int
index = Find(node->getData().attribName,attribs_test); int branch_index =
Find(info[index],node->getData().detailAttrib); if(branch_index == -1) { // is
not find this detail attribute in this node detailAttrib // there are two way
to deal with this situation // 1. every branch has possibility to choose // 2.
no such type and can not judge // the first solution make the correct ratio
low // the second solution has no fault-tolerance. // and here I choose the
second solution. // if I have more free time later, I will write the first
solution throw “no such type”; } GeneralTreeNode * childNode =
gt.GetAChild(node,branch_index); return JudgeType(childNode,
info,attribs_test); } bool CheckFileFormat(vector& attribs_test) {
bool isCorrect = true; for(int j = 0; j < attribs_test.size(); j++) {
if(Find(attribs_test[j],attribs) == -1) { isCorrect = false; } }
if(attribs_test.size() == attribs.size() - 1) { isCorrect = isCorrect && true;
} else { isCorrect = false; } return isCorrect; } };

这里的main函数这样写(自己使用的VS2005):

int _tmain(int argc, _TCHAR* argv[]) { DT dt; //dt.Print(); string testFile =
“test.txt”; string testResult = “testResult.txt”; vectortypes;
dt.Judge(testFile,types,testResult); return 0; }

自己感觉DT 的注释比较详细,所以在我的blog中就不再做太多的解释。另外这段代码会将测试结果放在工程目录下的testResult.txt中。

另外在控制台上会有生成决策树ID3的相关相关的信息显示,例如:

红概率为:0.25
黄概率为:0.125
桔黄概率为:0.125
绿概率为:0.5
颜色的G为:1
球概率为:0.625
椭球概率为:0.25
弯月概率为:0.125
形状的G为:1.20121
轻概率为:0.375
一般概率为:0.375
重概率为:0.25
轻重的G为:0.688722
choose attribute:轻重
go into the branch:一般
红概率为:0.125
黄概率为:0.125
绿概率为:0.125
颜色的G为:0
球概率为:0.25
弯月概率为:0.125
形状的G为:0
…choose attribute:颜色
…go into the branch:红
…decision type:苹果
…go into the branch:绿
…decision type:苹果
…go into the branch:黄
…decision type:香蕉
…go into the branch:桔黄
…decision type:
go into the branch:轻
红概率为:0.125
桔黄概率为:0.125
绿概率为:0.125
颜色的G为:0
球概率为:0.25
椭球概率为:0.125
形状的G为:0
…choose attribute:颜色
…go into the branch:红
…decision type:草莓
…go into the branch:绿
…decision type:草莓
…go into the branch:黄
…decision type:
…go into the branch:桔黄
…decision type:桔子
go into the branch:重
…decision type:西瓜

这一段信息是什么意思呢?

红概率为:0.25
黄概率为:0.125
桔黄概率为:0.125
绿概率为:0.5
颜色的G为:1

红,黄,桔黄,绿的概率是颜色的具体属性。这里没有把entropy打印出来。如果此段代码被中科院的师弟师妹有幸看到,

你们可以在AttribDifferComputer()函数中添加几行代码就可以把每一个entropy打印出来。反正老师也会让你们看代码,这里就当作作业题吧。
(另外老师第十章机器学习ppt上的决策树的这个例子计算结果有错误。如果你认真计算过的话)颜色G的含义是颜色G的决策值,决策值越小,选择此属性的概率就越大。

那决策树是什么样子的呢?

choose attribute:轻重
go into the branch:一般

…choose attribute:颜色
…go into the branch:红


看看上面的这些.这里代表根节点是“轻重”,然后进入“一般”分支,然后进入“一般”分支的节点为颜色…然后进入”红“分支.这里一定要注意”…“,相等的"…
”代表树的相同的层次。

做出这个Decision Tree 的ID3代码主要是为了学弟学妹们在考试中测试用的。因为我只是测试了老师ppt中的例子,不保证对于所有的例子都正确。而且老
师出的考试题比较变态(属性十个左右)…如果手工计算应该需要一个小时左右的时间。

当初后悔没有先编一个程序。祝各位考试顺利…(我想我这段代码可能会在考试之前被搜到)。

同时提醒大家一点, ID3也不是什么很好的算法。当两个属性的G值一致时,如果它并不能给出一个更好的判断标准。而且如果采用顺序选择很有可能生成一个非最小决策树
。这点还值得研究一下。

这个类是为了给GeneralTree提供Queue队列操作才创建的。

因为GeneralTree使用层次遍历的时候,必须要使用这样一个队列。当然如果你没有这样一个队列,但是你在每个节点那里设置了计数器,那么你还是可以完成一个层
次遍历操作。

这里为了保持GeneralTreeNode的最简单性,所以没有添加计数器属性。

下面是List类的具体代码:

/* * create by chico chen * date: 2009/02/02 / #ifndef LIST_H #define
LIST_H template class ListNode { public: T data; ListNode
next;
ListNode() { next = NULL; } ListNode(T & data) { this->data = data; next =
NULL; } ListNode(T & data, ListNode* next) { this->data = data; this->next
= next; } ~ListNode() { next = NULL; } }; template class List {
private: int length; ListNode* head; public: List() { head = NULL; length =
0; } List(ListNode* head) { this->head = head; length = 1; } ~List() {
ListNode* tempHead = head; while(NULL != head) { tempHead = head->next;
delete head; head = tempHead; } length = 0; } bool IsEmpty() { return 0 ==
length; } // the coral function to insert the node // pre : none // post: no
matter what kind of situation, the function can work. void Insert(ListNode*
node, int index) { if(0 == index) { // insert in the front if(NULL == head) {
head = node; } else { node->next = head; head = node; } } else { if(NULL ==
head) { head = node; } else { if(index >= length || index < 0) { index =
length; } ListNode* temp = head; while(NULL != temp->next && index–) {
temp = temp->next; } temp->next = node; } } length ++; } ListNode*
GetHead() { return this->head; } // pre: list is not empty // post: return the
last element. ListNode* GetTail() { if(NULL == head) { return NULL; }
ListNode* tempHead = head; while(NULL != tempHead->next) { tempHead =
tempHead->next; } return tempHead; } // pre: node is not NULL // post: return
the node’s next node ListNode* GetNext(ListNode* node) { if(NULL !=
node) { return node->next; } } // pre: begin at zero, and the index is less
than the length of the list // post: if index is -1, then return the last //
post: if index is not -1 and less than zer, or bigger than the length, throw
exception. ListNode* GetAt(int index) { ListNode* temp = NULL; if(-1 ==
index) { // get the last temp = GetTail(); } else if(0 <= index && index <
length) { ListNode* tempHead = head; while(tempHead && index–) { tempHead
= tempHead->next; } temp = tempHead; } else { throw “out of list”; } return
temp; } void DeleteHead() { ListNode* tempHead = head; head = head->next;
delete tempHead; this->length–; } // pre: head is not NULL // post: delete
the last one and length subtract 1 void DeleteTail() { if(NULL == head)
return; ListNode* tempTail = head; while(NULL != tempTail->next) { tempTail
= tempTail->next; } delete tempTail; length–; } // pre: head may be not NULL
// post: if index is equal to -1, then delete tail element // post: if index
is equal to 0, then delete the head // post: if it is bigger than the length,
or less than 0, throw exception // post: delete one node at index and length
subtract 1 void DeleteAt(int index) { if(-1 == index) { DeleteTail(); } else
if(0 == index) { DeleteHead(); } else if(0 < index && index < length) {
ListNode* temp = GetAt(index-1); ListNode* dNode = temp->next;
temp->next = dNode->next; delete dNode; length --; } else { throw “out of
List”; } } }; #endif

这个类用于一般树形,每个节点可以有多个分支,且数目不定。

可以看做是二叉树的变形形式。一个节点除了父指针外还有左右两个指针。

左指针为孩子节点的起始指针,右指针为同父节点的兄弟节点的指针

例如:

A的左指针为B,右指针为C,C的左指针为E,右指针为D

则,A,C,D为同兄弟节点。B为A的子节点,E为C的子节点。

这里使用到了 GeneralTreeNode类

这个树没有delete操作。因为我暂时不知道这个树类在什么地方会用到delete操作。而且这个树的查找是O(n),相比与排序二叉树那是慢的太多了。不过这个树
在未知每个节点的分叉个数时,可以使用。其他的地方,个人认为还是尽量使用其他树形。

这个GeneralTree类还要进行大量的改进。

另外因为继承的缘故,这里大量使用dynamic_cast<>()方法。为了将GeneralTreeNode类转变为TreeNode类。这里我暂时还是不知道有
什么好的方法。

另外注意这里的Print函数,必须传入一个函数指针。因为树不知道你的打印数据方法和格式,其实我这里想了很多,最后感觉还是这种方法好点。感觉应该在TreeNo
de类中添加一个virtual Print()函数来负责data的打印工作。

开始的时候,想过使用模板的方法,在TreeNode中添加一个模板参数。后来发现这样做对数据控制不利,而且我要改动非常多的代码,不如直接在GeneralTre
eNode类中添加一个virtual Print()函数,然后传入指针参数去控制打印。

当然这样做的缺点在于如果还有类继承了TreeNode,而且也需要有print data
的方法。那么代码还要改动。但是现在的需求并没有看出这样做的趋势…所以暂时还是在GeneralTreeNode类中添加一个virtual
Print()函数.

具体代码如下:

/* created by chico chen * date 2009/02/02 * 如需转载注明出处 / #ifndef
GENERAL_TREE #define GENERAL_TREE #include #include
#include “GeneralTreeNode.h” #include “BinaryTree.h” #include “List.h” using
namespace std; // this tree can not accept the same value. No element is the
same! // The class is not finished, and I am thinking where the class should
be used. // And there is no delete operator. template class
GeneralTree: public BinaryTree { private : GeneralTreeNode

GetTail(GeneralTreeNode* head) { // only the right piont can be used!
if(head != NULL) { while(head->right != NULL) { head =
(GeneralTreeNode)head->right; } } else { throw “head is null!”; } return
head; } // pre: parent != NULL and index is bigger than or equal with 0
GeneralTreeNode
GetAChild(GeneralTreeNode* parent,int index) {
assert(index>=0); assert(parent!=NULL); GeneralTreeNode* head =
dynamic_cast<GeneralTreeNode>(parent->left); assert(head != NULL);
while(head->right != NULL && index–) { head =
dynamic_cast<GeneralTreeNode
>(head->right); } if(NULL == head->right &&
index > 0) { throw “index is over float!”; } return head; } // this is deep
print(深度遍历) void DeepPrint(GeneralTreeNode* subRoot) { if(NULL != subRoot)
{ cout << subRoot->getData()<<" "<<endl;
DeepPrint(dynamic_cast<GeneralTreeNode>(subRoot->getLeft()));
DeepPrint(dynamic_cast<GeneralTreeNode
>(subRoot->getRight())); } } // this
is level print(层次遍历) void LevelPrint(GeneralTreeNode* subRoot,void
(print)(T& data)) { List<GeneralTreeNode> queue; queue.Insert(new
ListNode<GeneralTreeNode>(subRoot),-1); while(!queue.IsEmpty()) {
ListNode<GeneralTreeNode
>* temp = queue.GetHead(); GeneralTreeNode*
tempNode = temp->data; tempNode->Print(print); for(int i = 0; i <
tempNode->childLength; i++) { GeneralTreeNode* tempChildNode =
GetAChild(tempNode,i); queue.Insert(new ListNode<GeneralTreeNode*

(tempChildNode),-1); } queue.DeleteHead(); } } // pre: node != NULL // post:
true iff node is in the Tree, false iff node isn’t in the tree bool
Search(GeneralTreeNode* subRoot,GeneralTreeNode* node) { if(subRoot ==
NULL) { return false; } else if(node == subRoot) { return true; } else { bool
a = Search((GeneralTreeNode)subRoot->getLeft(),node); bool b =
Search((GeneralTreeNode
)subRoot->getRight(),node); return a||b; } }
public: GeneralTree():BinaryTree() { this->root = NULL; } GeneralTree(T&
data):BinaryTree(data) { this->root->parent = NULL; } virtual ~GeneralTree() {
} // this function will call Insert (GeneralTreeNode* node,
GeneralTreeNode * parent) // and it will find the point of parentData. //
So it means if there are the same T in two node, it will return the first
node. //void Insert(T & dataCurrent, T & parentData) //{ //} // pre: node is
not in the tree. void Insert(GeneralTreeNode* node, GeneralTreeNode *
parent) { if(parent == NULL&& root == NULL) { // this is root root = node;
return; } if(root == NULL) { throw “no parent!”; } bool isFind =
Search(dynamic_cast<GeneralTreeNode>(root),parent); if(!isFind) { throw
“no such parent node!”; } isFind =
Search(dynamic_cast<GeneralTreeNode
>(root),node); if(isFind) { throw
“there is the same node in the tree!”; } if(parent->left == NULL) {
parent->left = node; } else { GeneralTreeNode* tail =
GetTail((GeneralTreeNode)parent->left); tail->right = node; } node->parent
= parent; parent->childLength ++; } // this is deep print(深度遍历) void
DeepPrint() { DeepPrint(dynamic_cast<GeneralTreeNode
>(this->root)); } //
this is level print(层次遍历) void LevelPrint(void (print)(T& data)) {
LevelPrint(dynamic_cast<GeneralTreeNode
>(this->root),print); } }; #endif

这里可能还需要一个 List.h

文件,大家可以使用stl中的代替,也可以自己写,也可以使用我的…

写这个类是配合GeneralTree这个类的。

这个类使用TreeNode基类继承而来。这里有一点要说明的。为了编程的方便,这里TreeNode中的成员属性均设置为Public

当然,如果有需求一遍写为protected。当然我这里是为了自娱自乐…所以没有在意太多。

TreeNode头文件详见 http://blog.csdn.net/cctt_1/archive/2008/08/19/2794469.aspx

这个Node其实是二叉树的一种变形形式。它含有一个父指针,和一个孩子个数计数器。

#ifndef GENERALTREENODE_H #define GENERALTREENODE_H #include “TreeNode.h”
template class GeneralTreeNode : public TreeNode { public : int
childLength; // how many children does the node have GeneralTreeNode*
parent;// the parent point of the node public: GeneralTreeNode(T &
data):TreeNode(data) { childLength = 0; parent = NULL; } GeneralTreeNode(T&
data, TreeNode* left, TreeNode* right, TreeNode* parent)
:TreeNode(data,left,right) { childLength = 0; parent = parent; }
GeneralTreeNode(GeneralTreeNode* a):TreeNode(a->data,a->left,a->right) {
childLength = a->childLength; parent = a->parent; } // to print the data
virtual void Print(void (*print)(T& data)) { print(data); } virtual
~GeneralTreeNode() { childLength = 0; parent = NULL; } };

查找它的各个孩子的任务交给了GeneralTree类来做,它的职能就是记录孩子节点的个数,并快速的查找到它的父节点可能上面那个网页的TreeNode.h文件
由于以前是直接贴代码到CSDN上,所以可能现在不适合拷贝。

所以将TreeNode.h的代码在贴到下方:

/* * create by chico chen * date: 2009/02/02 / #ifndef TREENODE_H #define
TREENODE_H template class TreeNode { public: T data; TreeNode *
left; TreeNode * right; public: TreeNode(T& data) { this->data = data;
this->left = NULL; this->right = NULL; } TreeNode(T& data,TreeNode
left,
TreeNode* right) { this->data = data; this->left = left; this->right =
right; } virtual ~TreeNode() { // cout << “node (”<data<<“)
destory!”<<endl; // to do } T& getData() { return data; } void setData(T&
data) { this->data = data; } TreeNode * getLeft() { return left; } void
setLeft(TreeNode * left) { this->left = left; } TreeNode * getRight() {
return right; } void setRight(TreeNode* right) { this->right = right; } };
#endif

从我用计算机开始,算来一共装过两三次系统。一直以来靠备份还原度日。终于最近不行了。蜗牛没有备份资料,只好重装,开始的时候只是在清理各种软件,然后使用PQ
Magic分区。然后PQ提示重启…结果就发生了boot.ini
missing。因为多年没有装机,所以没有把安装盘带回家,只好现在网上下,然后再刻录为光盘。结果nero的刻录软件老是出问题,不能识别或者说burn
error还有buffer error错误,害我损失了n张盘。那后拿到蜗牛上去试,结果蜗牛死活不认,一直boot cd failure。想哭呀…不知道是不
是蜗牛的那个光驱不认,还是刻录的盘不能启动。因为有张linux的盘,蜗牛是承认的,就是慢死在安装上。后来还是找到了新光驱,然后换下了蜗牛的光驱。那几个启动盘
都能使用,也不用看网上的教程如果做一个启动盘,其实就是光驱的问题。装了Windows xp分了两个区,希望一个装Unix,然后再使用FreeBSD的安装盘。
这里犯下一个错误,就是不能使用windows可以识别的分区来装Unix,一定要把要装分区的标识去掉才行。否则你装FreeBSD时要不出现cannot
write hd0 ,要不即使装好了,并且装了boot Mgr,可是你启动windows时,一定会出现ntldr is missing
错误.然后使用网络上的那个教程也没有用。

网络教程是: http://www.computerhope.com/issues/ch000465.htm

。所有的办法用尽,还是选择重装。然后去掉d盘符。装上了FreeBSD。不过FreeBSD画面.的确不咋地…

然后出问题的就是我的土狗,这家伙怎么都不能联网。开始的时候,如果你开机的时候插着网线,那么可以上网。你中途拔下网线,它便死活不认。有时显示连接上,但是发出的
包和接受的包都是0.也想卸载网卡,结果每次卸载都卡在那里。网络连接停用和修复有时也会卡在那里。最后连关机都关不上。不知道为啥,土狗特给我老爸面子。卸载驱动,
一下就成功。我看着真是无语。看来人品真的很重要。

或许人生要自己把握才能叫做人生。

不管结果如何,总是自己做的决定。想起了教父的那句话:“不管对错,一定是我做的决定!”

在7楼的日子。没有目标,每天只不过是为了活下去。不知道自己的目的地,不知道生为何,死为何。

有天终于可以脱离,去想去的地方,成就自己的“梦想”,掌握自己的生死.

或许我们活得很简单:看到大海,走到目标,穿上喜欢的衣服,体味到生的乐趣。

博弈
如果有最佳策略,则对手一定采用那个最佳策略。自己要根据那个最佳策略相应而行。但是有一点要谨记:
那就是对手是从哪个角度考虑他的最佳策略的。如果是从短期的预算,还是想击垮某个竞争对手?
如果你有一个优势策略,那么就选择你的优势策略,不用担心对方。对方一定照办。优势策略不意味着你的策略产生的最差结果比其他
策略要好。(这是同时行动是才采用的)

追求最佳,避免最差

博弈是中纳什均衡不代表有利还是没有利。得利不得利是另外一套体系。博弈均衡是指产生了一个稳定的结果。
纳什均衡:在对方确定策略里,自己的是最好的。所以没有人会改变策略。
有几率策略来制定相应的策略。
纯策略是参与者一次性选取的,并且坚持他选取的策略;而混合策略是参与者在各种备选策略中采取随机方式选取的。
在博弈中,参与者可以改变他的策略,而使得他的策略选取满足一定的概率。
启示1:没有把真正的问题找出来就盲目采取行动,是最愚蠢的做法。能够找出问题,已经可以说是把问题解决一半了。
启示2:解决问题的公式:
(1)找出问题发生的原因;
(2)分辨情报的价值;
(3)彻底推行解决方案;
(4)观察事情进行得是否顺利。
任何事情都看似很难,实质不难;任何事情都比你预期的更令人满意;任何事情都能办好,而且是在最佳的时刻办好——麦可斯韦尔定

律有助你走出阴霾。
如果未来是重要的话,就不存在最佳的策略。一报还一报的规则。不首先背叛。希望坚持引出不背叛的好处。
在持续的囚徒困境中如何表现:
1.不要嫉妒。
不要把对方的成功和自己的成功对立起来
2.不要首先背叛
3.对合作与背叛都给予回报(惩罚和宽恕的公平)
4.不要耍小聪明(不要用复杂的规则进行推断,不要永久报复)
5.一报还一报从来没有在游戏中赢得更高的分数。

启示:两只困倦的刺猬由于寒冷而拥在一起。可因为各自身上都长着刺,于是它们离开了一段距离,
但又冷得受不了,于是凑到一起。几经折腾,两只刺猬终于找到一个合适的距离:既能互相获得对方的温暖而又不至于被扎。
了解并关心对方,并巧妙地保护自己,会使合作更加长久。
长期建立合作关系。如果背叛的惩罚非常大,那么即使短期的合作也最优策略
只要双方的长期合作激励大于背叛的短期激励即可。
不可以无条件合作,这样会宠坏对方。
未战而庙算胜者,得算多也
人数的平方代表军力,军力多为胜多。
分散敌军,各个击破。
合则两利,分则两害。
同样的兵力守则不足,攻则有余
形人而我无形
兵闻速拙,未睹巧久。夫兵久而国利者,未之有也。故不尽知用兵之害者,则不能尽知用兵之利也。
成本就是为了得到某种东西而必须放弃的东西。
你支付的成本越大,局面就越不利。
围棋中不将棋走重,效率低,而且包袱重。
最好不要迈出第一步,除非你清楚的知道自己去哪里。
认识自己,正确选择,这是最重要的。
保留选择余地总归是有好处的。
计划好的行动路线以及使这一路线显得可信的承诺。
一个无条件的行动(不计代价、只要胜利)可以使这个参与者获得策略上的优势,抢占先机,率先出招。
回应规则:许诺和威胁。

经济活动要善于从已有的认知模式中跳出来。要有足够的学习能力——即探索未知领域的能力。
两只手表并不能告诉你更准确的时间,只会让你在两种不同的时间面前茫然无措。你要做的就是选择其中较可信赖的一只,尽力校准它,并

以此作为你的标准,听从它的指导行事。
如果你想过得幸运一些,你必须只采用一种判断准则而不要贪多,这样你会活得更容易些。–尼采
一个经济社会,要尽量做到信息是对称的。
为什么知情权如此重要?就是因为信息的传播有利于人们在掌握信息之后,通过理性选择,作出正确决定。这对社会和个人都有好处。
民可使由之,不可使知之。
所谓专家,就是周旋于三宫六院间的太监,无所不知,却无能为力。
别在自己不熟悉的领域发言。
根据迹象预见到危险的人,能够避开危险。
有四样东西一去不复返:说过的话、泼出去的水、虚度的年华和错过的机会。
岂能尽如人意?但求无愧我心。
上苍赋予人类的许多宝贵礼物中,“选择的权利”就是其中的一个。
边际效用递减原理说的是:第一个东西带给他的最好,第二个就其次…
运气仅仅是你最喜欢的状态而已
(1)世界上本来就有很多潜在的稀罕事,你肯定会经历其中的一些。
(2)有些事情看起来稀奇,实际上并不是。比如,在24个任意选择的人们中发现两个生日(月和日)一样的人的概率有多大?答案是超过50%!
如果对手知道得比你多,千万别赌。
谁也不满足于自己的财产,谁都满足于自己的聪明。——托尔斯泰
炒股是一种冤大头游戏。
人往往是这样,到手的东西总不那么叫人满意。但是知道“适可而止”总不是坏事。
破窗理论的谬误原本不知道资源是短缺的。因为这里并没有增长财富。而是消耗了财富。
经济学建立在两个假设前提上:其一,人是自私的,都在追求利益的最大化;
其二,人是理性的,其所有行为都是为了实现追求利益最大化这个目的。
任何时候,只要可能,我们必须做最有成效的事情。
所谓“此一时,彼一时”,当时做的认为正确的决定,不一定事后认为也正确。不过不要后悔了,既然已经做了,那就坚持自己的决定。
有冒险而成功的将领,没有无备而胜利的军队。在不曾达到目的以前,尽可能保存好每一个铜板,尽可能不被眼前的事物牵绊,这是成功的

必备条件,因为前面的路说不定很长。
民主投票往往不民主
一方能否获胜,不仅仅取决于他的实力,更取决于实力对比造成的复杂关系。
才华出众者创造历史;碌碌无为者繁衍子孙。
三党的政策是不稳定的
我们不是因一贯正确而获得权威,而是因获得了权威而一贯正确。
怎样才能把权力交到有能力的人手中,交到善良人的手中。这个问题不能解决,一切都无从做起。然而,现在已经没有好的方法。
情侣博弈无法使用纳什均衡
帕累托效率表明:如果可以改善自己而不损耗他人利益,那说明资源还没有得到充分利用。否则定会改善自己损害他人。
从某种层度而言:GDP是对自然破坏的指标。
根据纳什均衡,可能等不到宇宙灾难的那天,人类就已经自己把自己灭掉了。

故此,尔等须知晓自身宿命,故此,尔等须把稳船只……置欲求于动机之后,尔须奋力以搏。
故此,且容好奇心为尔等指南。追寻天上真理,如同在大地寻觅。
所不敢为者,为之;所不敢至者,往之。
道路千万条,宜选阳光道。聪明择路,正派为人,公平行事。
故此,尔须多有智识,勤于创造。
——《爱因斯坦的圣经》

好多人失败,不是因为他们傻,而是太聪明。
一个聪明人的麻烦是他总希望比别人多得一些,或者说,他总面临这样做的诱惑。
要不要与人合作?利益如何分配?它会不会得罪某些人?等等。你不得不考虑它们,因为这些问题确实存在。这样你就不得不花费大量的精

力和智慧去处理它们,而这些花费对你本来想做的那件事并无多大益处。也就是说,它们大大提高了你做事的成本。这种多余的花费似乎是

我们的宿命。
不要把赢作为惟一目标,也不要总是追求最好结果。
你不可能永远控制局面,也不必永远控制局面,人类最理智的时候,往往是别无选择的时候。
即使是全然理性的决策也可能是错的,反之亦然。
无论你想做什么,不管是赌博、运动、投资股市、择偶,甚或发动战争,之前你最好弄清楚自己在做什么。
合作与双赢并不意味着完全的公平。所有好的策略,都不过是在公平与效率之间找平衡。
团体决策基本上比个人决策更难保持理性,在团体决策过程中有很大的操弄和使诈的空间。
至今仍找不到令人满意的方法,能在不产生不良结果的情形下,同时顺利地把各人偏好转换成团体偏好。阿罗不可能原理告诉我们:任何制

度都有缺陷,而最好的制度就是造成损害最少的制度。内耗不可避免,明智的人把内耗控制在可接受的限度内。据此推论,“若每个人的行

为都以理性的自利为出发点,则其结果仍会对社会有利”,这个乐观想法仍旧是个误区。更不幸的是,它反而掩饰了无知自利的影响。再以

此推论,至今人类仍未发明出一种政府形态,完全令人满意、可以作出造福社会的团体决策。我们真的不知道该往何处去,所以要常怀谦逊

之心。

有时我想知道怎样设计容器类才是合理的。

是让用户自己new一个新的对象在放入容器类,还是我隐式的new一个新的对象?

这就带来一些问题。如果我隐式为新的对象建立容器类,那么很有可能我以后不好释放。因为对于object来说,是不能使用delete。并且每次都new也带来不小的
时间损耗。

最简单的方式是不为用户new出新的对象,不delete容器类中的对象。

那么假如粗心的用户new出来新的指针并放入容器中…那么用户只好清除的时候先清除容器内的每个对象,然后再delete容器。

这样看起来不错。好像也只能这样做。

有三个门,两个羊一个车。嘉宾选择一个门后,主持人打开另外两个门中的一个,门里是羊。嘉宾改选或者不改选。门后有车就中大奖。否则什么都没有。

记得当年做这个题目的时候就与小李子和疯子争论的不休。

当时时至今日仍然不能完全确定这是个概率问题。

其实这个不完全是概率问题

因为概率中只是考虑了出现结果的可能性。但是这个问题却考虑出现结果的好坏。

换而言之,就是在这个事件中。它是一个不可重复的事情。你甚至可以考虑到主持人的心理在做决策。

所以它不是一般意义上的概率问题。

因为主持人的心理对这个事件有着非常重大的影响。如果主持人随机选择一个门并打开,并且里面是羊。那么你改选或者不改选你的概率都是1/2。如果主持人要指定打开一个
羊的门,那么你改选选中车的概率就是2/3.如果这个老兄和主持人是熟人,其实可以通过这点信息交互就能断定哪个是车的门。

有一个同样的例子:三个囚徒,其中两个是要被释放的。囚徒A与看守很熟,但是不能直接打听自己是否会被释放。另外两个中肯定有一个会被释放。那么是否打听过那两个中的
一个释放名字。会影响自己的释放的概率呢?

当然不会,这点谁都能理解。但是囚徒A竟然改变了另两个囚徒选中概率。其实…我觉得也是不可能。一个不被释放概率变为0,另外一个变为2/3.这样囚徒A会不会因为
得到这条消息“另外两个中的一个人被释放了”,而非常开心呢?(傻瓜才会开心!)

那么说来,如果我们有很多奖项等待颁发(抽奖的形式)。那么你应该听到别人的名字而感到开心。因为你不久就会中奖了。但是如果刚才的情况是两个囚徒同时知道另外一个人
可以被释放。那么难道两个囚徒不被释放的概率都是2/3吗,难道不应该是1/2?按照刚才那个选车选羊的问题给出的结论。那的确都是2/3.所以我一直不认为这个是个
概率的问题。因为这是个博弈问题。

如果主持人是相当狡猾的。他的任何选择都没有给带来任何信息。那么你的选择其实刚刚从打开羊门的一霎那才开始。

但是不管怎么说,你改变你过去的选择在概率上对你来说是百利而无一害。因为不管怎样你选择另外一个门的概率比你坚守一个门的概率要么相等,要么高出一倍。

所以最优策略就是改选。

when you stuck your head, relax, turn and pull. 有时候做人做事要转换一下方式,否则还是会卡住头。

Because all around the planet, there are animals who feel like they cannot,
like a little hamster, who once spends his day in the vehicle park dreaming
the day when he, too, save the little girl from danger and be told, “you did!
you did, rhino. You saved the day.” They need a hero, bolt. Someone no matter
what they are or do what is right. They need a hero to tell them that,
sometimes, impossible can become possible, if you are awesome!

我们时常需要一种精神的力量。这或许是人人都喜欢超人的缘故。我们需要一种非凡的勇气去面对这个充满未知艰险的世界。如果有这样一个“超人”告诉我们,前面有路可以到
达目的地,但是只是有些难走。我们就会以为自己误入了迷途。如果说做学问需要老师,大抵如此。可是现实生活中,谁是老师,谁有是那个超人呢?但凡伟人,不过是凡人。

歌词不错,记录如下

I have got so much to give
I swear I do
I may not have nine lives
this one feel brand new
Yes, I’ve lived a good one
I’ve tried to be true
There are something I never realized
Till I met you
How the wind feels on my cheeks
When I barking at the moon

There is no home like the one you’ve got
cause the home belong to you
huuu~ Here I come
Huuu~ back to you
There is no home like the one you’ve got
cause the home belong to you

when I was in trouble bad
I was so confused
I may not see in color, baby
But I sure can feel blue
I have been a lot of things
They may not all be true
My experience was so mysterious
Till I met you
Now the sun will rise in the east
But I barking at the moon

There is no home like the one you’ve got
cause the home belong to you
huuu~ Here I come
Huuu~ back to you
There is no home like the one you’ve got
cause the home belong to you
they act they love you,
they act they will be there for ever,
Then one day,  they packed all stuff things, and moved away, and take their
love with them!
And leave their pet defending herself.
They leave her, wondering what she did wrong.
cat说的话,这世界总有些人。如同演戏一样,当曲终人散,离你而去。

当然也总有人,they are different!

The hero must go to face their chanllege alone.

当个Hero太痛苦了。独自面对挑战,总有些挑战是要自己去面对的。但是其他的挑战就一起去面对吧。

But if bolt have told me anything, that is never abandon a friend at time you
need.
When your teammate is in the trouble, you go.
No matter they asked or not, you go.
knowing you come back dead or alive, you go.
When you know the struggle and then present in your mind, you go.

仓鼠的话为啥都是自理名言呢?可爱的小东西。团队中最重要的是相互帮助。为了完成最终的目标,首先要帮助的是成员。如果每个成员都成功的完成了任务,那你的团队还没有
成功吗?

Is that dog looks familiar?
No, I never see him before my life.

哈哈,人不要太自信,不要太自大。即使是明星,也不一定每个人都认识你。所以每个人都只是凡人,只是小人物。

相信张艺谋、刘德华的名字在某些地方还是未被听到。

![bolt](http://p.blog.csdn.net/images/p_blog_csdn_net/cctt_1/EntryImages/20090
120/000.jpg)

译  名 闪电狗/明星狗/霹雳战狗
◎片  名 Bolt
◎年  代 2008
◎国  家 美国
◎类  别 动画/喜剧/家庭/幻想
◎语  言 英语
◎字  幕 N/A
◎IMDB评分 7.7/10 5,879 votes
◎IMDB链接 http://www.imdb.com/title/tt0397892

◎文件格式 XviD + MP3
◎视频尺寸 640 x 336
◎文件大小 1CD 51 x 15MB
◎片  长 103min
◎导  演 克里斯·威廉姆斯 Chris Williams
Byron Howard
◎主  演 约翰·特拉沃塔 John Travolta
麦莉·赛勒斯 Miley Cyrus
马尔科姆·麦克道威尔 Malcolm McDowell
Nick Swardson …(voice)
戴德里克·巴德 Diedrich Bader
科洛·莫瑞兹 Chloe Moretz
Greg Germann …(voice)
J.P. Manoux …(voice)
Susie Essman …Mittens (voice)
Ronn Moss …(voice)
James Lipton …(voice)
Randy Savage …(voice)
Mark Walton …Rhino (voice)
Sean Donnellan …Penny’s Dad

0%