目录
完整代码(binTree.h)
主函数测试
非递归的前中后遍历
前序实现:
中序
后序
完整代码(binTree.h)
#include"seqQueue.h" #include主函数测试#include using namespace std; template class binTree{ friend void printTree(const binTree & t,T flag){ //由于要输出值,所以队列存值 //为了检验函数功能,直接调用已实现函数 if(t.root==NULL) return; seqQueue s; s.enQueue(t.root->data);//值 T tmp,lc,rc; while(!s.is_empty()){ tmp=s.deQueue(); //调用左右孩子 lc=t.lchild(tmp,flag); rc=t.rchild(tmp,flag); cout<<"("< data==x) return t; tmp=find(x,t->lchild); if(tmp) return tmp; else return find(x,t->rchild); } public: binTree(){ root=NULL;} void createTree(T flag);//用flag表示空结点 void levelTraverse() const;//层次遍历 void preTraverse() const; void midTraverse() const; void postTraverse() const; int nodeSize() const; int treeHigh() const; T lchild(T x,T flag) const; T rchild(T x,T flag) const; //清空+剪枝 void clear(); void defLeft(T x); void defRight(T x); }; //创建树+层次遍历 template void binTree ::createTree(T flag){ seqQueue s;//创建装有结点指针的队列 //输入根节点并入队 T x; cout<<"输入根节点:"; cin>>x; s.enQueue(root=new node(x)); //访问结点,并将非空左右孩子入队 node* tmp; T ldata,rdata; while(!s.is_empty()){ tmp=s.deQueue(); cout<<"输入结点"< data<<"的左右孩子:"; cin>>ldata>>rdata; if(ldata!=flag) s.enQueue(tmp->lchild=new node(ldata)); if(rdata!=flag) s.enQueue(tmp->rchild=new node(rdata)); } cout<<"create successful!n"; } template void binTree ::levelTraverse() const{ cout<<"n层次遍历:"; if(root==NULL) return; seqQueue s; s.enQueue(root); while(!s.is_empty()){ node* tmp=s.deQueue(); cout< data<<" ";//输出 if(tmp->lchild) s.enQueue(tmp->lchild); if(tmp->rchild) s.enQueue(tmp->rchild); } } //递归实现前中后序遍历 template void binTree ::preTraverse(node* t) const{ if(t==NULL) return; cout< data<<" "; preTraverse(t->lchild); preTraverse(t->rchild); } template void binTree ::preTraverse() const{ cout<<"n前序遍历:"; preTraverse(root); } template void binTree ::midTraverse(node* t) const{ if(t==NULL) return; midTraverse(t->lchild); cout< data<<" "; midTraverse(t->rchild); } template void binTree ::midTraverse() const{ cout<<"n中序遍历:"; midTraverse(root); } template void binTree ::postTraverse(node* t) const{ if(t==NULL) return; postTraverse(t->lchild); postTraverse(t->rchild); cout< data<<" "; } template void binTree ::postTraverse() const{ cout<<"n后序遍历:"; postTraverse(root); } //求结点数+树高 template int binTree ::nodeSize(node* t) const{ if(t==NULL) return 0; //结点数=根+左子树+右子树 else return nodeSize(t->lchild)+nodeSize(t->rchild)+1; } template int binTree ::nodeSize() const{ return nodeSize(root); } template int binTree ::treeHigh(node* t) const{ if(t==NULL) return 0; int L,R; L=treeHigh(t->lchild); R=treeHigh(t->rchild); return 1+(L>R?L:R);//根+max(左子树高度,右子树高度) } template int binTree ::treeHigh() const{ return treeHigh(root); } //求左右孩子 template T binTree ::lchild(T x,T flag) const{ node* tmp=find(x,root); if(tmp==NULL||tmp->lchild==NULL) return flag; else return tmp->lchild->data; } template T binTree ::rchild(T x,T flag) const{ node* tmp=find(x,root); if(tmp==NULL||tmp->rchild==NULL) return flag; else return tmp->rchild->data; } //清空+剪枝 template void binTree ::clear(node* &t){ if(t==NULL) return; clear(t->lchild); clear(t->rchild); delete t; t=NULL;//把根节点置空 } template void binTree ::clear(){ clear(root); } template void binTree ::defLeft(T x){ node* tmp=find(x,root); if(tmp==NULL) return; clear(tmp->lchild); } template void binTree ::defRight(T x){ node* tmp=find(x,root); if(tmp==NULL) return; clear(tmp->rchild); }
#include"binTree.h" #include#include using namespace std; int main(){ binTree bt; bt.createTree('#'); printTree(bt,'#'); cout< 非递归的前中后遍历
引入栈文件----stack.h
template前序实现:class seqStack{ private: elemType* data; int maxsize; int top_s; void doublespace();//扩容 public: //构造+析构 seqStack(int initszie=10){ data=new elemType[initszie]; maxsize=initszie; top_s=-1; } ~seqStack(){ delete[] data;} //函数操作 bool is_empty() const{ return top_s==-1;} elemType top() const{ return data[top_s];} elemType pop(){ return data[top_s--]; } void push(const elemType& x){ data[++top_s]=x; } }; //扩容 template void seqStack ::doublespace(){ elemType* tmp; maxsize*=2; data=new elemType[maxsize]; for(int i=0;i<=top_s;i++){ data[i]=tmp[i]; } delete[] tmp; } 中序void preTraverse() const{ seqStacks; if(root==NULL) return; cout<<"前序遍历:"; s.push(root); node* tmp; while(!s.is_empty()){ tmp=s.pop(); cout< data<<" "; //由于栈后进先出,一定要先右后左 if(tmp->rchild) s.push(tmp->rchild); if(tmp->lchild) s.push(tmp->lchild); } } 比较简单,类似层次遍历,只是一定要先右孩子进栈,然后左孩子进栈
后序void midTraverse() const{//非递归中序 if(root==NULL) return; struct elem{ node* cur; int time; elem(node* p=NULL):cur(p),time(0){ }//构造函数 }; cout<<"非递归中序遍历:"; //初始化---装有elem的栈和elem变量 seqStacks; elem bt(root); s.push(bt); elem tmp;//记录出栈 while(!s.is_empty()){ tmp=s.pop(); if(tmp.time==1){ //表明已经出栈过一次了,也就是左结点访问结束 cout< data<<" "; //接下来访问右孩子节点 if(tmp.cur->rchild) s.push(tmp.cur->rchild); } else{ tmp.time+=1; s.push(tmp);//自己是第一次访问,入栈,time+1 //左孩子进栈 if(tmp.cur->lchild) s.push(tmp.cur->lchild); } } cout< 注意:elem(tmp.cur->lchild)-----是elem类型,没有指定变量名,类似临时变量
注意:如果出栈过一次,那么time+1,而且在访问左结点,一定要:再进栈push一次
void postTraverse() const{//非递归后序 if(root==NULL) return; struct elem{ node* cur; int time; elem(node* p=NULL):cur(p),time(0){ }//构造函数 }; cout<<"非递归后序遍历:"; //初始化---装有elem的栈和elem变量 seqStacks; elem bt(root); s.push(bt); elem tmp;//记录出栈 //以上和中序遍历代码一致 while(!s.is_empty()){ tmp=s.pop(); if(tmp.time==2){ //已访问两次,也就是左右孩子都遍历了,输出结果 cout< data<<" "; } else{ if(tmp.time==1){ //左孩子已访问,右孩子进栈 tmp.time+=1; s.push(tmp);//一定别忘了,右孩子进栈时,自己再进一次栈 if(tmp.cur->rchild) s.push(elem(tmp.cur->rchild));//注意类型 } else{ tmp.time+=1; s.push(tmp);//自己进栈,然后遍历左孩子 if(tmp.cur->lchild) s.push(elem(tmp.cur->lchild)); } } } } 与中序区别只在:
while(!s.is_empty()){
//区别
}
if(tmp.time==2){ //已访问两次,也就是左右孩子都遍历了,输出结果 cout<data<<" "; } else{ if(tmp.time==1){ //左孩子已访问,右孩子进栈 tmp.time+=1; s.push(tmp);//一定别忘了,右孩子进栈时,自己再进一次栈 if(tmp.cur->rchild) s.push(elem(tmp.cur->rchild));//注意类型 } else{ tmp.time+=1; s.push(tmp);//自己进栈,然后遍历左孩子 if(tmp.cur->lchild) s.push(elem(tmp.cur->lchild)); } } 注意这个根左右过程:
if 访问根
else if 第一次---左孩子
else 第二次---右孩子
完整程序
#include#include"seqStack.h" #include using namespace std; template class binTree{ private: struct node{ T data; node *lchild,*rchild; node():lchild(NULL),rchild(NULL){} node(const T& x,node* p=NULL,node* q=NULL):data(x),lchild(p),rchild(q){} ~node(){} }; node* root; public: binTree(){ root=NULL;} void createTree();//静态初始化树 void preTraverse() const{//非递归前序 if(root==NULL) return; cout<<"非递归前序遍历:"; //将根节点入栈 seqStack s;//栈的元素类型是--node* s.push(root); node* tmp;//记录出栈元素 while(!s.is_empty()){ tmp=s.pop();//栈顶元素出栈 cout< data<<" ";//前序遍历--先访问根 //由于栈的后进先出,右孩子先于左孩子进栈 if(tmp->rchild) s.push(tmp->rchild); if(tmp->lchild) s.push(tmp->lchild); } cout< s; elem bt(root); s.push(bt); elem tmp;//记录出栈 while(!s.is_empty()){ tmp=s.pop(); if(tmp.time==1){ //表明已经出栈过一次了,也就是左结点访问结束 cout< data<<" "; //接下来访问右孩子节点 if(tmp.cur->rchild) s.push(tmp.cur->rchild); } else{ tmp.time+=1; s.push(tmp);//自己是第一次访问,入栈,time+1 //左孩子进栈 if(tmp.cur->lchild) s.push(tmp.cur->lchild); } } cout< s; elem bt(root); s.push(bt); elem tmp;//记录出栈 //以上和中序遍历代码一致 while(!s.is_empty()){ tmp=s.pop(); if(tmp.time==2){ //已访问两次,也就是左右孩子都遍历了,输出结果 cout< data<<" "; } else{ if(tmp.time==1){ //左孩子已访问,右孩子进栈 tmp.time+=1; s.push(tmp);//一定别忘了,右孩子进栈时,自己再进一次栈 if(tmp.cur->rchild) s.push(elem(tmp.cur->rchild));//注意类型 } else{ tmp.time+=1; s.push(tmp);//自己进栈,然后遍历左孩子 if(tmp.cur->lchild) s.push(elem(tmp.cur->lchild)); } } } } }; template void binTree ::createTree(){ node* f=new node('f'); node* g=new node('g'); node* k=new node('k'); node* h=new node('h'); node* e=new node('e',f,g); node* j=new node('j',NULL,k); node* d=new node('d',NULL,e); node* i=new node('i',j,NULL); node* b=new node('b',d,NULL); node* c=new node('c',h,i); root=new node('a',b,c); } 测试主函数
int main(){
binTree
bt; bt.createTree();
bt.preTraverse();
bt.midTraverse();
bt.postTraverse();
return 0;
}



