二叉树

1.二叉树遍历

1.1 前序遍历:按照根结点->左子树->右子树的顺序访问
在这里插入图片描述
1.2 中序遍历:按照左子树->根结点->右子树的顺序访问
在这里插入图片描述
1.3 后序遍历:按照左子树->右子树->根结点的顺序访问
在这里插入图片描述

2.前序遍历,中序遍历与后序遍历之间的推导

  1. 已知前序和中序:
     ①从前序中找根结点root1
     ②在中序中根据根结点root1将其分为左子树和右子树
     ③从前序中找左子树的根结点root2
     ④在中序中将左子树根据根结点root2将左子树又分为左子树和右子树
      循环上述过程,画出二叉树图,再得到后序遍历
  2. 已知中序和后序:
      提示:后序的最后一个为树的根结点
  3. 已知前序和后序:答案不唯一

3.二叉树的性质

  • 在二叉树的第i层上最多有2(i-1)个结点
  • 二叉树中如果深度为k(有k层),那么最多有2^k - 1个结点

4.二叉树的形态

  1. 完美二叉树(满二叉树 Perfect Binary Tree, BST)
     高度为k的二叉树有2^k - 1个结点
  2. 完全二叉树(Complete Binary Tree, CBT)
     从根结点到倒数第二层满足完美二叉树,最后一层可以不完全填充,其叶子结点都靠左对齐
     叶子结点的最大深度与最小深度差不超过1
  3. 完满二叉树(Full Binary Tree, FBT)
     所有非叶子结点的度都是2
  4. 三者的比较
    在这里插入图片描述
  5. 平衡二叉树(Balanced Binary Tree)
     任意结点的左子树与右子树高度差不超过1

5.二分搜索树(Binary Search Tree, BST)

5.1 二分搜索树的整体代码

import java.util.LinkedList;
import java.util.Queue;

public class BST<E extends Comparable<E>> {
	private class Node {
		public E e;
		public Node left;
		public Node right;

		public Node(E e) {
			this.e = e;
			this.left = null;
			this.right = null;
		}
	}

	private Node root;
	private int size;

	public BST() {
		root = null;
		size = 0;
	}

	public int size() {
		return size;
	}

	public boolean isEmpty() {
		return size == 0;
	}

	public void add(E e) {
		root = add(root, e);
	}

	// return the root node after add a new node
	private Node add(Node node, E e) {
		if (node == null) {
			size++;
			return new Node(e);
		}
		if (e.compareTo(node.e) < 0) {
			node.left = add(node.left, e);
		} else if (e.compareTo(node.e) > 0) {
			node.right = add(node.right, e);
		}
		return node;
	}

	public boolean contains(E e) {
		return contains(root, e);
	}

	private boolean contains(Node node, E e) {
		if (node == null) {
			return false;
		}
		if (e.compareTo(node.e) < 0) {
			return contains(node.left, e);
		} else if (e.compareTo(node.e) == 0) {
			return true;
		} else {
			return contains(node.right, e);
		}
	}

	public void preOrder(Node node) {
		if (node == null) {
			return;
		}
		System.out.println(node.e);
		preOrder(node.left);
		preOrder(node.right);
	}

	public void inOrder(Node node) {
		if (node == null) {
			return;
		}
		inOrder(node.left);
		System.out.println(node.e);
		inOrder(node.right);
	}

	public void postOrder(Node node) {
		if (node == null) {
			return;
		}
		postOrder(node.left);
		postOrder(node.right);
		System.out.println(node.e);
	}

	public void levelOrder() {
		Queue<Node> queue = new LinkedList<>();
		queue.add(root);
		while (!queue.isEmpty()) {
			Node cur = queue.remove();
			System.out.println(cur.e);
			if (cur.left != null) {
				queue.add(cur.left);
			}
			if (cur.right != null) {
				queue.add(cur.right);
			}
		}
	}

	public E minimum() {
		if (size == 0) {
			throw new IllegalArgumentException("BST is empty!");
		}
		return minimum(root).e;
	}

	private Node minimum(Node node) {
		if (node.left == null) {
			return node;
		}
		return minimum(node.left);
	}

	public E removeMin() {
		E ret = minimum();
		root = removeMin(root);
		return ret;
	}

	private Node removeMin(Node node) {
		if (node.left == null) {
			Node rightNode = node.right;
			node.right = null;
			size--;
			return rightNode;
		}
		node.left = removeMin(node.left);
		return node;
	}

