二叉搜索树Java实现

二叉搜索树

一,概念

树节点增加key属性,用来比较大小,key不能重复

对于任意树节点,他的key比左子树大,比右子树小

1.前驱

比当前节点的key小的节点中,key最大的节点

左子树key最大的节点 或者 最后一个自左而来的节点

2.后继

比当前节点的key大的节点中,key最小的节点

右子树key最小的节点 或者 最后一个自右而来的节点

二,方法

注:节点类在最后实现代码中给出,由于导入原因,
缩进有所不同,可放入idea中一键格式化

1.put方法

不断根据key寻找插入位置,并通过prev记录上一个节点,

key存在则更新value,不存在则判断key与prev的key决定插入位置

public void put(KeyType key, ValueType value) {
        BSTNode<KeyType, ValueType> p = root;
        BSTNode<KeyType, ValueType> prev = null;
        while (p != null) {
            prev = p;
            int result = key.compareTo(p.key);
            if (result < 0) {
                p = p.left;
            } else if (result > 0) {
                p = p.right;
            } else {
                p.value = value;
                return;
            }
        }
        if (prev == null) {
            root = new BSTNode<KeyType, ValueType>(key, value);
            return;
        }
        if (key.compareTo(prev.key) < 0) {
            prev.left = new BSTNode<KeyType, ValueType>(key, value);
        } else {
            prev.right = new BSTNode<KeyType, ValueType>(key, value);
        }
    }

2.get方法

不断根据key寻找节点,找到返回对应的value,不存在返回null

public ValueType get(KeyType key) {
        BSTNode<KeyType, ValueType> p = root;
        while (p != null) {
            int result = key.compareTo(p.key);
            if (result < 0) {
                p = p.left;
            } else if (result > 0) {
                p = p.right;
            } else {
                return p.value;
            }
        }
        return null;
    }
3.寻找前驱

根据key寻找对应节点,并在每一次进入右子树之前记录当前节点为prev

左子树存在则前驱为左子树的最大值,否则为prev

 public ValueType findPrecursor(KeyType key) {
        BSTNode<KeyType, ValueType> precursor = findPrecursor(root, key);
        return precursor != null ? precursor.value : null;
    }
private BSTNode<KeyType, ValueType> findPrecursor(BSTNode<KeyType, ValueType> node, KeyType key) {
        BSTNode<KeyType, ValueType> p = node;
        BSTNode<KeyType, ValueType> pre = null;
        while (p != null) {
            if (key.compareTo(p.key) < 0) {
                p = p.left;
            } else if (key.compareTo(p.key) > 0) {
                pre = p;
                p = p.right;
            } else {
                break;
            }
        }
        if (p == null) {
            return null;
        }
        if (p.left == null) {
            return pre;
        }
        return max(p.left);
    }
4.寻找后继

根据key寻找对应节点,并在每一次进入左子树之前记录当前节点为prev

右子树存在则前驱为右子树的最小值,否则为prev

public ValueType findSubsequent(KeyType key) {
        BSTNode<KeyType, ValueType> subsequent = findSubsequent(root, key);
        return subsequent != null ? subsequent.value : null;
    }
private BSTNode<KeyType, ValueType> findSubsequent(BSTNode<KeyType, ValueType> node, KeyType key) {
        BSTNode<KeyType, ValueType> p = node;
        BSTNode<KeyType, ValueType> pre = null;
        while (p != null) {
            if (key.compareTo(p.key) < 0) {
                pre = p;
                p = p.left;
            } else if (key.compareTo(p.key) > 0) {
                p = p.right;
            } else {
                break;
            }
        }
        if (p == null) {
            return null;
        }
        if (p.right != null) {
            return min(p.right);
        }
        return pre;
    }
5.删除

根据key寻找当前节点并在每一次前进时记录当前节点为prev,继而分类讨论:

​ 1)左子树为空,将右子树继承到prev

​ 2)右子树为空,将左子树继承到prev

​ 3)左右都存在,寻找后继,

​ 后继与当前节点相邻:将后继节点继承到被删除节点的父节点上

​ 后继与当前节点不相邻:将后继节点的右子树继承到后继节点的父节点上,

​ 再将后继节点继承到被删除节点的父节点上,最后调整左右子节点为被删除节点的左右节点

