树的定义 |
1、非空树有且只有一个根节点 2、子树互不相交
树的节点:包含一个数据元素和若干指向其它子树的分支 节点的度:节点拥有的子树数 叶节点:度为0的节点 树的度:树内节点的度的最大值
孩子:节点的子树的根,该节点称为孩子的双亲 节点的祖先:从根节点到该节点所经分支上的所有节点
堂兄弟:双亲在同一层的节点 树的深度:树中节点的最大深度 |
树的存储结构 |
双亲表示法:每个节点中,设置一个指示器指示双亲在链表中的位置
|
二叉树 |
1、每个节点最多有两颗子树 2、左子树右子树是有顺序的,不能颠倒的
二叉树的五种形态: 1、空二叉树 2、只有一个根节点 3、根节点只有左子树 4、根节点只有右子树 5、根节点既有左子树又有右子树
特殊树: 1、斜树:所有节点都只有左子树叫做左斜树,都只有右子树叫做右斜树
2、满二叉树:所有分支节点都存在左子树和右子树,并且所有叶子都在同一层
3、完全二叉树:对于一颗有N个节点的二叉树按层序编号,如果编号为 i (1<= i <= N)的节点与同样深度的满二叉树中编号为 i 的节点在二叉树中的位置完全相同,这种二叉树叫完全二叉树
完全二叉树不一定是满二叉树,满二叉树一定是完全二叉树
完全二叉树特点: (1)叶子节点只能出现在最下面两层 (2)最下层的叶子一定集中在左部连续位置 (3)倒数第二层,若有叶子节点,一定集中在右部连续位置 (4)同样节点数的二叉树,完全二叉树深度最小
判断是否是完全二叉树的方法:给每个节点按照满二叉树的结构按层编号,如果编号出现空档,就说明不是完全二叉树
二叉树的性质: (1)在二叉树的i层上至多有2^(i - 1)个节点 (2)深度为k的二叉树至多有2^k - 1个节点(1+2+4.。。) (3)对任何一颗二叉树T,如果其终端节点的数为n0,度为2的节点数为n1,则n0 = n1 + 1; (4)具有N个节点的完全二叉树的深度为⌊log2N⌋ + 1;(满二叉树 N = 2^K - 1, 完全二叉树 2^(K - 1) - 1 < N <= 2^K - 1, 2^(K - 1) <= N <2^K)
|
二叉树的存储结构 |
顺序存储结构:按层序编号,完全二叉树的优势就体现;一般的二叉树,把不存在的节点位置为'^' 缺点:空间浪费,比如深度为K的右斜树,所以顺序存储结构一般用于完全二叉树 |
二叉树遍历
前序遍历:先访问根节点,再遍历左子树,最后遍历右子树
中序遍历:先遍历左子树,再访问根节点,最后遍历右子树
应用:对于二叉搜索树,我们可以通过中序遍历得到一个递增的有序序列。
后序遍历:先遍历左子树,再遍历右子树,最后访问根节点
应用:
1、删除节点的时候,按照后序遍历的方式进行,先删除左节点,再删除右节点,最后删除节点本身
2、数学表达式中用后序遍历来解析后缀表达式;中序遍历可以将后缀转中缀
写法:递归、迭代、莫里斯遍历
线索二叉树
原理 |
1、二叉树许多空指针的存在(n个节点,2n个指针域,(n-1)条分支,所以有n+1个空指针) 2、二叉树可以知道子节点的地址,但是只有经过遍历之后才知道前驱和后继 3、所以可以利用空指针指向某种遍历序列下的前驱和后继节点 |
概念 |
线索:指向前驱和后继的指针 线索链表:加上线索的二叉链表 线索二叉树:线索链表相应的二叉树 线索化:对二叉树以某种次序遍历使其变成线索二叉树的过程
线索化的实质是将二叉树的空指针改为指向前驱或后继的线索
|
leetcode总结
树的遍历 | |
(1)题目 Binary Tree Preorder Traversal Binary Tree Postorder Traversal Binary Tree Level Order Traversal Binary Tree Level Order Traversal II Binary Tree Zigzag Level Order Traversal (2)分类
| |
树的深度优先遍历 | |
中序, 先序和后序三种方式, 不过结点遍历的方式是相同的, 只是访问的时间点不同而已, 对应于Binary Tree Inorder Traversal, Binary Tree Preorder Traversal和Binary Tree Postorder Traversal这三道题目。
(1)实现方式
递归左右结点, 直到结点为空作为结束条件就可以, 哪种序就取决于你访问结点的时间。
一个栈手动模拟递归的过程 前序和中序遍历就是不断往左走的过程节点入栈,走到底之后节点出栈,走右边; 后序遍历往左走到底之后不能根节点直接出栈,因为遍历完右子树,还要将根节点添加到vector中 要判断是从左子树回到的根节点还是从右子树回到的根节点(可以用哈希表) 如果是从左子树回到根节点,此时应转到右子树; 如果从右子树回到的根节点,应该将当前节点弹出加入到vector中
另一种后序遍历迭代的思路: 类似前序(根-右-左)+反转 (2)时间和空间复杂度
解决方法:Morris遍历方法用了线索二叉树,这个方法不需要为每个节点额外分配指针指向其前驱和后继结点,而是利用叶子节点中的右空指针指向中序遍历下的后继节点就可以了。这样就节省了需要用栈来记录前驱或者后继结点的额外空间, 所以可以达到O(1)的空间复杂度。 缺点:这种方法有一个问题就是会暂时性的改动树的结构 | |
树的广度优先搜索 | |
层序遍历,LeetCode中有三种自顶向下层序, 自底向上层序和锯齿层序遍历, 对应于Binary Tree Level Order Traversal, Binary Tree Level Order Traversal II和Binary Tree Zigzag Level Order Traversal。
其实层序遍历也可以用DFS,只要加上level标记
自顶向下层序:思路就是维护一个队列存储上一层的结点, 逐层访问。(可以加上level标记) 自底向上层序:思路之一就是把自顶向下层序遍历得到的层放入数据结构然后reverse过来
锯齿形层次遍历:实现逆序(最晚入列最先访问),用双栈(一个栈出栈上一层节点,另一个栈入栈保存该层节点),添加的时候对层数进行奇偶数判断,奇数时,先入右节点,再入左节点;偶数树,先入左节点,再入右节点 |
树的构造 | ||||
(1)题目
Convert Sorted Array to Binary Search Tree Convert Sorted List to Binary Search Tree Construct Binary Tree from Preorder and Inorder Traversal Construct Binary Tree from Inorder and Postorder Traversal Convert Sorted Array to Binary Search Tree:
Convert Sorted List to Binary Search Tree:
Construct Binary Tree from Inorder and Postorder Traversal: 主要问题是如何将节点劈成左右两部分进行递归
Construct Binary Tree from Preorder and Inorder Traversal:
总结: 统一的思路是找到根节点,然后递归左右子树 | ||||
树的性质 | |||||
LeetCode中关于树的性质有以下题目: | |||||
|
树的求和 | ||||
(1)题目: Path Sum
| ||||
给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。
求根到叶子节点数字之和
二叉树中的最大路径和
总结: 总体来说,求和路径有以下三种:(1)根到叶子结点的路径;(2)父结点沿着子结点往下的路径;(3)任意结点到任意结点(也就是看成无向图) |