【数据结构】二叉树的三种遍历--(递归+非递归)
来源:互联网 发布:矩阵乘法规则 编辑:程序博客网 时间:2024/06/05 18:06
前序遍历:根节点—>左子树—>右子树
中序遍历:左子树—>根节点—>右子树
后序遍历:左子树—>右子树—>根节点
【构造一棵树】
我们用数组存树的节点
int a[15] = { 1, 2, ‘#’, 3, ‘#’, ‘#’, 4, 5, ‘#’, 6, ‘#’, 7, ‘#’, ‘#’, 8 }
“#”代表非法值,就是为空的节点
#include<iostream>#include<stack>#include<queue>using namespace std;template < class T>struct BinaryTreeNode{ BinaryTreeNode* _left; BinaryTreeNode* _right; T _data; BinaryTreeNode(const T&x) :_left(NULL) , _right(NULL) ,_data(x) {}};template <class T>class BinaryTree{ typedef BinaryTreeNode<T> Node;public: BinaryTree() :_root(NULL) {} BinaryTree(const T* a, size_t n, const T& invalid) { size_t index = 0; _root = _CreatTree(a, n, invalid, index);//构造树的函数 }//构造树Node* _CreatTree(const T*a, size_t n, const T& invalid, size_t& index) { Node* root = NULL; if (index < n&&a[index] != invalid) { root = new Node(a[index]); root->_left = _CreatTree(a,n,invalid,++index); root->_right = _CreatTree(a, n, invalid, ++index); } return root; } ~BinaryTree() { _Destroy(_root); cout << endl; }protected: Node* _root;
前序——–递归
前序就是遇到根节点就访问,之后访问左子树,再右子树,所以很容易可以写出如下非递归代码
void PrevOrder() { _PrevOrder(_root); cout << endl; }void _PrevOrder(Node* root) { if (root == NULL) { return; } cout << root->_data << " "; _PrevOrder(root->_left); _PrevOrder(root->_right); }
前序——–非递归
这里我们要借用栈,因为栈的特性是后进先出。
先遍历树的最左节点,并把每个节点入栈。在入栈的同时就可以访问根节点。
当cur为NULL时,这颗树的最左边的根节点节点都全部入栈,
然后取出栈顶节点,访问右子树,
当栈为空,这个树就遍历结束
void PrevOrder_NonR()//非递归前序遍历 { stack<Node*> s; Node* cur = _root; while (cur||!s.empty()) { while (cur) { s.push(cur); cout << cur->_data << " "; cur = cur->_left; } Node* top = s.top(); s.pop(); cur = top->_right; } cout << endl; }
中序—-递归
void InOrder()//中序{ _InOrder(_root); cout << endl;} void _InOrder(Node* root) { if (root == NULL) { return; } _InOrder(root->_left); cout << root->_data << " "; _InOrder(root->_right); }
中序—-非递归
依然借助栈,把树的最左边的根节点cur全部入栈,
然后依次取栈顶节点访问,
再访问右子树,右子树不为空的时候继续入栈。
void InOrder_NonR()//非递归中序遍历 { Node* cur = _root; stack<Node*> s; while (cur||!s.empty()) { while (cur) { s.push(cur); cur = cur->_left; } Node* top = s.top();//此时访问的是最左节点 cout << top->_data << " "; s.pop(); cur = top->_right; } cout << endl; }
后序—-递归
void PosOrder()//后序{ _PosOrder(_root); cout << endl;}void _PosOrder(Node* root){ if (root == NULL) { return; } _PosOrder(root->_left); _PosOrder(root->_right); cout << root->_data << " ";}
后序—-非递归
还是借助栈。但是此时有一个问题:后序是先访问左子树,在右子树,最后根节点,那么问题来了:–访问右子树,是需要通过先访问根节点,当cur=top->_right,cur不是NULL,把cur入栈,依次访问右子树,最后依次退到根节点访问,但是此时cur=top->_right,cur不等于NULL,再次入栈;可是我们已经把右树访问过了,所以我们会在这里陷入死循环。
那么如何解决呢?
我们可以设置一个标记prev,prev表示上一个访问的节点。当我们取出栈顶节点时,如果他的右子树已经访问过了,就不再把右子树入栈,而直接访问当前节点。
void PostOrder_NonR()//后序非递归{ stack<Node*> s; Node* cur = _root; Node* prev = NULL; while (cur||!s.empty()) { while (cur) { s.push(cur); cur = cur->_left; } Node* top = s.top(); if (top->_right == NULL || top->_right == prev) { cout << top->_data << " "; prev = top; s.pop(); } else { cur = top->_right; } } cout << endl;}
阅读全文
0 0
- 二叉树的三种遍历(递归+非递归)
- 【数据结构】二叉树的三种遍历--(递归+非递归)
- 【数据结构】二叉树的遍历(递归与非递归)
- 数据结构BinaryTree实例(三):二叉树的后序遍历(递归与非递归)
- 数据结构 二叉树的非递归遍历
- 数据结构:二叉树的非递归遍历
- 二叉树的非递归遍历-数据结构
- 二叉树的三种遍历方式(递归、非递归和Morris遍历)
- 【数据结构与算法】二叉树的遍历(递归遍历、非递归遍历、层序遍历)
- [数据结构] 二叉树的递归与非递归遍历
- 二叉树非递归三种遍历
- 数据结构之二叉树遍历(递归和非递归)
- 二叉树的四种遍历(递归、非递归)
- 数据结构中二叉树的三种遍历的非递归写法
- 数据结构学习笔记(三)二叉树的非递归遍历
- 二叉树的三种遍历方法(递归和非递归)(转载)
- 二叉树的三种遍历方法(递归和非递归)(转载)
- 二叉树的三种遍历方法(递归和非递归)(转载)
- java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory
- 彻底理解ThreadLocal
- jQuery知识点大全
- Java面向对象特性--多态
- OCR识别-python版(一)
- 【数据结构】二叉树的三种遍历--(递归+非递归)
- Material Design整理(九)——CollapsingToolbarLayout
- git命令搜集总结
- 云栖大会·杭州峰会:《云数据·大计算:海量日志数据分析与应用》环境准备
- bzoj 2752: [HAOI2012]高速公路(road) 线段树
- python super()函数
- Exchange证书错误导致接收到Online的邮件
- 接口和抽象类的区别
- git 命令总结