目录
完整代码(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;
/*求左右孩子结点值---传参x和表示空的flag*/
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{ seqStack
s; 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{//非递归中序 /*由于要记录出栈次数,所以引入结构elem*/ if(root==NULL) return; struct elem{ node* cur; int time; elem(node* p=NULL):cur(p),time(0){ }//构造函数 }; cout<<"非递归中序遍历:"; //初始化---装有elem的栈和elem变量 seqStack
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< 注意:elem(tmp.cur->lchild)-----是elem类型,没有指定变量名,类似临时变量
注意:如果出栈过一次,那么time+1,而且在访问左结点,一定要:再进栈push一次
void postTraverse() const{//非递归后序 /*由于要记录出栈次数,所以引入结构elem*/ if(root==NULL) return; struct elem{ node* cur; int time; elem(node* p=NULL):cur(p),time(0){ }//构造函数 }; cout<<"非递归后序遍历:"; //初始化---装有elem的栈和elem变量 seqStack
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)); } } } } 与中序区别只在:
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;
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)