后序遍历

二叉搜索树的后序遍历序列

三世轮回 提交于 2019-11-29 08:56:05
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。假设输入的数组的任意两个数字都互不相同。 例如,下图是后序遍历序列 1,3,2 所对应的二叉搜索树。 使用递归的方式,先判断数组的左子树和右子树的位置 然后再判断左子树和右子树是不是二叉搜索树。 public boolean VerifySquenceOfBST(int[] sequence) { if (sequence == null || sequence.length == 0) return false; return verify(sequence, 0, sequence.length - 1); } private boolean verify(int[] sequence, int first, int last) { if (last - first <= 1) return true; int rootVal = sequence[last]; int cutIndex = first; while (cutIndex < last && sequence[cutIndex] <= rootVal) cutIndex++; for (int i = cutIndex; i < last; i++) if (sequence[i] < rootVal) return false; return

二叉树的递归与非递归遍历

為{幸葍}努か 提交于 2019-11-29 08:18:53
二叉树的递归与非递归遍历 前序遍历二叉树 递归遍历 非递归遍历 中序遍历二叉树 递归遍历 非递归遍历 后序遍历二叉树 递归遍历 非递归遍历 将二叉树遍历的结果保存到vector中返回。 递归遍历代码简短,也相对容易理解,此不赘述。咱们重点来看一下非递归遍历。 前序遍历二叉树 递归遍历 void preORecursive(TreeNode* pRoot, vector<int>& vec) { if(pRoot == NULL) return; vec.push_back(pRoot->val); preORecursive(pRoot->left, vec); preORecursive(pRoot->right, vec); } vector<int> preOrderRecursive(TreeNode* pRoot) { vector<int> vec; if(pRoot == NULL) return vec; preORecursive(pRoot, vec); return vec; } 非递归遍历 思想: 栈后法,右左子孩子入栈法 ///栈后法,右左子孩子入栈法 vector<int> preOrder(TreeNode* pRoot) { vector<int> vec; stack<TreeNode*> sta; if(pRoot) { vec.push

二叉树遍历(前、中、后序及层序遍历)

倾然丶 夕夏残阳落幕 提交于 2019-11-29 06:57:37
二叉树的遍历 所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个节点均做一次且仅做一次的访问。访问节点所做的操作依赖于具体的应用问题。遍历是二叉树上最重要的运算之一。是二叉树上进行其它运算的基础。 如何将所有节点都遍历打印出来?经典的方法有三种:前序遍历、中序遍历、后序遍历。除此之外,还有按层遍历。其中,前、中、后序表示的是节点和它左右子树节点遍历打印的先后顺序。 前序遍历是指,对树中的任意节点,先打印这个节点本身,然后再打印它的左子树,最后打印它的右子树。 中序遍历是指,对树中的任意节点,先打印它的左子树,然后再打印这个节点本身,最后打印它的右子树。 后序遍历是指,对树中的任意节点,先打印它的左子树,然后再打印它的右子树,最后打印这个节点本身。 层次遍历是指,从第一层(根节点)开始,从上到下一层一层遍历,同层之间按从左到右的顺序依次遍历节点。 实际上,二叉树的前、中、后序遍历就是一个递归的过程。比如,前序遍历就是先打印根节点,然后再递归的打印左子树,最后递归的打印右子树。 二叉树的前、中、后序遍历的递归实现: /** Java版 * public class TreeNode{ * int val; * TreeNode left; * TreeNode right; * TreeNode(int x){ val = x; } */ // 前序遍历 public

二叉树

旧巷老猫 提交于 2019-11-29 05:11:54
前言 树是数据结构中的重中之重,尤其以各类二叉树为学习的难点。一直以来,对于树的掌握都是模棱两可的状态,现在希望通过写一个关于二叉树的专题系列。在学习与总结的同时更加深入的了解掌握二叉树。本系列文章将着重介绍一般二叉树、完全二叉树、满二叉树、 线索二叉树 、 霍夫曼树 、 二叉排序树 、平衡二叉树、红黑树、B树。希望各位读者能够关注专题,并给出相应意见,通过系列的学习做到心中有“树”。 1 重点概念 1.1 结点概念 结点是数据结构中的基础,是构成复杂数据结构的基本组成单位。 1.2 树结点声明 本系列文章中提及的结点专指树的结点。例如:结点A在图中表示为: 2 树 2.1 定义 树(Tree)是n(n>=0)个结点的有限集。n=0时称为空树。在任意一颗非空树中: 1)有且仅有一个特定的称为根(Root)的结点; 2)当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1、T2、......、Tn,其中每一个集合本身又是一棵树,并且称为根的子树。 此外,树的定义还需要强调以下两点: 1)n>0时根结点是唯一的,不可能存在多个根结点,数据结构中的树只能有一个根结点。 2)m>0时,子树的个数没有限制,但它们一定是互不相交的。 示例树: 图2.1为一棵普通的树: 图2.1 普通树 由树的定义可以看出,树的定义使用了递归的方式。递归在树的学习过程中起着重要作用

