二叉树(BinaryTree) ◼ 二叉树的特点
每个节点的度最大为 2(最多拥有 2 棵子树)
左子树和右子树是有顺序的
即使某节点只有一棵子树,也要区分左右子树
◼ 二叉树是有序树 还是 无序树?
有序树
二叉树的性质:
非空二叉树的第i层,最多有2^i-1个节点(i≥1)
在高度为h的二叉树上最多有2h-1个结点(h≥1)
对于任何一棵非空二叉树,如果叶子节点个数为n0,度为2的节点个数为n2,则有: n0= n2+1
假设度为1的节点个数为n1,那么二叉树的节点总数n = n0 + n1 + n2
二叉树的边数T =n1+ 2*n2 = n- 1 = n0 + n1 + n2-1
因此n0 = n2+ 1
边的计算:
从结点度数看:结点度数就是边数
从结点看: 每个节点顶部都有一条边,整棵树除了根节点都有一条边
真二叉树(Proper Binary Tree)
满二叉树(Full Binary Tree) 满二叉树:所有节点的度都要么为0,要么为2。且所有的叶子节点都在 最后一层
在同样高度的二叉树中,满二叉树的叶子节点数量最多、总节点数量最多
满二叉树一定是真二叉树,真二叉树不一定是满二叉树
假设满二叉树的高度为h (h≥ 1),那么
第i层的节点数量:2^(i-1)
叶子节点数量: 2^(h-1)
总节点数量n
n= 2^h -1 = 2^0+2^1+2^2+…+ 2^(h-1)
h = log2(n+ 1)
二叉树的遍历: 前序遍历(Preorder Traversal)
中序遍历(Inorder Traversal)
后序遍历(Postorder Traversal)
层序遍历(Level Order Traversal)
前序遍历:
递归实现: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 public class BinaryTreePreorderTraversal { public List<Integer> preorderTraversal (TreeNode root) { List<Integer> list = new LinkedList<>(); traverse(root, list); return list; } private void traverse (TreeNode root, List<Integer> list) { if (root == null ) { return ; } list.add(root.val); traverse(root.left, list); traverse(root.right, list); } public static void main (String[] args) { BinaryTreePreorderTraversal binaryTreePreorderTraversal = new BinaryTreePreorderTraversal(); TreeNode newNodeA = new TreeNode(1 ); TreeNode newNodeB = new TreeNode(2 ); TreeNode newNodeC = new TreeNode(3 ); newNodeA.right = newNodeB; newNodeA.left = null ; newNodeB.left = newNodeC; newNodeB.right = null ; newNodeC.right = null ; newNodeC.left = null ; binaryTreePreorderTraversal.preorderTraversal(newNodeA).stream().forEach(e->{ System.out.print(e+"," ); }); } }
中序遍历(Inorder Traversal)
递归实现: 1 2 3 4 5 6 7 8 9 10 11 12 private void traverse (TreeNode root, List<Integer> list) { if (root == null ) { return ; } traverse(root.left, list); list.add(root.val); traverse(root.right, list); }
栈实现: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public List<Integer> inorderTraversalByStack (TreeNode root) { List<Integer> list = new ArrayList<>(); ; while (root!=null ||! stk.isEmpty()){ while (root!=null ){ stk.push(root); root=root.left; } root = stk.pop(); list.add(root.val); root=root.right; } return list; }
后序遍历(Postorder Traversal)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public List<Integer> postorderTraversal (TreeNode root) { LinkedList<Integer> res = new LinkedList(); traverse(root, res); return res; } public void traverse (TreeNode root, List<Integer> res) { if (root == null ) { return ; } traverse(root.left, res); traverse(root.right, res); res.add(root.val); }
栈实现: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public List<Integer> postorderTraversalByStack (TreeNode root) { LinkedList<Integer> res = new LinkedList(); if (root == null ) { return res; } TreeNode prev = null ; Deque<TreeNode> stack = new LinkedList(); while (root != null || !stack.isEmpty()) { while (root != null ) { stack.push(root); root = root.left; } root = stack.pop(); if (root.right == null || root.right == prev) { res.add(root.val); prev = root; root = null ; } else { stack.push(root); root = root.right; } } return res; }
层序遍历: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 @author * @date : 2022 /3 /6 */ public List<List<Integer>> levelOrder(TreeNode root) { List<List<Integer>> list = new ArrayList<>(); Deque<TreeNode> que = new LinkedList(); que.addLast(root); List<Integer> eachLayer ; if (root==null ){ return Collections.emptyList(); } while (!que.isEmpty()){ int count = que.size(); eachLayer = new ArrayList<>(); while ( count>0 ){ TreeNode first = que.pop(); eachLayer.add(first.val); if (first.left!=null ){ que.addLast(first.left); } if (first.right!=null ){ que.addLast(first.right); } count--; } list.add(eachLayer); } return list; } }
完全二叉树(Complete Binary Tree)
完全二叉树:叶子节点只会出现最后2层,且最后1层的叶子结点都靠左对齐
从上到下,从左到右依次排列
叶子节点只会出现最后2层,最后1层的叶子结点都靠左对齐
完全二叉树从根结点至倒数第⒉层是一棵满二叉树
满二叉树一定是完全二叉树,完全二叉树不一定是满二叉树
完全二叉树性质:
面试题
1 2 3 System.out.println(5 /2 ); System.out.println(5 >>2 );/1
二叉搜索树(Binary Search Tree): ◼ 在 n 个动态的整数中搜索某个整数?(查看其是否存在)
◼ 假设使用动态数组存放元素,从第 0 个位置开始遍历搜索,平均时间复杂度:O(n)
◼ 如果维护一个有序的动态数组,使用二分搜索,最坏时间复杂度:O(logn)
但是添加、删除的平均时间复杂度是 O(n)
◼ 针对这个需求,有没有更好的方案?
使用二叉搜索树,添加、删除、搜索的最坏时间复杂度均可优化至:O(logn)
◼ 二叉搜索树是二叉树的一种,是应用非常广泛的一种二叉树,英文简称为 BST
又被称为:二叉查找树、二叉排序树
任意一个节点的值都大于其左子树所有节点的值
任意一个节点的值都小于其右子树所有节点的值
它的左右子树也是一棵二叉搜索树
◼ 二叉搜索树可以大大提高搜索数据的效率
◼ 二叉搜索树存储的元素必须具备可比较性
比如 int、double 等
如果是自定义类型,需要指定比较方式
不允许为 null
接口设计 ◼ int size() // 元素的数量 ◼ boolean isEmpty() // 是否为空
◼ void clear() // 清空所有元素
◼ void add(E element) // 添加元素
◼ void remove(E element) // 删除元素
◼ boolean contains(E element) // 是否包含某元素
删除结点: 度为2的结点:
先从前驱或者后继节点的值覆盖原结点的值