	public E maximum() {
		if (size == 0) {
			throw new IllegalArgumentException("BST is empty!");
		}
		return maximum(root).e;
	}

	private Node maximum(Node node) {
		if (node.right == null) {
			return node;
		}
		return maximum(node.right);
	}

	public E removeMax() {
		E ret = maximum();
		root = removeMax(root);
		return ret;
	}

	private Node removeMax(Node node) {
		if (node.right == null) {
			Node leftNode = node.left;
			node.left = null;
			size--;
			return leftNode;
		}
		node.right = removeMax(node.right);
		return node;
	}

	public void remove(E e) {
		root = remove(root, e);
	}

	private Node remove(Node node, E e) {
		if (node == null) {
			return null;
		}
		if (e.compareTo(node.e) < 0) {
			node.left = remove(node.left, e);
			return node;
		} else if (e.compareTo(node.e) > 0) {
			node.right = remove(node.right, e);
			return node;
		} else {
			if (node.left == null) {
				Node rightNode = node.right;
				node.right = null;
				size--;
				return rightNode;
			}
			if (node.right == null) {
				Node leftNode = node.left;
				node.left = null;
				size--;
				return leftNode;
			}
			Node successor = minimum(node.right);
			successor.right = removeMin(node.right);
			successor.left = node.left;
			node.left = node.right = null;
			return successor;
		}
	}
}

5.2 add method

5.2.1 非递归实现(not recursion)

public void add(E e) {
    Node node = new Node(e);
    if (root == null) {
        root = node;
        size++;
    } else {
        Node temp = root;
        while (temp != null) {
            if (e.compareTo(temp.e) < 0) {
                if (temp.left == null) {
                    temp.left = node;
                    size++;
                    return;
                } else {
                    temp = temp.left;
                }
            } else {
                if (temp.right == null) {
                    temp.right = node;
                    szie++;
                    return;
                } else {
                    temp = temp.right;
                }
            }
        }
    }
}

5.2.2 递归实现(recursion)

public void add(E e) {
    if (root == null) {
        root = new Node(e);
        size++;
    } else {
        add(root, e);
    }
}

private void add(Node node, E e) {
    if (e.equals(node.e)) {
        return;
    } else if (e.compareTo(node.e) < 0 && node.left == null) {
        node.left = new Node(e);
        size++;
        return;
    } else if (e.compareTo(node.e) > 0 && node.right == null) {
        node.right = new Node(e);
        size++;
        return;
    }
    if (e.compareTo(node.e) < 0) {
        add(node.left, e);
    } else {
        add(node.right, e);
    }
}

5.2.3 递归实现(optimize and refactor recursion method)

// recurse method optimization and refactor
public void add(E e) {
    root = add(root, e);
}

//return the root node after add a new node
private Node add(Node node, E e) {
    if (node == null) {
        size++;
        return new Node(e);
    }
    if (e.compareTo(node.e) < 0) {
        node.left = add(node.left, e);
    } else if (e.compareTo(node.e) > 0) {
        node.right = add(node.right, e);
    }
    return node;
}

5.3 search method

5.3.1 非递归实现(not recursion)

public boolean contains(E e) {
    Node temp = root;
    while (temp != null) {
        if (e.compareTo(temp.e) == 0) {
            return true;
        } else if (e.compareTo(temp.e) < 0) {
            temp = temp.left;
        } else {
            temp = temp.right;
        }
    }
    return false;
}

5.3.2 递归实现(recursion)

public boolean contains(E e) {
    return contains(root, e);
}

private boolean contains(Node node, E e) {
    if (node == null) {
        return false;
    }
    if (e.compareTo(node.e) < 0) {
        return contains(node.left, e);
    } else if (e.compareTo(node.e) == 0) {
        return true;
    } else {
        return contains(node.right, e);
    }
}

5.4 traversal method

5.4.1 非递归实现(not recursion)

用到了栈(stack)实现

public void preOrder() {
    Stack < Node > stack = new Stack < > ();
    stack.push(root);
    while (!stack.isEmpty()) {
        Node cur = stack.pop();
        System.out.println(cur.e);
        if (cur.right != null) {
            stack.push(cur.right);
        }
        if (cur.left != null) {
            stack.push(cur.left);
        }
    }
}

5.4.2 递归实现(recursion)

public void preOrder(Node node) {
    if (node == null) {
        return;
    }
    System.out.println(node.e);
    preOrder(node.left);
    preOrder(node.right);
}

6.AVL树

6.1 AVL树的左旋与右旋