【树论】求先序遍历

僤鯓⒐⒋嵵緔 提交于 2019-11-29 02:22:05
原题传送门 题目 题目描述 给出一棵二叉树的中序与后序排列。求出它的先序排列。(约定树结点用不同的大写字母表示)。 输入输出格式 输入格式: 2行,均为大写字母组成的字符串,表示一棵二叉树的中序与后序排列。 输出格式: 1行,表示一棵二叉树的先序。 思路 首先,一点基本常识,给你一个后序遍历,那么最后一个就是根(如ABCD,则根为D)。 因为题目求先序,意味着要不断找根。 中序ACGDBHZKX,后序CDGAHXKZB,首先可找到主根B; 那么我们找到中序遍历中的B,由这种遍历的性质,可将中序遍历分为ACGD和HZKX两棵子树, 那么对应可找到后序遍历CDGA和HXKZ(从头找即可) 从而问题就变成求1.中序遍历ACGD,后序遍历CDGA的树 2.中序遍历HZKX,后序遍历HXKZ的树; 接着递归,按照原先方法,找到1.子根A,再分为两棵子树2.子根Z,再分为两棵子树。 就按这样一直做下去(先输出根,再递归); 模板概括为step1:找到根并输出 step2:将中序,后序各分为左右两棵子树; step3:递归,重复step1,2; Code #include<cstdio> #include<iostream> #include<cstring> using namespace std; void beford(string in,string after){ if (in

LeetCode 145. 二叉树的后序遍历 (用栈实现后序遍历二叉树的非递归算法)

早过忘川 提交于 2019-11-29 02:12:49
题目链接: https://leetcode-cn.com/problems/binary-tree-postorder-traversal/ 给定一个二叉树,返回它的 后序 遍历。 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [3,2,1] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: vector<int> postorderTraversal(TreeNode* root) { vector<int> result; if(root==nullptr) return result; stack<TreeNode*> s; TreeNode *p=root,*r=nullptr; while(p||!s.empty()){ if(p){ s.push(p); p=p->left; }else{ p=s.top(); if(p->right&&p->right!

数据结构--树的非递归遍历

