前序遍历

根据前序遍历和中序遍历的结果重构二叉树LeetCode 95

只愿长相守 提交于 2020-01-22 05:25:16
题目描述 https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/ 根据一棵树的前序遍历与中序遍历构造二叉树。 注意: 你可以假设树中没有重复的元素。 前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder = [9,3,15,20,7] 返回如下的二叉树: 3 / \ 9 20 / \ 15 7 思路 首先我们在上一篇文章中解释了前序遍历和中序遍历的含义,因为是树的结构,一般都是用递归来实现。 用数学归纳法的思想就是,假设最后一步,就是root的左右子树都已经重建好了,那么我只要考虑将root的左右子树安上去即可。 根据前序遍历的性质,第一个元素必然就是root,那么下面的工作就是如何确定root的左右子树的范围。 根据中序遍历的性质,root元素前面都是root的左子树,后面都是root的右子树。那么我们只要找到中序遍历中root的位置,就可以确定好左右子树的范围。 简单来说就是当前前序遍历的结果,第一个元素必然是当前节点的值,而对于中序遍历来说,当前节点值的位置的前面都是左子树的值,后面都是右子树的值,所以根据这个思想,重新构建二叉树。 实现代码 /** * Definition for a binary tree

Morris 遍历二叉树

跟風遠走 提交于 2020-01-21 08:37:47
Morris Traversal 方法实现前序、中序以及后序遍历二叉树。相比使用栈或者递归(也是通过栈空间)方法,Morris 方法可以在空间复杂度为 O(1) ,时间复杂度为 O(n) 的条件下实现对二叉树的遍历。 前序遍历 如果当前节点左孩子 cur->left 为空,输出当前节点 cur 并指向右孩子 cur->right。 如果当前节点左孩子 cur->left 不为空,那么在当前节点的左子树中找出前驱节点 pre,也就是左子树中最大的点。 如果前驱节点的右孩子 pre->right 为空,那么将右孩子指向当前节点。 输出当前节点 。当前节点更新为当前节点的左孩子。 如果前驱节点的右孩子 pre->right 不为空,也就是指向当前节点。重新将右孩子设为空。当前节点更新为当前节点的右孩子。 重复 1、2 直到当前节点为空。 class Solution { public: vector<int> preorderTraversal(TreeNode* root) { TreeNode* cur = root; TreeNode* pre = NULL; vector<int> result; while(cur!=NULL){ if (cur->left == NULL){ result.push_back(cur->val); cur = cur->right;

二叉树遍历

天大地大妈咪最大 提交于 2020-01-21 07:54:32
二叉树遍历最简单的就是递归了。因为递归实质上是栈存了一些中间值,所以我们可以使用stack实现迭代版的遍历。 中序遍历 步骤: 首先将root节点作为当前节点。 1.如果当前节点不为空,压入当前节点。将左节点作为当前节点。 2.否则弹出栈顶节点作为当前节点,输出当前节点。 3.如果右节点不为空,右节点作为当前节点。 4.否则将当前节点置为空。 重复1、2、3、4直到栈为空。 void InorderTraversal(TreeNode *root){ if(!root)return; TreeNode *node=root; stack<TreeNode*> mystk; while(node||mystk.size()){ while(node){ mystk.push(node); node=node->left; } node=mystk.top(); mystk.pop(); cout<<node->val<<'\t'; if(node->right){ node=node->right; }else{ node=NULL; } } } 前序遍历 前序遍历和中序遍历差不多,只是输出节点值的时机不同。 步骤: 以root节点作为当前节点 1.如果当前节点不为空,将当前节点压入栈,同时输出当前节点。并将左节点作为当前节点。 2.否则弹出栈顶作为当前节点。 3.如果右节点不为空

浅谈数据结构-二叉树

浪子不回头ぞ 提交于 2020-01-20 17:35:34
二叉树是树的特殊一种,具有如下特点:1、每个结点最多有两颗子树,结点的度最大为2。2、左子树和右子树是有顺序的,次序不能颠倒。3、即使某结点只有一个子树,也要区分左右子树。 一、特殊的二叉树及特点 1、斜树 所有的结点都只有左子树(左斜树),或者只有右子树(右斜树)。这就是斜树,应用较少 2、满二叉树 所有的分支结点都存在左子树和右子树,并且所有的叶子结点都在同一层上,这样就是满二叉树。就是完美圆满的意思,关键在于树的平衡。 根据满二叉树的定义,得到其特点为: 叶子只能出现在最下一层。 非叶子结点度一定是2. 在同样深度的二叉树中,满二叉树的结点个数最多,叶子树最多。 3、完全二叉树 对一棵具有n个结点的二叉树按层序排号,如果编号为i的结点与同样深度的满二叉树编号为i结点在二叉树中位置完全相同,就是完全二叉树。满二叉树必须是完全二叉树,反过来不一定成立。 其中关键点是按层序编号,然后对应查找。 在上图中,树1,按层次编号5结点没有左子树,有右子树,10结点缺失。树2由于3结点没有字数,是的6,7位置空挡了。树3中结点5没有子树。 上图就是一个完全二叉树。 结合完全二叉树定义得到其特点: 叶子结点只能出现在最下一层(满二叉树继承而来) 最下层叶子结点一定集中在左 部连续位置。 倒数第二层,如有叶子节点,一定出现在右部连续位置。 同样结点树的二叉树,完全二叉树的深度最小

剑指offer——java刷题总结【三】

最后都变了- 提交于 2020-01-19 03:36:07
Note 题解汇总: 剑指offer题解汇总 代码地址: Github 剑指offer Java实现汇总 点击目录中的题名链接可直接食用题解~ 有些解法博文中未实现,不代表一定很难,可能只是因为博主太懒```(Orz) 如果博文中有明显错误或者某些题目有更加优雅的解法请指出,谢谢~ 目录 题号 题目名称 21 栈的压入、弹出序列 22 从上往下打印二叉树 23 二叉搜索树的后序遍历序列 24 二叉树中和为某一值的路径 25 复杂链表的复制 26 二叉搜索树与双向链表 27 字符串的排列 28 数组中出现次数超过一半的数字 29 最小的K个数 30 连续子数组的最大和 正文 21、栈的压入、弹出序列 题目描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的) 题目分析 解法一: 设置一个指向pop数组的index指针,遍历push数组,针对每一个遍历值做如下操作: 1、将当前遍历值压入栈中; 2、查看栈顶元素和pop数组的当前弹出值是否相等,如果相等则模拟出栈操作,将stack的栈顶元素弹出,并对pop数组的指针进行后移

二叉树

牧云@^-^@ 提交于 2020-01-18 23:36:19
二叉树 二叉树的概念 定义:每个节点最多只能有两个子节点的一种形式称之为二叉树 二叉树的节点分为左节点和右节点 图示: 满二叉树:二叉树的所有叶子节点(无分叉的节点)都在最后一层,并且总结点数为2 n - 1,n为层数 图示: 完全二叉树:所有的叶子节点都在最后一层或者是倒数第二层,并且最后一层左边连续,倒数第二层右边连续。连续就是都是这一层的。 图示: 二叉树的遍历方式 基本概念 前序遍历:先输出父节点,在遍历左子树和右子树 中序遍历:先遍历左子树,在输出父节点,在遍历右子树 后序遍历:先遍历左子树,再遍历右子树,最后输出父节点 ** 父节点的输出先后决定其实遍历的顺序** 思路分析 创建一个二叉树 遍历: 前序遍历: 输出当前节点 判断:如果左子节点不为空,那就继续前序遍历 判断:如果右子节点不为空,那就继续前序遍历 中序遍历: 如果当前节点的左子节点不为空,则递归中序遍历 输出当前节点 如果当前节点右子节点不为空,那就递归中序遍历 后序遍历: 如果当前节点的左子节点不为空,那就递归左子节点 如果当前节点的右子节点不为空,那就递归右子节点 输出当前节点 代码实现: class BinaryTree { //二叉树有必须有根节点 private HeroNode root ; public BinaryTree ( HeroNode root ) { this . root =

102. 二叉树的层次遍历

时光总嘲笑我的痴心妄想 提交于 2020-01-18 04:01:05
非递归算法: 用队列,关键是对入队的结点进行划分,计算当前层次的结点总数; 一,下一层的结点总数的计算: 法一: 从上一层第一个结点开始出队到上一层最后一个结点出对完成时,下一层所有结点刚好完成了入队操作;在此段时间内不断更新计数器可计算出下一层的节点总数;此时用下一层结点总数更新当前结点总数值; 法二: 外层每一次循环(while(){})都是一层,所以直接在外层调用 queue.size()即为当前层次结点的总数; 二,List<List>类型(以线性表为元素的线性表)的集合的操作; 声明:List<List> list = new ArrayList<List< Integer >>(); 添加外层表的元素:list.add(new ArrayList()); 添加表的表的元素(整型值)list.get(level).add(tmp.val); 三,队列的使用 声明:Queue queue = new LinkedList(); 入队:queue.add(root); 出队:tmp = queue.remove(); 判断队空:queue.isEmpty() /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode

【LeetCode】N叉树的前序遍历

邮差的信 提交于 2020-01-18 01:30:42
给定一个 N 叉树,返回其节点值的 前序遍历 。 例如,给定一个 3叉树 : 返回其前序遍历: [1,3,5,6,2,4] 。 /* // Definition for a Node. class Node { public int val; public List<Node> children; public Node() {} public Node(int _val) { val = _val; } public Node(int _val, List<Node> _children) { val = _val; children = _children; } }; */ class Solution { ArrayList<Integer> list = new ArrayList(); public List<Integer> preorder(Node root) { helper(root); return list; } public void helper(Node root) { if(root == null) { return; } list.add(root.val); int s = root.children.size(); for(int i = 0; i < s; i++) { helper(root.children.get(i)); } } }

