【数据结构】二叉树的遍历(递归与非递归)
2017-05-11 17:58
441 查看
先序遍历(递归)
遍历过程访问根结点
先序遍历其左子树
先序遍历其右子树
void PreOrderTraversal(BinTree BT) { if( BT ) { printf("%d", BT->Data); PreOrderTraversal(BT->Left); PreOrderTraversal(BT->Right); } }
中序遍历(递归)
遍历过程为中序遍历其左子树
访问根结点
中序遍历其右子树
void InOrderTraversal( BinTree BT ) { if( BT ) { InOrderTraversal( BT->Left ); printf("%d", BT->Data); InOrderTraversal( BT->Right ); } }
后序遍历(递归)
遍历过程为后序遍历其左子树
后序遍历其右子树
访问根结点
void PostOrderTraversal( BinTree BT ) { if( BT ){ PostOrderTraversal(BT->Left); PostOrderTraversal(BT->Right); printf("%d", BT->Data); } }
非递归遍历算法
非递归算法实现的基本思路:使用堆栈中序遍历过程:
遇到一个结点就把它压入栈,并去遍历它的左子树。
当左子树遍历结束后,从栈顶弹出这个结点并访问它。
然后按其右指针再去中序遍历该结点的右子树。
void InOrderTraversal( BinTree BT ) { BinTree T = BT; Stack S = CreatStack( MaxSize );/*创建并初始化堆栈S*/ while( T || !IsEmpty(S)){ while(T){/*一直向左并将沿途结点压入堆栈*/ Push(S, T); T = T->left; } if(!IsEmpty(S)){ T = Pop(S);/*结点弹出堆栈*/ printf("%5d", T->Data);/*访问并打印结点*/ T = T->Right;/*转向右子树*/ } } }
先序遍历的非递归算法,就是第一次碰到结点的时候就print出来,相对于中序遍历(第二次遍历到它的时候再print),就是改下结点的输出时间。
void PreOrderTraversal(BinTree BT) { BinTree T = BT; Stack S = CreatStack( MaxSize );/*创建并初始化堆栈S*/ while( T || !IsEmpty(S)){ while(T){/*一直向左并将沿途结点压入堆栈*/ printf("%5d", T->Data);/*访问并打印结点*/ Push(S, T); T = T->left; } if(!IsEmpty(S)){ T = Pop(S);/*结点弹出堆栈*/ T = T->Right;/*转向右子树*/ } } }
后序遍历递归定义:先左子树,后右子树,再根节点。后序遍历的难点在于:需要判断上次访问的节点是位于左子树,还是右子树。若是位于左子树,则需跳过根节点,先进入右子树,再回头访问根节点;若是位于右子树,则直接访问根节点。
void PostOrderTraversal( BinTree BT ) { BinTree T = BT; BinTreeNode pLastVisit; /*pLastVisit:上次访问节点 */ Stack S = CreatStack( MaxSize );/*创建并初始化堆栈S*/ while( T ){/*一直向左并将沿途结点压入堆栈*/ Push(S, T); T = T->left; } while( !IsEmpty(S) ){ T = Pop(S);/*弹出栈顶元素*/ /*如果不存在右子树,或者右子树已经被访问过,则输出根结点*/ if( T->Right == NULL || T->Right == pLastVisit ){ printf("%5d", T->Data);/*访问并打印结点*/ pLastVisit = T;/*修改最近被访问的结点*/ }else{ //如果存在右子树并且右子树没有访问过,则根结点再次入栈 Push(S, T); //进入右子树,并将右子树的所有左子树压入栈中 T = T->Right; While(T){ Push(S,T); T = T->Left; } } } }
层序遍历
二叉树遍历的核心问题:二维结构的线性化从结点访问其左、右儿子结点,访问左儿子后有儿子怎么办?
需要一个存储结构保存暂时不访问的结点:堆栈、队列
队列的实现:
遍历从根结点开始,然后将根结点入队列,然后开始执行循环:结点出队,访问该结点,将其左右儿子入队列。
动图,耐心观看,简单明了
void LevelOrderTraversal( BinTree BT ) { Queue Q; BinTree T; if(!BT) Return;/*若是空树则直接返回*/ Q = CreateQueue( MaxSize )/*创建并初始化队列*/ AddQ(Q, BT); while( !IsEmptyQ(Q) ){ T = DeleteQ(Q); printf("%d\n", T->Data);/*访问出队列结点*/ if( T->Left ) AddQ( Q, T->Left ); if( T->Right ) AddQ( Q, T->Right ); } }
相关文章推荐
- 数据结构---二叉树的前序、中序、后序遍历的递归和非递归 实现(C++)
- 数据结构:二叉树的前序,中序,后序遍历(递归和非递归)
- 数据结构--树:二叉树的遍历方式(递归和非递归)
- 二叉树创建及遍历算法(递归及非递归)
- [置顶] 数据结构——二叉树 前序、中序、后序、递归遍历和非递归遍历
- 二叉树创建及遍历算法(递归及非递归)
- 数据结构(六)——二叉树 前序、中序、后序、层次遍历及非递归实现 查找、统计个数、比较、求深度的递归实现
- 二叉树的遍历(递归与非递归)
- 二叉树的三种遍历方式的递归实现和非递归实现
- 二叉树的层序遍历(递归与非递归)
- 43.递归和非递归俩种方法实现二叉树的前序遍历。
- 二叉树的遍历详解(前序中序后序层次-递归和非递归)
- 二叉树的前序,中序,后续,递归及非递归遍历的python实现
- 二叉树的三种遍历方式(递归和非递归)
- 数据结构 —— 二叉树 前序、中序、后序、层次遍历及非递归实现 查找、统计个数、比较、求深度的递归实现
- 二叉树的遍历与青蛙跳台阶——利用递归的数据结构来理解递归过程
- 我用Java实现的二叉树的遍历(递归和非递归)
- 数据结构 二叉树 已知前序中序遍历求后续遍历的递归实现
- 二叉树的三种遍历,递归与非递归
- 数据结构--二叉树--中序非递归遍历二叉树(链式结构)