主宰稳场 提交于 2019-11-28 22:33:42
树的递归遍历代码非常简单易懂,但是由于递归会占用非常多的栈空间,因此非递归的遍历树也是必须要掌握的。因此最近仔细分析了很多的代码以及理解了遍历的过程,最后敲一遍并在这里记录一下,以后可以快速回顾。一般来说,递归可以解决的问题也一定可以用栈加循环的方式解决,毕竟递归实质上就是利用了栈嘛。 树从根节点开始对每个结点进行遍历,每个结点必定被访问三次,如上图。 第一次碰到就访问就是先序,第二次碰到访问就是中序,第三次碰到访问就是后序。 public class Tree { public void preOrder(TreeNode t) { //先序遍历 Stack<TreeNode> s = new Stack<>(); while(t != null || !s.isEmpty()) { while(t != null) { System.out.println(t.val); //第一次碰到就访问结点 s.push(t); //压栈保存,以便左边访问完了,可以得到此结点的右节点 t = t.left; } if(!s.isEmpty()) { t = s.pop(); t = t.right; //当上述循环推出,说明左子树全访问完了,则把父结点弹出,准备访问右子树 } } } public void inOrder(TreeNode t) { //中序,与先序很像

二叉树遍历(非递归版)——python

久未见 提交于 2019-11-28 22:27:17
二叉树的遍历分为广度优先遍历和深度优先遍历 广度优先遍历 (breadth first traversal):又称层次遍历,从树的根节点(root)开始,从上到下从从左到右遍历整个树的节点。 深度优先遍历( depth first traversal):对于一颗二叉树,深度优先遍历是沿着树的深度遍历树的节点,尽可能深的搜索树的分支。深度优先遍历有重要的三种方法。这三种方式常被用于访问树的节点,它们之间的不同在于访问每个节点的次序不同。这三种遍历分别叫做 先序遍历 (preorder):根节点->左子树->右子树, 中序遍历 (inorder):左子树->根节点->右子树,和 后序遍历 (postorder):左子树->右子树->根节点。这三种都是递归方式实现对一整个二叉树遍历的哦。 代码(非递归版) class TreeNode: def __init__(self, x): self.val = x self.left = None self.right = None class Trees: #根据前序和中序列表来重建二叉树 def reConstructBinaryTree(self, pre, tin): # write code here if len(pre) == 0: return None if len(pre) == 1: return TreeNode(pre

面试常见二叉树算法题集锦-Java实现

亡梦爱人 提交于 2019-11-28 20:43:29
1.求二叉树的深度或者说最大深度 /* ***1.求二叉树的深度或者说最大深度 */ public static int maxDepth(TreeNode root){ if(root==null) return 0; int left=maxDepth(root.left); int right=maxDepth(root.right); return Math.max(left,right)+1; } 2.求二叉树的最小深度 /* ***2.求二叉树的最小深度 */ public static int MinDepth(TreeNode root){ if(root==null) return 0; if(root.left==null&&root.right==null) return 1; int left=MinDepth(root.left); int right=MinDepth(root.right); if(root.left==null||root.right==null) return Math.max(left,right)+1; return Math.min(left,right)+1; } 3.求二叉树中节点的个数 /* ***3.求二叉树中节点的个数 */ public static int nodeCount(TreeNode root){ if

二叉树(二叉树的性质及遍历)

☆樱花仙子☆ 提交于 2019-11-28 19:54:58
一、二叉树的性质 在二叉树的第 i 层上至多有 2 i-1 个节点。 深度为 k 的二叉树至多有 2 k -1 个节点。 对任意一棵二叉树 T ,若终端节点数为 n 0 ,而其度数为 2 的节点为 n 2 ,则 n 0 =n 2 +1。 具有 n 个节点的完全二叉树的深度为 。 二、单链表结点的存储结构描述 typedef struct Node { ElemType data; struct Node *next; }Node,*LinkList; LinkList 和 Node * 同为结构指针类型,这两种类型是等价的。通常习惯上用 LinkList 说明指针变量,强调它是某个单链表的头指针变量。例如,使用定义 LinkList L, 则 L 为单链表的头指针,从而提高程序的可读性。用 Node* 来定义指向单链表中结点的指针,例如, Node *p, 则 p 为指向单链表中结点的指针变量。 三、二叉树的遍历方式 先序遍历:根、左、右 中序遍历:左、根、右 后序遍历:左、右、根 #include <iostream> #include <malloc.h> using namespace std; //二叉树的节点 typedef struct BiTNode { char ch;; struct BiTNode *lchild;//左孩子 struct BiTNode