一、二叉树种类
1、满二叉树:如果一颗二叉树只有度为0和2的节点,并且只有最后一层节点度为0。
2、完全二叉树:除了底层节点可能没满,其余层均满,并且最后一层节点集中在最左边。
3、二叉搜索树:是一个有序树,满足左子节点值小于父节点值,右子节点值大于父节点值,同时左右子树也满足二叉搜索树。
4、平衡二叉搜索树(AVL):它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉搜索树
5、另一种平衡二叉搜索树:红黑树,性质
- 根节点是黑色的,叶子节点是不存储数据的黑色空节点
- 任何相邻的两个节点不能同时为红色(即红节点的两个子节点均为黑节点)
- 任意节点到其可到达的叶子节点包含相同数目的黑节点
6、红黑树和AVL树的区别
- 调整平衡的实现机制不同: 红黑树根据节点颜色约束实现;AVL树根据平衡因子。
- 红黑树的插入效率更高:红黑树不严格要求达到平衡,降低对旋转的要求,而AVL树旋转次数更多,插入效率降低。
- 红黑树统计性能更高
- AVL查找效率高
- 查找次数远远大于插入和删除的时候,选择AVL树。否则选择红黑树。
二、二叉树的遍历
二叉树主要有两种遍历方式,深度优先搜索和广度优先搜索,深度优先搜索又可以分为前序、中序、后序遍历,广度优先搜索包括层序遍历。
1、前序遍历
分为递归和迭代两种方法
//递归方式
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new LinkedList<>();
traversal(root, res);
return res;
}
public void traversal(TreeNode root, List<Integer> list) {
if(root == null) return;
list.add(root.val);//中
traversal(root.left, list);//左
traversal(root.right, list);//右
}
}
//迭代法
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new LinkedList<>();
if(root == null) return res;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while(!stack.isEmpty()) {
TreeNode node = stack.pop();
res.add(node.val);
if(node.right != null) stack.push(node.right);
if(node.left != null) stack.push(node.left);
}
return res;
}
}
2、中序遍历
//递归方式
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new LinkedList<>();
traversal(root, res);
return res;
}
public void traversal(TreeNode root, List<Integer> list) {
if(root == null) return;
traversal(root.left, list);//左
list.add(root.val);//中
traversal(root.right, list);//右
}
}
//迭代法
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new LinkedList<>();
Stack<TreeNode> stack = new Stack<>();
TreeNode node = root;
while(node != null || !stack.isEmpty()){
if(node != null) {
stack.push(node);//左
node = node.left;
} else{
TreeNode temp = stack.pop();
res.add(temp.val); //中
node = temp.right; //右
}
}
return res;
}
}
3、后序遍历
//递归方式
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new LinkedList<>();
traversal(root, res);
return res;
}
public void traversal(TreeNode root, List<Integer> list) {
if(root == null) return;
traversal(root.left, list);//左
traversal(root.right, list);//右
list.add(root.val);//中
}
}
//迭代法
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new LinkedList<>();
if(root == null) return res;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while(!stack.isEmpty()) {
TreeNode node = stack.pop();
res.add(node.val);
if(node.left != null) stack.push(node.left);
if(node.right != null) stack.push(node.right);
}
Collections.reverse(res);
return res;
}
}
4、层序遍历
//递归法
class Solution {
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> levelOrder(TreeNode root) {
ceng(root, 0);
return res;
}
public void ceng(TreeNode node, int deep) {
if(node == null) return;
deep++;
if(res.size() < deep) {
List<Integer> list = new ArrayList<>();
res.add(list);
}
res.get(deep - 1).add(node.val);
ceng(node.left, deep);
ceng(node.right, deep);
}
}
//迭代法,借助队列
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
if(root == null) return res;
Queue<TreeNode> que = new LinkedList<>();
que.add(root);
while(!que.isEmpty()) {
int length = que.size();
List<Integer> list = new ArrayList<>();
while(length > 0) {
TreeNode temp = que.poll();
list.add(temp.val);
if(temp.left != null) que.add(temp.left);
if(temp.right != null) que.add(temp.right);
length--;
}
res.add(list);
}
return res;
}
}