二叉树
和链表一样,动态数据结构。
基本结构:
private class Node{
E e;
Node left;
Node right;
}
二叉树具有唯一的根节点
叶子节点
二叉树不一定是“满”的
二叉树具有天然的递归结构
二分搜索树Binary Search Tree
二分搜索树是二叉树
二分搜索树每个节点的值:
-----------大于其左子树的所有节点的值;
-----------小于其右子树所有节点的值。
每一个子树也是二分搜索树
存储的数据具有可比性。
二分搜索树具有顺序性
floor :比元素x小的最大元素
ceil:比元素x大的最小元素
二分搜索树
rank:排名
select
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
public class BST<E extends Comparable<E>> {
//节点
private class Node{
public E e;
public Node left,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;
}
//向二分搜索树添加新的元素E
public void add(E e){
root = add(root , e);
}
//向以Node为根的二分搜索树插入元素E 递归算法
//返回插入新节点后二分搜索树的根
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;
}
//查询二分搜索树是否包含元素e
public boolean contains(E e){
return contains(root , e);
}
//以node为根的二分搜索树是否包含元素e 递归算法
private boolean contains(Node node , E e){
if(node == null){
return false;
}
if(e.compareTo(node.e) == 0){
return true;
}
else if(e.compareTo(node.e) < 0){
return contains(node.left , e);
}
else //(e.compareTo(node.e) > 0){
return contains(node.right , e);
}
//前序遍历
public void preOrder(){
preOrder(root);
}
//前序遍历以node为根的二分搜索树 递归算法
public void preOrder(Node node){
if(node == null)
return;
System.out.println(node.e);
preOrder(node.left);
preOrder(node.right);
}
//前序遍历的非递归写法
public void preOrderNR(){
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);
}
}
//中序遍历 二分搜索树的中序遍历是顺序的
public void inOrder(){
inOrder(root);
}
private void inOrder(Node node){
if(node == null)
return;
inOrder(node.left);
System.out.println(node.e);
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.e);
}
//二分搜索树的层序遍历 非递归操作
public void levelOrder(){
Queue<Node> q = new LinkedList<>();
q.add(root);
while (!q.isEmpty()){
Node cur = q.remove();
System.out.println(cur.e);
if(cur.left != null)
q.add(cur.left);
if (cur.right != null)
q.add(cur.right);
}
}
//寻找二分搜索树的最小元素
public E miniNum(){
if(size == 0)
throw new IllegalArgumentException("Bst is Empty!");
return miniNum(root).e;
}
private Node miniNum(Node node){
if(node.left == null)
return node;
return miniNum(node.left);
}
//寻找二分搜索树的最大元素
public E maxiNum(){
if(size == 0)
throw new IllegalArgumentException("Bst is Empty!");
return maxiNum(root).e;
}
private Node maxiNum(Node node){
if(node.right == null)
return node;
return maxiNum(node.right);
}
//删除二分搜索树的最小元素 返回最小值
public E removeMin(){
E ret = miniNum();
root = removeMin(root);
return ret;
}
//删除以node为根的二分搜索树的最小节点
//返回删除后新的二分搜索树的根
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 removeMax(){
E ret = maxiNum();
root = removeMax(root);
return ret;
}
//删除以node为根的二分搜索树的最大节点
//返回删除后新的二分搜索树的根
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;
}
//删除二分搜索树的任意节点 Hibbard Deletion
public void remove(E e){
root = remove(root , e);
}
//删除以node为根的二分搜素树中值为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;
}
if(e.compareTo(node.e) > 0){
node.right = remove(node.right , e);
return node;
}else{ //e.compareTo(node.e) = 0
//待删除的节点左子树为空
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 = miniNum(node.right);
successor.right = removeMin(node.right);
successor.left = node.left;
node.left = node.right = null;
return successor;
}
}
@Override
public String toString() {
StringBuilder res = new StringBuilder();
generateBSTString(root , 0 , res);
return res.toString();
}
//生成以node为根节点,深度为depth的描述二叉树的字符串
private void generateBSTString(Node node , int depth , StringBuilder res){
if(node == null){
res.append(generateBSTString(depth) + "NULL\n");
return;
}
res.append(generateBSTString(depth) + node.e + "\n");
generateBSTString(node.left ,depth + 1 , res);
generateBSTString(node.right ,depth + 1 , res);
}
private String generateBSTString(int depth){
StringBuilder res = new StringBuilder();
for(int i = 0 ; i < depth ; i++)
res.append(" --");
return res.toString();
}
}