//继承方法,将child通过curr与pre的节点关系继承到pre上,
//即删除curr,curr是左节点就将child集成到pre的左子树上
private void extend(BSTNode<KeyType, ValueType> pre, BSTNode<KeyType, ValueType> curr, BSTNode<KeyType, ValueType> child) {
        if (pre == null) {
            root = child;
        } else if (pre.left == curr) {
            pre.left = child;
        } else {
            pre.right = child;
        }
    }
 public ValueType remove(KeyType key) {
        BSTNode<KeyType, ValueType> p = root;       //待删除节点
        BSTNode<KeyType, ValueType> pre = null;     //待删除节点的父节点
        while (p != null) {
            if (key.compareTo(p.key) < 0) {
                pre = p;
                p = p.left;
            } else if (key.compareTo(p.key) > 0) {
                pre = p;
                p = p.right;
            } else {
                break;
            }
        }
        if (p == null) {    //未找到待删除节点
            return null;
        }
        if (p.left == null) {   //左子树为空
            extend(pre, p, p.right);
        } else if (p.right == null) {   //右子树为空
            extend(pre, p, p.left);
        } else {       //均不空,则寻找后继
            BSTNode<KeyType, ValueType> s = p.right;   //待删除后继
            BSTNode<KeyType, ValueType> sprev = null;   //待删除后继的父节点
            while (s.left != null) {     //寻找待删除后继
                sprev = s;
                s = s.left;
            }

            if (sprev.right != p) {     //后继与待删除节点不相邻
                extend(sprev, s, s.right);
                s.right = p.right;
            }
            extend(pre, p, s);
            s.left = p.left;
        }
        return p.value;
    }

6.遍历

这里就不过多赘述了,直接上代码

public void inOrders() {//中序遍历
        BSTNode<KeyType, ValueType> curr = root;
        Stack<BSTNode<KeyType, ValueType>> stack = new Stack<>();
        while (curr != null || !stack.isEmpty()) {
            if (curr != null) {
                stack.push(curr);
                curr = curr.left;
            } else {
                BSTNode<KeyType, ValueType> pop = stack.pop();
                System.out.println(pop.value);
                curr = pop.right;
            }
        }
    }

public void preOrders() {//前序遍历
        preOrders(root);
    }

private void preOrders(BSTNode<KeyType, ValueType> node) {
    if (node == null) {
        return;
    }
    System.out.print(node.value + "\t"); // 值
    preOrders(node.left); // 左
    preOrders(node.right); // 右
}

public void outOrders() {后序遍历
    BSTNode<KeyType, ValueType> curr = root;
    Stack<BSTNode<KeyType, ValueType>> stack = new Stack<>();
    BSTNode<KeyType, ValueType> pop = null;
    while (curr != null || !stack.isEmpty()) {
        if (curr != null) {
            stack.push(curr);
            curr = curr.left;
        } else {
            BSTNode<KeyType, ValueType> peek = stack.peek();
            if (peek.right == null || peek.right == pop) {
                pop = stack.pop();
                System.out.println(pop.value);
            } else {
                curr = peek.right;
            }
        }
    }
}
三,实现
package BSTTree;

import java.util.Stack;

public class BSTTree<KeyType extends Comparable<KeyType>, ValueType>{
    static class BSTNode<KeyType, ValueType> {
        KeyType key;
        ValueType value;
        BSTNode<KeyType, ValueType> left;
        BSTNode<KeyType, ValueType> right;

        public BSTNode(KeyType key) {
            this.key = key;
        }

        public BSTNode(KeyType key, ValueType value) {
            this.key = key;
            this.value = value;
        }

        public BSTNode(KeyType key, ValueType value, BSTNode<KeyType, ValueType> left, BSTNode<KeyType, ValueType> right) {
            this.key = key;
            this.value = value;
            this.left = left;
            this.right = right;
        }
    }

    private BSTNode<KeyType, ValueType> root;

    public ValueType min() {
        return min(root).value;
    }

    public ValueType max() {
        return max(root).value;
    }


    public ValueType get(KeyType key) {
        BSTNode<KeyType, ValueType> p = root;
        while (p != null) {
            int result = key.compareTo(p.key);
            if (result < 0) {
                p = p.left;
            } else if (result > 0) {
                p = p.right;
            } else {
                return p.value;
            }
        }
        return null;
    }

    public void put(KeyType key, ValueType value) {
        BSTNode<KeyType, ValueType> p = root;
        BSTNode<KeyType, ValueType> prev = null;
        while (p != null) {
            prev = p;
            int result = key.compareTo(p.key);
            if (result < 0) {
                p = p.left;
            } else if (result > 0) {
                p = p.right;
            } else {
                p.value = value;
                return;
            }
        }
        if (prev == null) {
            root = new BSTNode<KeyType, ValueType>(key, value);
            return;
        }
        if (key.compareTo(prev.key) < 0) {
            prev.left = new BSTNode<KeyType, ValueType>(key, value);
        } else {
            prev.right = new BSTNode<KeyType, ValueType>(key, value);
        }
    }

