二叉树的建立和遍历(递归、非递归)
2015-11-09 21:29
363 查看
从二叉树的遍历的定义可知,3种遍历算法的不同之处在于访问根节点和左右子树的先后关系。如果在算法中暂时忽略访问根节点的printf语句,则3种遍历算法完全相同。因此,从递归执行的角度来看,先序、中序和后序遍历是完全相同的。上图中的用带箭头的虚线表示这3种遍历算法执行的过程。其中,向下的箭头表示更深一层的递归调用,向上的箭头表示从递归调用退出返回;虚线旁的三角形、圆形和方形内的字符分别表示先序、中序和后序遍历二叉树过程中访问节点时输出的信息。
# include<stdio.h> # include<malloc.h> # define MAX 100 //二叉树节点 typedef struct BiNode{ char data; struct BiNode *lchild,*rchild; }BiNode,*BiTree; //栈 typedef struct{ BiTree data[MAX]; int top; }Stack; void createBiTree(BiTree &T); void PreOrder(BiTree T); void PreOrder2(BiTree T,Stack &s); void InOrder(BiTree T); void InOrder2(BiTree T,Stack &s); void PostOrder(BiTree T); void PostOrder2(BiTree T,Stack s1,Stack s2); int getTop(Stack &s,BiTree &t); void InitStack(Stack &s); int isFull(Stack s); int isEmpty(Stack s); int Push(Stack &s,BiTree t); int Pop(Stack &s); int main() { BiTree T=NULL; Stack s1,s2; InitStack(s1); InitStack(s2); printf("创建二叉树('#'代表空节点):"); createBiTree(T); printf("\n先序遍历二叉树(递归):"); PreOrder(T); printf("\n先序遍历二叉树(非递归):"); PreOrder2(T,s1); printf("\n中序遍历二叉树(递归):"); InOrder(T); printf("\n中序遍历二叉树(非递归):"); InOrder2(T,s1); printf("\n后序遍历二叉树(递归):"); PostOrder(T); printf("\n后序遍历二叉树(非递归):"); PostOrder2(T,s1,s2); printf("\n"); return 0; } //创建二叉树 void createBiTree(BiTree &T) { char ch; scanf("%c",&ch); if(ch=='#') { T=NULL; return ; } else { T=(BiTree)malloc(sizeof(BiNode)); T->data=ch; T->lchild=T->rchild=NULL; createBiTree(T->lchild); createBiTree(T->rchild); } } //先序遍历二叉树(递归) void PreOrder(BiTree T) { if(!T) return ; else { printf("%c ",T->data); PreOrder(T->lchild); PreOrder(T->rchild); } } //先序遍历二叉树(非递归) void PreOrder2(BiTree T,Stack &s) { if(!T) return ; BiTree p=NULL; InitStack(s); Push(s,T); while(!isEmpty(s)) { //一直向左,直到遇到NULL while(getTop(s,p)&&p) { printf("%c ",p->data); Push(s,p->lchild); } Pop(s);//空指针退栈 if(!isEmpty(s)) { getTop(s,p); Pop(s); Push(s,p->rchild); } } } //中序遍历二叉树(递归) void InOrder(BiTree T) { if(!T) return ; else { InOrder(T->lchild); printf("%c ",T->data); InOrder(T->rchild); } } //中序遍历二叉树(非递归) void InOrder2(BiTree T,Stack &s) { if(!T) return ; BiTree p=NULL; InitStack(s); Push(s,T); while(!isEmpty(s)) { while(getTop(s,p)&&p) Push(s,p->lchild);//一直向左走到尽头 Pop(s);//空指针出栈 if(!isEmpty(s)) { getTop(s,p); printf("%c ",p->data); Pop(s); Push(s,p->rchild); } } } //后序二叉树遍历(递归) void PostOrder(BiTree T) { if(!T) return ; else { PostOrder(T->lchild); PostOrder(T->rchild); printf("%c ",T->data); } } //后序遍历二叉树(非递归) void PostOrder2(BiTree T,Stack s1,Stack s2) { if(!T) return ; BiTree p=NULL; InitStack(s1); InitStack(s2); Push(s1,T); //先按照‘根右左’的顺序遍历,s1作为该遍历顺序的辅助栈。逆过来,就是'左右根'。s1中先访问的节点先压入栈s2. while(!isEmpty(s1)) { while(getTop(s1,p)&&p) { Push(s2,p); Push(s1,p->rchild);//一直向右走,直到尽头 } Pop(s1);//空指针出栈 if(!isEmpty(s1)) { getTop(s1,p); Pop(s1); Push(s1,p->lchild); } } //依次从s2栈顶弹出节点便是按照‘左右根’顺序遍历二叉树 while(!isEmpty(s2)) { getTop(s2,p); printf("%c ",p->data); Pop(s2); } } //初始化栈 void InitStack(Stack &s) { s.top=0; } //判断栈是否满了,若是,则返回1,否则返回0. int isFull(Stack s) { if(s.top>=MAX) return 1; else return 0; } //判断栈是否为空,若是,返回1,否则返回0 int isEmpty(Stack s) { if(s.top==0) return 1; else return 0; } //入栈,若成功,则返回1,否则返回0 int Push(Stack &s,BiTree t) { if(isFull(s)) return 0; else { s.data[s.top]=t; s.top++; return 1; } } //出栈,若出栈成功,则返回1,否则返回0 int Pop(Stack &s) { if(isEmpty(s)) return 0; else { s.top--; return 1; } } //获得栈顶元素,成功返回1,失败返回0 int getTop(Stack &s,BiTree &t) { if(isEmpty(s)) return 0; else { t=s.data[s.top-1]; return 1; } }
相关文章推荐
- 响应式网页
- c#??操作符
- 数据库大数据访问的解决方法
- DOxygen for C++使用说明——注释代码二
- 字符串匹配(算法导论)
- MediaPlayer的使用
- iOS UITextField控件总结
- HDU3518 后缀数组求不可重叠重复出现的不同子串个数
- logback学习资料
- HDU5533(水不水?)
- 如何用dw新建一个网页
- hdu4324 Triangle LOVE【tarjan强连通分量基础题】
- 程序员的支配力 (上)
- HDOJ 5240 Exam (贪心)
- Java-微信支付-接口配置信息验证-配置代码和技巧
- UITextField 全面的介绍
- Beaglebone Black(9)运用Python来发邮件
- 树形dp
- ROS(robot OS)学习 (N)
- 《leetCode》:First Missing Positive