中序遍历

非递归方式实现树的遍历

天大地大妈咪最大 提交于 2020-02-14 23:08:26
本文转载自作者:hzhu212 链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal/solution/yan-se-biao-ji-fa-yi-chong-tong-yong-qie-jian-ming/ 来源:力扣(LeetCode) 官方题解中介绍了三种方法来完成树的中序遍历,包括: 递归 借助栈的迭代方法 莫里斯遍历 在树的深度优先遍历中(包括前序、中序、后序遍历),递归方法最为直观易懂,但考虑到效率,我们通常不推荐使用递归。 栈迭代方法虽然提高了效率,但其嵌套循环却非常烧脑,不易理解,容易造成“一看就懂,一写就废”的窘况。而且对于不同的遍历顺序(前序、中序、后序),循环结构差异很大,更增加了记忆负担。 因此,我在这里介绍一种“颜色标记法”(瞎起的名字……),兼具栈迭代方法的高效,又像递归方法一样简洁易懂,更重要的是,这种方法对于前序、中序、后序遍历,能够写出完全一致的代码。 其核心思想如下: 使用颜色标记节点的状态,新节点为白色,已访问的节点为灰色。 如果遇到的节点为白色,则将其标记为灰色,然后将其右子节点、自身、左子节点依次入栈。 如果遇到的节点为灰色,则将节点的值输出。 使用这种方法实现的中序遍历如下: class Solution : def inorderTraversal ( self

由二叉树的前序遍历字符串得到其中序遍历字符串

删除回忆录丶 提交于 2020-02-14 02:15:11
Case1:满二叉树 题目描述 给出一棵满二叉树的先序遍历,有两种节点:字母节点(A-Z,无重复)和空节点(#)。要求这个树的中序遍历。输出中序遍历时不需要输出#。满二叉树的层数n满足1<=n<=5。 示例1 Sample Input: ABC#D#ESample Output:CBADE Solution: 满二叉树的特征很明显,左右子树结点个数相等,那么以某一个结点为根的子树中,该根节点在先序遍历中排在第一位,其在中序遍历中一定排在最中间的位置上。利用分治的思想,建立一个数组,   根节点插入到数组中间位置,   左子树根节点插入到数组左边的中间位置,   一直这样直至数组左边中间位置已满开始插入到右边数组的中间位置,   依次递归 . . . . . . 以示例为例,遍历前序遍历字符串插入到数组中,最后输出数组中字符串,即为中序遍历字符串。 #include <iostream> #include <string.h> using namespace std; int i; // 全局变量,控制字符串的遍历 string s; void insert(char a[], int left, int right){ // 将字符串各个元素插入数组对应位置 int mid = (left + right) / 2; if(left <= right && a[mid] != s

二叉树相关

安稳与你 提交于 2020-02-12 18:14:42
镜面反转 :是指将所有非叶结点的左右孩子对换。 1.已知先序遍历,中序遍历,求层序遍历 (这道题求层序的镜面反转,所以每一层 从右向左 遍历) #include<iostream> #include<algorithm> #include<queue> using namespace std; const int N = 10110; int pre[N],mid[N]; //前序遍历 中序遍历结果 int n,cnt; queue<int> q; struct Node { int w; int l,r; }node[N]; void bulid(int l,int r,int pos) { if(l>=r) { node[pos].w = -1; return; } int root = pre[cnt++]; node[pos].w = root; node[pos].l = 2*pos;//左子结点 node[pos].r = 2*pos+1;//右子结点 int m = find(mid,mid+r,root)-mid; //algorithm中的find()函数,返回指针 bulid(l,m,2*pos); bulid(m+1,r,2*pos+1); } void LevelPrint() { q.push(1); int pos; while(!q.empty())

leetcode(33)--中序遍历二叉树

送分小仙女□ 提交于 2020-02-11 21:19:57
题目: 给定一个二叉树,返回它的 中序 遍历。 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 思路:非迭代方法 class Solution { public: vector<int> inorderTraversal(TreeNode *root) { vector<int> res; stack<TreeNode *> s; TreeNode *p = root; while(p != NULL || !s.empty()) { while(p != NULL) { s.push(p); p = p->left; } if(!s.empty()) { p = s.top(); res.push_back(p->val); s.pop(); p = p->right; } } return res; } }; 思路2:迭代方法 class Solution { public: vector<int> inorderTraversal(TreeNode* root) { vector<int> res; inorder(root,res); return res; } void inorder(TreeNode* p, vector<int>& res) { if(p!=NULL) {

Leetcode——863.二叉树中所有距离为 K 的结点

余生长醉 提交于 2020-02-09 12:53:05
给定一个二叉树(具有根结点 root), 一个目标结点 target ,和一个整数值 K 。 返回到目标结点 target 距离为 K 的所有结点的值的列表。 答案可以以任何顺序返回。 示例 1: 输入:root = [3,5,1,6,2,0,8,null,null,7,4], target = 5, K = 2 输出:[7,4,1] 解释: 所求结点为与目标结点(值为 5)距离为 2 的结点, 值分别为 7,4,以及 1 注意,输入的 "root" 和 "target" 实际上是树上的结点。 上面的输入仅仅是对这些对象进行了序列化描述。 提示: 给定的树是非空的,且最多有 K 个结点。 树上的每个结点都具有唯一的值 0 <= node.val <= 500 。 目标结点 target 是树上的结点。 0 <= K <= 1000. 来源:力扣(LeetCode) 链接: https://leetcode-cn.com/problems/all-nodes-distance-k-in-binary-tree 一 这道题给了我们一棵二叉树,一个目标结点 target,还有一个整数K,让返回所有跟目标结点 target 相距K的结点。我们知道在子树中寻找距离为K的结点很容易,因为只需要一层一层的向下遍历即可,难点就在于符合题意的结点有可能是祖先结点,或者是在旁边的兄弟子树中

二叉树的遍历

淺唱寂寞╮ 提交于 2020-02-09 07:50:28
二叉树是一种非常重要的数据结构,很多其它数据结构都是基于二叉树的基础演变而来的。对于二叉树,有前序、中序以及后序三种遍历方法。因为树的定义本身就是递归定义,因此采用递归的方法去实现树的三种遍历不仅容易理解而且代码很简洁。而对于树的遍历若采用非递归的方法,就要采用栈去模拟实现。在三种遍历中,前序和中序遍历的非递归算法都很容易实现,非递归后序遍历实现起来相对来说要难一点。 前序遍历 递归 void preOrder1(BinTree *root) //递归前序遍历 { if(root!=NULL) { cout<<root->data<<" "; preOrder1(root->lchild); preOrder1(root->rchild); } } 非递归 根据前序遍历访问的顺序,优先访问根结点,然后再分别访问左孩子和右孩子。即对于任一结点,其可看做是根结点,因此可以直接访问,访问完之后,若其左孩子不为空,按相同规则访问它的左子树;当访问其左子树时,再访问它的右子树。因此其处理过程如下: 对于任一结点P: 1)访问结点P,并将结点P入栈; 2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P; 3)直到P为NULL并且栈为空,则遍历结束。 void preOrder2

二叉树三种遍历方式的非递归实现

南楼画角 提交于 2020-02-09 07:50:11
1、二叉树的先序遍历。 节点->左孩子->右孩子 用递归很容易解决,但是会遇到内存溢出情况。用栈可以解决找个问题。 根据前序遍历访问的顺序,优先访问根结点,然后再分别访问左孩子和右孩子。即对于任一结点,其可看做是根结点,因此可以直接访问,访问完之后,若其左孩子不为空,按相同规则访问它的左子树;当访问其左子树时,再访问它的右子树。因此其处理过程如下:   对于任一结点P: 1)访问结点P,并将结点P入栈; 2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P; 3)直到P为NULL并且栈为空,则遍历结束。 1 public void xianxu(TreeNode root){ 2 Stack<TreeNode> stack = new Stack<>(); 3 TreeNode p = root; 4 while ( !stack.isEmpty() ){ 5 while ( p != null ){ 6 System.out.println(p.val); 7 stack.push(p); 8 p = p.left; 9 } 10 if ( !stack.isEmpty() ){ 11 p = stack.pop(); 12 p = p.right; 13 } 14 } 15

二叉树的遍历方式(迭代)

妖精的绣舞 提交于 2020-02-09 07:49:41
1.先序遍历 根据前序遍历访问的顺序,优先访问根结点,然后再分别访问左孩子和右孩子。即对于任一结点,其可看做是根结点,因此可以直接访问,访问完之后,若其左孩子不为空,按相同规则访问它的左子树;当访问其左子树时,再访问它的右子树。因此其处理过程如下:   对于任一结点P: 1)访问结点P,并将结点P入栈; 2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P; 3)直到P为NULL并且栈为空,则遍历结束。 vector<int> PreOrder(TreeNode* root){ vector<int>res; if (!root)return res; stack<TreeNode*>ss; TreeNode* cur = root; while (cur || !ss.empty()){ if (cur){ res.push_back(cur->val); ss.push(cur); cur = cur->left; } else{ cur = ss.top(); cur = cur->right; ss.pop(); } } return res; } 2.中序遍历 根据中序遍历的顺序,对于任一结点,优先访问其左孩子,而左孩子结点又可以看做一根结点,然后继续访问其左孩子结点

教你如何迭代地遍历二叉树

牧云@^-^@ 提交于 2020-02-09 07:49:21
为何要迭代? 二叉树遍历是一个非常常见的操作,无论是中序遍历、先序遍历还是后续遍历,都可以用递归的方法很好地完成,但是相对来说迭代的方法难度就高不少,而且除此之外,迭代地遍历树至少有两个现实意义的优点: 1.比递归节省空间,递归是用栈实现的,因此如果树的高度h很大的话,递归很有可能会造成栈溢出 2.迭代的代码利用循环,而循环可以用循环不变量来证明代码的正确性 我们现在就分别详解这几个迭代地遍历树的方法。 先序遍历 我们先来看看先序遍历,因为在这个里面先序遍历用迭代实现是最简单的。我们先看递归的代码: class Solution: # @param root, a tree node # @return a list of integers def preorder(self,root): ans=[] self.dfs(root, ans) return ans def dfs(self,root,ans): if not root: return ans.append(root.val) self.dfs(root.left, ans) self.dfs(root.right,ans) 先序遍历就是先处理根节点,再处理左右子女节点,因此用迭代实现时,我们只要处理完根节点之后,把左右子女按照先右子女、后左子女的顺序推入栈来保证这个处理顺序就可以了。这个代码也很好理解: class

LeetCode94 二叉树的中序遍历

不羁岁月 提交于 2020-02-09 07:48:04
给定一个二叉树,返回它的 中序 遍历。 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ /* 算法思想: 算法思想: 采用递归的思想,即借助系统栈,效率较低。二叉树的前序遍历规则:1. 遍历左子树; 2. 访问根结点; 3. 遍历右子树 */ /* class Solution { private: void rec(TreeNode* root,vector<int> &ret){ if(root != NULL){ rec(root->left,ret); ret.push_back(root->val); rec(root->right,ret); } } public: vector<int> inorderTraversal(TreeNode* root) { vector<int> ret; rec(root,ret); return ret;