6.1.1 AVL树的左旋与右旋的规则

在这里插入图片描述

6.1.2 AVL树的左旋与右旋的实例

备注:在左旋和右旋时需要重新计算height值
在这里插入图片描述

6.2 AVL树的整体代码

import java.util.Queue;
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;

public class AVLTree<K extends Comparable<K>, V> {

	private class Node {
		public K key;
		public V value;
		public Node left;
		public Node right;
		public int height;

		public Node(K key, V value) {
			this.key = key;
			this.value = value;
			this.left = null;
			this.right = null;
			this.height = 1;
		}
	}

	private Node root;
	private int size;

	public AVLTree() {
		root = null;
		size = 0;
	}

	public int getSize() {
		return size;
	}

	public boolean isEmpty() {
		return size == 0;
	}

	// 计算高度
	public int getHeight(Node node) {
		if (node == null) {
			return 0;
		}
		return node.height;
	}

	// 计算平衡因子
	private int getBalanceFactor(Node node) {
		if (node == null) {
			return 0;
		}
		return getHeight(node.left) - getHeight(node.right);
	}

	// 判断是否为二分搜索树
	public boolean isBST() {
		List<K> keys = new ArrayList<>();
		inOrder(root, keys);
		for (int i = 1; i < keys.size(); i++) {
			if (keys.get(i).compareTo(keys.get(i - 1)) < 0) {
				return false;
			}
		}
		return true;
	}

	private void inOrder(Node node, List<K> keys) {
		if (node == null) {
			return;
		}
		inOrder(node.left, keys);
		keys.add(node.key);
		inOrder(node.right, keys);
	}

	// 判断是否为平衡二叉树
	public boolean isBalanced() {
		return isBalanced(root);
	}

	private boolean isBalanced(Node node) {
		if (node == null) {
			return true;
		}
		int balanceFactor = getBalanceFactor(node);
		if (Math.abs(balanceFactor) > 1) {
			return false;
		}
		return isBalanced(node.left) && isBalanced(node.right);
	}

	private Node getNode(Node node, K key) {
		if (node == null) {
			return null;
		}
		if (key.compareTo(node.key) < 0) {
			return getNode(node.left, key);
		} else if (key.compareTo(node.key) > 0) {
			return getNode(node.right, key);
		} else {
			return node;
		}
	}

	public boolean contains(K key) {
		return getNode(root, key) != null;
	}

	public void preOrder() {
		preOrder(root);
	}

	private void preOrder(Node node) {
		if (node == null) {
			return;
		}
		System.out.println(node.key);
		preOrder(node.left);
		preOrder(node.right);
	}

	public void inOrder() {
		inOrder(root);
	}

	private void inOrder(Node node) {
		if (node == null) {
			return;
		}
		inOrder(node.left);
		System.out.println(node.key);
		inOrder(node.right);
	}

	public void postOrder() {
		postOrder(root);
	}

	private void postOrder(Node node) {
		if (node == null) {
			return;
		}
		postOrder(node.left);
		postOrder(node.right);
		System.out.println(node.key);
	}

	public void levelOrder() {
		Queue<Node> q = new LinkedList<>();
		q.add(root);
		while (!q.isEmpty()) {
			Node cur = q.remove();
			System.out.println(cur.key);
			if (cur.left != null) {
				q.add(cur.left);
			}
			if (cur.right != null) {
				q.add(cur.right);
			}
		}
	}

	public V get(K key) {
		Node node = getNode(root, key);
		return node == null ? null : node.value;
	}

	public void set(K key, V newValue) {
		Node node = getNode(root, key);
		if (node == null) {
			throw new IllegalArgumentException(key + "doesn't exist!");
		}
		node.value = newValue;
	}

	// 右旋
	//        y                            x
	//       / \                        /     \
	//      x   T4              向右旋转(y)        z       y
	//     / \       - - - - - - ->   / \     / \
	//    z   T3                    T1   T2 T3   T4
	//   / \
	// T1 T2
	private Node rightRotate(Node y) {
		Node x = y.left;
		Node T3 = x.right;
		x.right = y;
		y.left = T3;
		y.height = 1 + Math.max(getHeight(y.left), getHeight(y.right));
		x.height = 1 + Math.max(getHeight(x.left), getHeight(x.right));
		return x;
	}

