树形结构
生活中的树形结构
树的基本概念1
其中子树可以从子节点的个数入手,如2节点的子树个数为2(见下图)
树的基本概念2
有序树,无序树,森林
二叉树
二叉树的性质
真二叉树
满二叉树
完全二叉树
完全二叉树的性质
完全二叉树高度与节点数之间的关系应该牢记,同时树上节点与其父节点、左子节点、右子节点编号之间的关系也应该牢记
上图编号从1开始,若编号从0开始(见下图),则公式有所变化,这个需要实际运用时灵活变通
做道面试题
这道题目使用好完全二叉树边数与节点数之间的关系,可以得出n0 = n2+1,还要注意的是完全二叉树的n1(度为1的节点数)要么是0要么是1。有上述分析,相信后面得出答案是十分简单的。
国外教材的说法
二叉树的遍历
前序遍历
前序遍历非递归实现
方法一:
方法二:
中序遍历
中序遍历非递归
后序遍历
后序遍历非递归
层序遍历
三种四则运算
表达式数
遍历的应用
刷几道leetcode题
方法一(深度优先搜索):
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public int maxDepth(TreeNode root) {
if(root == null)
return 0;
int lh = maxDepth(root.left);
int rh = maxDepth(root.right);
return Math.max(lh,rh)+1;
}
}
方法二(广度优先搜索):
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public int maxDepth(TreeNode root) {
if(root == null)
return 0;
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(root);
int ans = 0;
while(!queue.isEmpty()){
int size = queue.size();
while(size>0){
TreeNode node = queue.poll();
size--;
if(node.left!=null)
queue.offer(node.left);
if(node.right!=null)
queue.offer(node.right);
}
ans++;
}
return ans;
}
}
这题目跟上题其实十分类似,我这里就用一下深搜吧
提交的答案
class Solution {
public int countNodes(TreeNode root) {
if(root == null)
return 0;
int lnode_num = countNodes(root.left);
int rnode_num = countNodes(root.right);
return lnode_num + rnode_num + 1;
}
}
提交的答案
class Solution {
public TreeNode invertTree(TreeNode root) {
if(root == null)
return null;
TreeNode left = invertTree(root.left);
TreeNode right = invertTree(root.right);
root.right = left;
root.left = right;
return root;
}
}
重构二叉树
说白了就是能否根据遍历结果推出唯一的二叉树
通过先序或后序遍历确定根节点,并通过中序遍历的结果,就能确定左右子树的元素。这方面自己做几道例题都能清楚了。
二叉搜索树
二叉搜索树比起动态数组来说,时间复杂度上有了很大的优化(见下图)
二叉搜索树的性质
二叉树搜索树添加节点
删除度为0的叶子节点
删除度为1的节点
删除度为2的节点
前驱节点和后继节点
前驱节点:二叉树中序遍历时的前一个节点,二叉搜索树中左子树的最大节点
后继节点:二叉树中序遍历时的后一个节点,二叉搜索树中右子树的最小节点
平衡二叉搜索树
二叉搜索树存在一个问题,由于插入的顺序可能导致二叉搜索树退化成链表
由此引入了平衡的概念
二叉搜索树的改进
AVL树
添加导致的失衡
添加导致失衡的修复
下图中n的意思是node,p的意思是parent,g的意思是grandparent(添加导致失衡的节点)
LL指的是n在g的左左
LL可以通过对g进行右旋转修复(具体过程自己找视频看吧,文字难以解释)
RR的情况则对g节点进行左旋转
LR,先对p节点进行左旋转,再对g节点进行右旋转
RL,先对p节点进行右旋转,再对g节点进行左旋转
zig和zag
删除导致的失衡
失衡后的恢复同样是通过判断LL、RR、LR、RL四种情况进行恢复
AVL树总结
刷道leetcode
提交的答案
class Solution {
public int height(TreeNode root){
if(root == null)
return 0;
int lh = height(root.left);
int rh = height(root.right);
return Math.max(lh,rh) + 1;
}
public boolean isBalanced(TreeNode root) {
if(root == null)
return true;
return ((Math.abs(height(root.left) - height(root.right)) <= 1) && isBalanced(root.left) && isBalanced(root.right));
}
}