二叉树先序、中序、后序遍历算法的实现
2015-08-11 16:49
531 查看
二叉树每个结点至多只有两颗子树,并且子树有左右之分。二叉树的遍历是二叉树的一项重要操作。二叉树的每一棵子树都还是一棵二叉树,因为此特性在实现二叉树的遍历的时候可以分为递归遍历和非递归遍历。
二叉树的递归遍历的实现:
二叉树非递归遍历的实现:
层次遍历:即从上到下从左到右依次遍历。层次遍历中需要用到queue进行操作,C++的queue文件中提供了其相关的操作。
对于二叉树除了比较重要的遍历操作外,统计二叉树叶子结点的个数、求二叉树的深度、宽度、将二叉树的左右子树进行相互交换都是一些重要的操作。
测试程序:
最后的实验结果:
![](https://img-blog.csdn.net/20150811164727556)
对程序的输入进行说明:通过先序遍历的方式创建二叉树,#表示其相应的子树为空。
二叉树的递归遍历的实现:
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <stack> #include <queue> #define OK 1 #define ERROR 0 #define OVERFLOW 1 using namespace std; int i=0; typedef struct BiTNode { char data; struct BiTNode *lchild, *rchild; }BiTNode,BiTree; //先序遍历创建树 int CreateBiTree(BiTree *&T) { char ch; ch = getchar(); if( ch == '#') { T = NULL; } else { T = (BiTNode *)malloc(sizeof(BiTNode)); if(!T) exit(OVERFLOW); T->data = ch; CreateBiTree(T->lchild); CreateBiTree(T->rchild); } return OK; } void PreOrderBiTree(BiTree *T)//递归先序遍历 { if(T != NULL) { cout<<T->data; PreOrderBiTree(T->lchild); PreOrderBiTree(T->rchild); } } void InOrderBiTree(BiTree *T)//递归中序遍历 { if(T) { InOrderBiTree(T->lchild); cout<<T->data; InOrderBiTree(T->rchild); } } void PostOrderBiTree(BiTree *T)//递归后序遍历 { if(T) { PostOrderBiTree(T->lchild); PostOrderBiTree(T->rchild); cout<<T->data; } }
二叉树非递归遍历的实现:
void PreOrder2(BiTree *T) //非递归前序遍历 { stack<BiTree*> s; BiTree *p = T; while(p!=NULL||!s.empty()) { while(p!=NULL) { cout<<p->data; s.push(p); p=p->lchild; } if(!s.empty()) { p=s.top(); s.pop(); p=p->rchild; } } } void InOrder2(BiTree *T)//非递归中序遍历 { stack<BiTree*> s; BiTree *p = T; while(p!=NULL || !s.empty()) { while(p!=NULL) { s.push(p); p = p->lchild; } if(!s.empty()) { p=s.top(); cout<<p->data; s.pop(); p = p->rchild; } } } void PostOrder2(BiTree *T) //非递归后序遍历 { stack<BiTree*> s; BiTree *cur; //当前结点 BiTree *pre=NULL; //前一次访问的结点 s.push(T); while(!s.empty()) { cur=s.top(); if((cur->lchild==NULL&&cur->rchild==NULL)|| (pre!=NULL&&(pre==cur->lchild||pre==cur->rchild))) { cout<<cur->data; //如果当前结点没有孩子结点或者孩子节点都已被访问过 s.pop(); pre=cur; } else { if(cur->rchild!=NULL) s.push(cur->rchild); if(cur->lchild!=NULL) s.push(cur->lchild); } } }
层次遍历:即从上到下从左到右依次遍历。层次遍历中需要用到queue进行操作,C++的queue文件中提供了其相关的操作。
void LevelOrder(BiTree *T)//层次遍历 { queue<BiTree*> q; BiTree *p = T; q.push(T); while(!q.empty()) { p = q.front(); cout<<p->data; q.pop(); if(p->lchild) q.push(p->lchild); if(p->rchild) q.push(p->rchild); } }
对于二叉树除了比较重要的遍历操作外,统计二叉树叶子结点的个数、求二叉树的深度、宽度、将二叉树的左右子树进行相互交换都是一些重要的操作。
int LeafNumber(BiTree *T)//叶子节点个数 { if(!T) return 0; if(T) { if((!T->lchild) && (!T->rchild)) i++; LeafNumber(T->lchild); LeafNumber(T->rchild); } return i; } int maxNumber(int a,int b) { if(a>=b) return a; else return b; } int GetMaxDepth (BiTree *T)//求树的深度 { if(!T) return 0; else { int left=GetMaxDepth(T-&g 4000 t;lchild); int right= GetMaxDepth(T->rchild); int num =maxNumber(left,right); return num+1; } } //树的宽度 //利用层次遍历 //每当一层的节点数入队列时记录增加nextwidth的值,如果其大于width的值,则将其付给width int GetMaxWidth(BiTree *T) { if(!T) return 0; queue<BiTree*> qu; qu.push(T); int width=1;//最终得到的树的宽度 int curwidth=1;//记录上一层的宽度 int nextwidth=0; while(!qu.empty()) { while(curwidth!=0) { BiTree* p=qu.front(); qu.pop(); curwidth--; if(p->lchild!=NULL) { qu.push(p->lchild); nextwidth++; } if (p->rchild!=NULL) { qu.push(p->rchild); nextwidth++; } } if(nextwidth>width) width=nextwidth; curwidth=nextwidth; nextwidth=0; } return width; } BiTree* Change(BiTree *T)//递归式调换左右子树的算法 { BiTree *p; if(T==NULL || (T->lchild==NULL && T->rchild==NULL)) return T; p=T->lchild; T->lchild = T->rchild; T->rchild = p; if(T->lchild) T->lchild = Change(T->lchild); if(T->rchild) T->rchild = Change(T->rchild); return T; } int Change2(BiTree *T)//非递归式交换左右子树 { stack<BiTree*> s; BiTree *p; if(T == NULL) return 0; s.push(T); while (!s.empty()) { T=s.top(); s.pop(); p = T->lchild; T->lchild = T->rchild; T->rchild = p; if(T->rchild) s.push(T->rchild); if(T->lchild) s.push(T->lchild); } return 1; }
测试程序:
int main() { BiTree *T; cout<<"Enter"<<endl; CreateBiTree(T); cout<<"先序递归遍历:"; PreOrderBiTree(T); cout<<endl<<"先序非递归遍历:"; PreOrder2(T); cout<<endl<<"中序递归遍历:"; InOrderBiTree(T); cout<<endl<<"中序非递归遍历:"; InOrder2(T); cout<<endl<<"后序递归遍历:"; PostOrderBiTree(T); cout<<endl<<"后序非递归遍历:"; PostOrder2(T); cout<<endl<<"层次遍历:"; LevelOrder(T); Change(T);//递归式交换左右子树 cout<<endl<<"交换左右子树后层次遍历:"; LevelOrder(T); Change2(T);//非递归式交换左右子树 cout<<endl<<"交换左右子树后层次遍历:"; LevelOrder(T); cout<<endl; cout<<"二叉树的叶子节点个数是:"<<LeafNumber(T); cout<<endl<<"二叉树的深度是:"<<GetMaxDepth(T); cout<<endl<<"二叉树的宽度是:"<<GetMaxWidth(T); return 0; }
最后的实验结果:
对程序的输入进行说明:通过先序遍历的方式创建二叉树,#表示其相应的子树为空。
相关文章推荐
- AVL树-自平衡二叉查找树(Java实现)
- C#中的递归APS和CPS模式详解
- WinForm实现按名称递归查找控件的方法
- C#中的尾递归与Continuation详解
- C语言二叉树的非递归遍历实例分析
- C#递归实现显示文件夹及所有文件并计算其大小的方法
- C++非递归队列实现二叉树的广度优先遍历
- php递归创建目录的方法
- C#使用前序遍历、中序遍历和后序遍历打印二叉树的方法
- Javascript递归打印Document层次关系实例分析
- oracle 使用递归的性能提示测试对比
- 使用curl递归下载软件脚本分享
- Perl脚本实现递归遍历目录下的文件
- JavaScript的递归之递归与循环示例介绍
- C# 递归查找树状目录实现方法
- 全排列算法的非递归实现与递归实现的方法(C++)
- php递归列出所有文件和目录的代码
- java递归菜单树转换成pojo对象
- 一个JavaScript递归实现反转数组字符串的实例
- Python:打印某个路径下的所有文件