递归 VS 非递归 内涵

空扰寡人 提交于 2020-01-16 05:13:08
递归与非递归转换的基础知识是能够正确理解三种树的遍历方法:前序,中序和后序,第一篇就是关于这三种遍历方法的递归和非递归算法。 一、为什么要学习递归与非递归的转换的实现方法? 1)并不是每一门语言都支持递归的。 2)有助于理解递归的本质。 3)有助于理解栈,树等数据结构。 二、三种遍历树的递归和非递归算法 递 归与非递归的转换基于以下的原理:所有的递归程序都可以用树结构表示出来。需要说明的是,这个”原理”并没有经过严格的数学证明,只是我的一个猜 想,不过在至少在我遇到的例子中是适用的。学习过树结构的人都知道,有三种方法可以遍历树:前序,中序,后序。理解这三种遍历方式的递归和非递归的表达方 式是能够正确实现转换的关键之处,所以我们先来谈谈这个。需要说明的是,这里以特殊的二叉树来说明,不过大多数情况下二叉树已经够用,而且理解了二叉树的 遍历,其它的树遍历方式就不难了。 1)前序遍历 a)递归方式: void preorder_recursive(Bitree T) /* 先序遍历二叉树的递归算法 */ { if (T) { visit(T); /* 访问当前结点 */ preorder_recursive(T->lchild); /* 访问左子树 */ preorder_recursive(T->rchild); /* 访问右子树 */ } } b)非递归方式 void preorder

二叉树递归遍历(前序,中序,后序)

谁都会走 提交于 2020-01-13 02:31:25
1.Java 中没有 Tree 的数据结构,不过我们可以自己写一个: public class TreeNode { int val; TreeNode left; TreeNode right; public TreeNode(int val) { this.val = val; } public TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } 2.初始化遍历的树 . TreeNode t4=new TreeNode(4,null,null); TreeNode t8=new TreeNode(8,null,null); TreeNode t6=new TreeNode(6,t4,t8); TreeNode t12=new TreeNode(12,null,null); TreeNode t16=new TreeNode(16,null,null); TreeNode t14=new TreeNode(14,t12,t16); TreeNode t10=new TreeNode(10,t6,t14); 3.前序遍历 public static void preOrder(TreeNode treeNode){