    public void inOrders() {
        BSTNode<KeyType, ValueType> curr = root;
        Stack<BSTNode<KeyType, ValueType>> stack = new Stack<>();
        while (curr != null || !stack.isEmpty()) {
            if (curr != null) {
                stack.push(curr);
                curr = curr.left;
            } else {
                BSTNode<KeyType, ValueType> pop = stack.pop();
                System.out.println(pop.value);
                curr = pop.right;
            }
        }
    }

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

    public void outOrders() {
        BSTNode<KeyType, ValueType> curr = root;
        Stack<BSTNode<KeyType, ValueType>> stack = new Stack<>();
        BSTNode<KeyType, ValueType> pop = null;
        while (curr != null || !stack.isEmpty()) {
            if (curr != null) {
                stack.push(curr);
                curr = curr.left;
            } else {
                BSTNode<KeyType, ValueType> peek = stack.peek();
                if (peek.right == null || peek.right == pop) {
                    pop = stack.pop();
                    System.out.println(pop.value);
                } else {
                    curr = peek.right;
                }
            }
        }
    }

    public ValueType findPrecursor(KeyType key) {
        BSTNode<KeyType, ValueType> precursor = findPrecursor(root, key);
        return precursor != null ? precursor.value : null;
    }

    public ValueType findSubsequent(KeyType key) {
        BSTNode<KeyType, ValueType> subsequent = findSubsequent(root, key);
        return subsequent != null ? subsequent.value : null;
    }

    public ValueType remove(KeyType key) {
        BSTNode<KeyType, ValueType> p = root;       //待删除节点
        BSTNode<KeyType, ValueType> pre = null;     //待删除节点的父节点
        while (p != null) {
            if (key.compareTo(p.key) < 0) {
                pre = p;
                p = p.left;
            } else if (key.compareTo(p.key) > 0) {
                pre = p;
                p = p.right;
            } else {
                break;
            }
        }
        if (p == null) {    //未找到待删除节点
            return null;
        }
        if (p.left == null) {   //左子树为空
            extend(pre, p, p.right);
        } else if (p.right == null) {   //右子树为空
            extend(pre, p, p.left);
        } else {       //均不空,则寻找后继
            BSTNode<KeyType, ValueType> s = p.right;   //待删除后继
            BSTNode<KeyType, ValueType> sprev = null;   //待删除后继的父节点
            while (s.left != null) {     //寻找待删除后继
                sprev = s;
                s = s.left;
            }

            if (sprev.right != p) {     //后继与待删除节点不相邻
                extend(sprev, s, s.right);
                s.right = p.right;
            }
            extend(pre, p, s);
            s.left = p.left;
        }
        return p.value;
    }

    private void preOrders(BSTNode<KeyType, ValueType> node) {
        if (node == null) {
            return;
        }
        System.out.print(node.value + "\t"); // 值
        preOrders(node.left); // 左
        preOrders(node.right); // 右
    }

    private void extend(BSTNode<KeyType, ValueType> pre, BSTNode<KeyType, ValueType> curr, BSTNode<KeyType, ValueType> child) {
        if (pre == null) {
            root = child;
        } else if (pre.left == curr) {
            pre.left = child;
        } else {
            pre.right = child;
        }
    }

    private BSTNode<KeyType, ValueType> findSubsequent(BSTNode<KeyType, ValueType> node, KeyType key) {
        BSTNode<KeyType, ValueType> p = node;
        BSTNode<KeyType, ValueType> pre = null;
        while (p != null) {
            if (key.compareTo(p.key) < 0) {
                pre = p;
                p = p.left;
            } else if (key.compareTo(p.key) > 0) {
                p = p.right;
            } else {
                break;
            }
        }
        if (p == null) {
            return null;
        }
        if (p.right != null) {
            return min(p.right);
        }
        return pre;
    }

    private BSTNode<KeyType, ValueType> findPrecursor(BSTNode<KeyType, ValueType> node, KeyType key) {
        BSTNode<KeyType, ValueType> p = node;
        BSTNode<KeyType, ValueType> pre = null;
        while (p != null) {
            if (key.compareTo(p.key) < 0) {
                p = p.left;
            } else if (key.compareTo(p.key) > 0) {
                pre = p;
                p = p.right;
            } else {
                break;
            }
        }
        if (p == null) {
            return null;
        }
        if (p.left == null) {
            return pre;
        }
        return max(p.left);
    }

    private BSTNode<KeyType, ValueType> max(BSTNode<KeyType, ValueType> node) {
        if (node == null) {
            return null;
        }
        BSTNode<KeyType, ValueType> p = node;
        while (p.right != null) {
            p = p.right;
        }
        return p;
    }

    private BSTNode<KeyType, ValueType> min(BSTNode<KeyType, ValueType> node) {
        if (node == null) {
            return null;
        }
        BSTNode<KeyType, ValueType> p = node;
        while (p.left != null) {
            p = p.left;
        }
        return p;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值