二叉树的遍历非递归
来源:互联网 发布:计算机数据单位 编辑:程序博客网 时间:2024/06/01 09:11
题目:给定一颗二叉树,如下图:
要求:
前序遍历输出结果:1 2 4 6 7 5 9 10 3 8
中序遍历输出结果:6 4 7 2 9 5 10 1 3 8
后序遍历输出结果:6 7 4 9 10 5 2 8 3 1
结构如下:
struct Node
{
Node(int val)
:_left(NULL)
,_right(NULL)
,_val(val)
{}
Node* _left;
Node* _right;
int _val;
};
前序遍历
分析:
前序遍历的递归定义:先根节点,后左子树,再右子树。有了中序遍历的基础,不用我再像中序遍历那样引导了吧。
首先,我们遍历左子树,边遍历边打印,并把根节点存入栈中,以后需借助这些节点进入右子树开启新一轮的循环。还得重复一句:所有的节点都可看做是根节点。
void PrevSort_Tree(Node* root)//前序遍历{assert(root);if(root->_left ==NULL&&root->_right ==NULL){cout<<root->_val;return ;}Node* cur=root;stack<Node*> s;s.push(root);while (!s.empty()) //循环结束条件与前两种不一样{cout << cur->_val <<" ";/*栈的特点:先进后出先被访问的根节点的右子树后被访问*/if (cur->_right )s.push(cur->_right );if (cur->_left )cur = cur->_left ;else{//左子树访问完了,访问右子树cur= s.top();s.pop();}}cout << endl;}
中序遍历:
中序遍历的递归定义:先左子树,后根节点,再右子树。如何写非递归代码呢?一句话:让代码跟着思维走。我们的思维是什么?思维就是中序遍历的路径。假设,你面前有一棵二叉树,现要求你写出它的中序遍历序列。如果你对中序遍历理解透彻的话,你肯定先找到左子树的最下边的节点。
void InSort_Tree(Node* root){assert(root);if(root->_left ==NULL&&root->_right ==NULL){cout<<root->_val;return ;}Node* cur=root;stack<Node*> s;while (!s.empty()||cur) //循环结束条件与前两种不一样{while(cur){s.push(cur);cur = cur->_left ;}if(!s.empty()){//左子树访问完了,访问右子树cur= s.top();s.pop();cout<<cur->_val <<" ";cur=cur->_right ;}}cout << endl;}
后续遍历:
后序遍历递归定义:先左子树,后右子树,再根节点。后序遍历的难点在于:需要判断上次访问的节点是位于左子树,还是右子树。若是位于左子树,则需跳过根节点,先进入右子树,再回头访问根节点;若是位于右子树,则直接访问根节点。
void PostOrderTraverse(Node* root)//非递归后序遍历,用一个标记标记右子树是否访问过 { if (root == NULL) return; stack<Node*> s; //pCur:当前访问节点,pLastVisit:上次访问节点 Node* pCur, *pLastVisit; pCur = root; pLastVisit = NULL; while (pCur) //先把pCur移动到左子树最下边 { s.push(pCur); pCur = pCur->_left ; } while (!s.empty()) //走到这里,pCur都是空,//并已经遍历到左子树底端(看成扩充二叉树,则空,亦是某棵树的左孩子) { pCur = s.top(); s.pop(); //一个根节点被访问的前提是:无右子树或右子树已被访问过 if (pCur->_right == NULL || pCur->_right == pLastVisit) { cout << pCur->_val <<" "; //修改最近被访问的节点 pLastVisit = pCur; } /*这里的else语句可换成带条件的else if: else if (pCur->lchild == pLastVisit)//若左子树刚被访问过,则需先进入右子树(根节点需再次入栈) 因为:上面的条件没通过就一定是下面的条件满足。仔细想想! */ else { //根节点再次入栈 s.push(pCur); //进入右子树,且可肯定右子树一定不为空 pCur = pCur->_right ; while (pCur) { s.push(pCur); pCur = pCur->_left ; } } } cout << endl; }
代码测试如下:
void test1(){BinaryTree t;Node* node1=new Node(1);Node* node2=new Node(2);Node* node3=new Node(3);Node* node4=new Node(4);Node* node5=new Node(5);Node* node6=new Node(6);Node* node7=new Node(7);Node* node8=new Node(8);Node* node9=new Node(9);Node* node10=new Node(10);node1->_left=node2;node1->_right=node3;node2->_left=node4;node2->_right=node5;node3->_left =node8;node4->_left =node6;node4->_right=node7;node5->_left =node9;node5->_right =node10;cout<<"PrevSort:";t.PrevSort_Tree(node1);cout<<"InSort:";t.InSort_Tree(node1);cout<<"PostSort:";t.PostOrderTraverse(node1);}int main(){test1();system("pause");return 0;}
层序遍历详见博客:http://blog.csdn.net/wodeqingtian1234/article/details/75646566
阅读全文
0 0
- 二叉树的递归,非递归遍历
- 二叉树的递归+非递归遍历
- 二叉树的递归非递归遍历
- 二叉树的遍历--递归+非递归
- 二叉树的递归、非递归遍历
- 二叉树的递归非递归遍历
- 二叉树的先中后序遍历,递归遍历,非递归遍历
- 二叉树的递归遍历与非递归遍历
- 二叉树的创建,递归遍历,非递归遍历
- 二叉树的递归遍历与非递归遍历
- 二叉树的非递归遍历以及递归遍历
- 二叉树的非递归遍历&递归遍历
- 二叉树的递归遍历和非递归遍历
- 二叉树的递归遍历与非递归遍历
- 二叉树的递归遍历和非递归遍历
- 二叉树的构造,递归遍历,非递归遍历
- 二叉树的遍历(递归+非递归+层次遍历)
- 二叉树的递归遍历与非递归遍历
- 集群基础----(ricci+luci的安装)
- Yii2中的components的使用
- PAT乙级 1044. 火星数字(20)
- sarpcd 启动出错 ERZ058503E/0108
- java初入门
- 二叉树的遍历非递归
- ACM 暴力枚举 Meeting with Aliens
- Integer.parseInt("a")方法和Integer.valueOf("a")、Integer.valueOf(a,b)方法的分析
- PAT乙级 1045. 快速排序(25)--数学问题
- 交叉编译helloword模块
- Appium 启动服务并连接模拟器和真机方案
- 游标的循环示例
- noip模拟赛第一题单词(7月26日)
- python连接JIRA增删改查issue