首页 / 算法 / [算法]二叉树的遍历:前序,中序与后序
[算法]二叉树的遍历:前序,中序与后序
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了[算法]二叉树的遍历:前序,中序与后序,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含7399字,纯文字阅读大概需要11分钟。
内容图文
![[算法]二叉树的遍历:前序,中序与后序](/upload/InfoBanner/zyjiaocheng/1290/144c9705b1cf4b2480b7e8c5c5a93c6b.jpg)
二叉树的遍历是二叉树的众多算法的基础。主要有,前序,中序与后序。
对于以下二叉树:
前序:12354
中序:21543
后序:24531
笔者实现了三种遍历方式:
1 前序:递归版本比较简单,只需要改变push_back操作的位置即可。
vector<int> PreOrderTraverse2(TreeNode *root) { vector<int> nodes; vector<int> temp; if(root == NULL) return nodes; nodes.push_back(root->val); temp = PreOrderTraverse2(root->left); for(vector<int>::size_type i = 0 ; i != temp.size() ; ++i) nodes.push_back(temp[i]); temp = PreOrderTraverse2(root->right); for(vector<int>::size_type i = 0 ; i != temp.size() ; ++i) nodes.push_back(temp[i]); return nodes; }
前序迭代版本,步骤如下:
(1)首先访问根节点root,先将root节点输出,压入堆栈,
(2)再考虑root节点的左子树,左子树也是一颗二叉树,重复(1)。
(3)某一步的左子树为空,那么该节点左子树已访问完毕,弹出栈顶,访问该节点的右子树,重复(1)即可。
很简单,只需要记住,在将节点压入堆栈时,该节点就已被访问,再访问完左孩子之后,再考虑右孩子所在的二叉树。
vector<int> PreOrderTraverse(TreeNode *root) { vector<int> nodes; stack<TreeNode *> s; if(root == NULL) return nodes; TreeNode *temp = root; while(temp || !s.empty()) { while(temp) { s.push(temp);//入栈之前就访问 nodes.push_back(temp->val); temp = temp->left; }//左子树访问完毕 temp = s.top(); s.pop(); temp = temp->right; } return nodes; }
2 中序, 递归版本:
vector<int> InOrderTraverse2(TreeNode *root) { vector<int> nodes; vector<int> temp; if(root == NULL) return nodes; temp = InOrderTraverse2(root->left); for(vector<int>::size_type i = 0 ; i != temp.size() ; ++i) nodes.push_back(temp[i]); nodes.push_back(root->val); temp = InOrderTraverse2(root->right); for(vector<int>::size_type i = 0 ; i != temp.size() ; ++i) nodes.push_back(temp[i]); return nodes; }
迭代版本:
(1)首先访问根节点root,压入堆栈。
(2)访问root的左子树,重复(1)即可。
(3)如果某节点左子树为空,那么该节点输出,并考察其右子树,重复(1)即可。
PS:节点入栈使不访问,遇到节点就入栈,直到栈顶左子树访问完毕,那么将栈顶弹出,考虑右子树,重复即可。
vector<int> InOrderTraverse(TreeNode *root) { vector<int> nodes; if(root == NULL) return nodes; TreeNode *temp = root; stack<TreeNode *> s; while(temp || !s.empty()) { while(temp) { s.push(temp); temp = temp->left; }// 左子树完毕 temp = s.top(); nodes.push_back(temp->val); s.pop(); temp = temp->right; } return nodes; }
3 后序,递归版本:
vector<int> PostOrderTraverse2(TreeNode *root) { vector<int> nodes; vector<int> temp; if(root == NULL) return nodes; temp = PostOrderTraverse2(root->left); for(vector<int>::size_type i = 0 ; i != temp.size() ; ++i) nodes.push_back(temp[i]); temp = PostOrderTraverse2(root->right); for(vector<int>::size_type i = 0 ; i != temp.size() ; ++i) nodes.push_back(temp[i]); nodes.push_back(root->val); return nodes; }
迭代版本:步骤如下:
PS:遇到根节点root,分两种情况讨论,如果根节点的右子树还没被访问,那么根节点入栈;否则输出根节点。
vector<int> PostOrderTraverse(TreeNode *root) { vector<int> nodes; if(root == NULL) return nodes; TreeNode *temp = root; TreeNode *pre = root; //记录前一次访问的节点 stack<TreeNode *> s; while(temp || !s.empty()) { while(temp) { s.push(temp); temp = temp->left; } temp = s.top(); if (temp->right == NULL || pre == temp->right) { nodes.push_back(temp->val); pre = temp; s.pop(); temp = NULL;//保证不重复访问 } else { temp = temp->right; } } return nodes; }
后序遍历的递归版本比较复杂。自己在编写代码时会出现死循环,因为出现了重复访问,因此上述的temp=NULL语句很重要。
后记:上述3种算法的空间复杂度均为O(n)。
完整的代码为:
#include<iostream> #include<vector> #include<stack> using namespace std; struct TreeNode{ int val; TreeNode *left; TreeNode *right; TreeNode(int x):val(x),left(NULL),right(NULL){} }; vector<int> InOrderTraverse2(TreeNode *root) { vector<int> nodes; vector<int> temp; if(root == NULL) return nodes; temp = InOrderTraverse2(root->left); for(vector<int>::size_type i = 0 ; i != temp.size() ; ++i) nodes.push_back(temp[i]); nodes.push_back(root->val); temp = InOrderTraverse2(root->right); for(vector<int>::size_type i = 0 ; i != temp.size() ; ++i) nodes.push_back(temp[i]); return nodes; } vector<int> PreOrderTraverse2(TreeNode *root) { vector<int> nodes; vector<int> temp; if(root == NULL) return nodes; nodes.push_back(root->val); temp = PreOrderTraverse2(root->left); for(vector<int>::size_type i = 0 ; i != temp.size() ; ++i) nodes.push_back(temp[i]); temp = PreOrderTraverse2(root->right); for(vector<int>::size_type i = 0 ; i != temp.size() ; ++i) nodes.push_back(temp[i]); return nodes; } vector<int> PostOrderTraverse2(TreeNode *root) { vector<int> nodes; vector<int> temp; if(root == NULL) return nodes; temp = PostOrderTraverse2(root->left); for(vector<int>::size_type i = 0 ; i != temp.size() ; ++i) nodes.push_back(temp[i]); temp = PostOrderTraverse2(root->right); for(vector<int>::size_type i = 0 ; i != temp.size() ; ++i) nodes.push_back(temp[i]); nodes.push_back(root->val); return nodes; } vector<int> PreOrderTraverse(TreeNode *root) { vector<int> nodes; stack<TreeNode *> s; if(root == NULL) return nodes; TreeNode *temp = root; while(temp || !s.empty()) { while(temp) { s.push(temp);//入栈之前就访问 nodes.push_back(temp->val); temp = temp->left; } temp = s.top(); s.pop(); temp = temp->right; } return nodes; } vector<int> InOrderTraverse(TreeNode *root) { vector<int> nodes; if(root == NULL) return nodes; TreeNode *temp = root; stack<TreeNode *> s; while(temp || !s.empty()) { while(temp) { s.push(temp); temp = temp->left; } temp = s.top(); nodes.push_back(temp->val); s.pop(); temp = temp->right; } return nodes; } vector<int> PostOrderTraverse(TreeNode *root) { vector<int> nodes; if(root == NULL) return nodes; TreeNode *temp = root; TreeNode *pre = root; //记录前一次访问的节点 stack<TreeNode *> s; while(temp || !s.empty()) { while(temp) { s.push(temp); temp = temp->left; } temp = s.top(); if (temp->right == NULL || pre == temp->right) { nodes.push_back(temp->val); pre = temp; s.pop(); temp = NULL;//保证不重复访问 } else { temp = temp->right; } } return nodes; } int main() { vector<int> nodes; TreeNode *root = new TreeNode(1); TreeNode *node2 = new TreeNode(2); TreeNode *node3 = new TreeNode(3); TreeNode *node4 = new TreeNode(4); TreeNode *node5 = new TreeNode(5); root->left = node2; root->right = node3; node5->right = node4; node3->left = node5; cout << "InOrder recursively..." << endl; nodes = InOrderTraverse2(root); for(vector<int>::size_type i = 0; i != nodes.size(); i++) cout << nodes[i] << " "; cout << endl; cout << "InOrder iterativelly..." << endl; nodes = InOrderTraverse(root); for(vector<int>::size_type i = 0; i != nodes.size(); i++) cout << nodes[i] << " "; cout << endl; cout << "PreOrder recursively..." << endl; nodes = PreOrderTraverse2(root); for(vector<int>::size_type i = 0; i != nodes.size(); i++) cout << nodes[i] << " "; cout << endl; cout << "PreOrder iterativelly..." << endl; nodes = PreOrderTraverse(root); for(vector<int>::size_type i = 0; i != nodes.size(); i++) cout << nodes[i] << " "; cout << endl; cout << "PostOrder recursively..." << endl; nodes = PostOrderTraverse2(root); for(vector<int>::size_type i = 0; i != nodes.size(); i++) cout << nodes[i] << " "; cout << endl; cout << "PostOrder iterativelly..." << endl; nodes = PostOrderTraverse(root); for(vector<int>::size_type i = 0; i != nodes.size(); i++) cout << nodes[i] << " "; cout << endl; }
原文:http://blog.csdn.net/xuqingict/article/details/19089727
内容总结
以上是互联网集市为您收集整理的[算法]二叉树的遍历:前序,中序与后序全部内容,希望文章能够帮你解决[算法]二叉树的遍历:前序,中序与后序所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。