	// 左旋
	//    y                                   x
	//   / \                               /     \
	// T1   x              向左旋转(y)       y       z
	//     / \          - - - - - - ->   / \     / \
	//   T2   z                        T1   T2 T3   T4
	//       / \
	//     T3   T4	
	private Node leftRotate(Node y) {
		Node x = y.right;
		Node T2 = x.left;
		x.left = y;
		y.right = T2;
		y.height = 1 + Math.max(getHeight(y.left), getHeight(y.right));
		x.height = 1 + Math.max(getHeight(x.left), getHeight(x.right));
		return x;
	}

	public void add(K key, V value) {
		root = add(root, key, value);
	}

	private Node add(Node node, K key, V value) {
		if (node == null) {
			size++;
			return new Node(key, value);
		}
		if (key.compareTo(node.key) < 0) {
			node.left = add(node.left, key, value);
		}
		if (key.compareTo(node.key) > 0) {
			node.right = add(node.right, key, value);
		} else {
			node.value = value;
		}
		// 计算高度
		node.height = 1 + Math.max(getHeight(node.left), getHeight(node.right));
		// 计算平衡因子
		int balanceFactor = getBalanceFactor(node);
		// LL
		if (balanceFactor > 1 && getBalanceFactor(node.left) >= 0) {
			return rightRotate(node);
		}
		// RR
		if (balanceFactor < -1 && getBalanceFactor(node.right) <= 0) {
			return leftRotate(node);
		}
		// LR
		if (balanceFactor > 1 && getBalanceFactor(node.left) < 0) {
			node.left = leftRotate(node.left);
			return rightRotate(node);
		}
		// RL
		if (balanceFactor < -1 && getBalanceFactor(node.right) > 0) {
			node.right = rightRotate(node.right);
			return leftRotate(node);
		}
		return node;
	}

	public K findMin() {
		if (size == 0) {
			throw new IllegalArgumentException("Can not find something from a blank tree.");
		}
		return findMin(root).key;
	}

	private Node findMin(Node node) {
		if (node.left == null) {
			return node;
		}
		return findMin(node.left);
	}

	public K removeMin() {
		K ret = findMin();
		root = removeMin(root);
		return ret;
	}

	private Node removeMin(Node node) {
		if (node.left == null) {
			Node rightNode = node.right;
			node.right = null;
			size--;
			return rightNode;
		}
		node.left = removeMin(node.left);
		return node;
	}

	public void remove(K key) {
		root = remove(root, key);
	}

	private Node remove(Node node, K key) {
		if (node == null) {
			return null;
		}
		Node retNode;
		if (key.compareTo(node.key) < 0) {
			node.left = remove(node.left, key);
			retNode = node;
		} else if (key.compareTo(node.key) > 0) {
			node.right = remove(node.right, key);
			retNode = node;
		} else {
			if (node.left == null) {
				Node rightNode = node.right;
				node.right = null;
				size--;
				retNode = rightNode;
			} else if (node.right == null) {
				Node leftNode = node.left;
				node.left = null;
				size--;
				retNode = leftNode;
			} else {
				Node successor = findMin(node.right);
				// successor.right = removeMin(node.right);
				successor.right = remove(node.right, successor.key);
				successor.left = node.left;
				node.left = node.right = null;
				retNode = successor;
			}
		}
		if (retNode == null) {
			return null;
		}
		retNode.height = 1 + Math.max(getHeight(retNode.left), getHeight(retNode.right));
		int balanceFactor = getBalanceFactor(retNode);
		// LL
		if (balanceFactor > 1 && getBalanceFactor(retNode.left) >= 0) {
			return rightRotate(retNode);
		}
		// RR
		if (balanceFactor < -1 && getBalanceFactor(retNode.right) <= 0) {
			return leftRotate(retNode);
		}
		// LR
		if (balanceFactor > 1 && getBalanceFactor(retNode.left) < 0) {
			retNode.left = leftRotate(retNode.left);
			return rightRotate(retNode);
		}
		// RL
		if (balanceFactor < -1 && getBalanceFactor(retNode.right) > 0) {
			retNode.right = rightRotate(retNode.right);
			return leftRotate(retNode);
		}
		return retNode;
	}
}

7.红黑树(Red Black Tree, RBT)

等价于2-3树(2-3树具有绝对平衡性),在添加和删除性能上优于AVL树
 1. 所有结点的颜色不是红色就是黑色
 2. 根结点的颜色为黑色
 3. 每一个叶子结点(最后的空节点)是黑色的
 4. 红色结点的两个孩子都为黑色
 5. 从任意结点出发到叶子结点经过的黑色结点数量相同

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值