数据结构与算法-自定义二叉树API

类名BinaryTree
构造方法名public BinaryTree()
成员内部类public class Node;结点类
成员方法public void put(Key key, Value value);往树中插入一个键值对
public Node put(Node x, Key key, Value value);在指定树x上,添加一个键值对,并返回添加后的新树
public Value get(Key key);根据key 返回value;
public int length();获取线性表数据个数(长度)
public T remove(int index);删除指定索引处元素,并将其返回
public Value get(Node x, Key key) ;从指定树中找出对应的值
public void delete(Key key);根据key,删除树中对应的键值对
public Node delete(Node x, Key key);删除指定树x上的键为key 的键值对,并返回删除后的新树
public int size();获取树中元素的个数
public Key min() ;查找整个树中最小的键
public Node min(Node x);在指定树x 中找出最小键所在的结点
public Key max();查找整个树中最大的键
public Node max(Node x);在指定树x 中找出最大键所在的结点
public Queue preErgodic();前序遍历获取整个树中所有的键
public void preErgodic(Node x, Queue keys);前序遍历获取指定树x 的所有键,并放到keys 队列中
public Queue midErgodic();使用中序遍历获取所有的键
private void midErgodic(Node x, Queue keys);使用中序遍历获取指定x中所有的键,并存放到key中
public Queue afterErgodic();使用后序遍历,把整个树中所有的键返回

private void afterErgodic(Node x, Queue keys);使用后序遍历,把指定x树中所有的键放入到keys 中
成员变量private int size;记录当前线性表的元素个数
private Node head;;定义头结点
成员内部类变量private Node left;记录左子结点
private Node right;记录右子结点
private Key key;记录key
private Value value;记录value
代码如下

输出结果

key 为E 的值是:5
key 为B 的值是:2
树中元素个数是:8
树中最小值是:1
树中最大值是:8
E-----2
B-----2
A-----1
D-----4
C-----3
G-----7
F-----6
H-----8

测试类

public static void main(String[] args) {
        BinaryTree<String, String> tree = new BinaryTree<>();
        tree.put("E", "5");
        tree.put("B", "2");
        tree.put("G", "7");
        tree.put("A", "1");
        tree.put("D", "4");
        tree.put("F", "6");
        tree.put("H", "8");
        tree.put("C", "3");


        System.out.println("key 为E 的值是:"+tree.get("E"));
        System.out.println("key 为B 的值是:"+tree.get("B"));
        System.out.println("树中元素个数是:"+tree.size());
        System.out.println("树中最小值是:"+ tree.min());
        System.out.println("树中最大值是:"+ tree.max());
        //前序遍历
        Queue<String> keys = tree.preErgodic();
        for (String key : keys){
            System.out.println(key+"-----"+tree.get(key));
        }

    }

BinaryTree类

package cn.bloghut.tree;

/**
 * @author by 闲言
 * @classname BinaryTree
 * @description 自定义二叉树api
 * @date 2021/7/21 10:53
 */
public class BinaryTree<Key extends Comparable, Value> {
    //存储元素个数
    private int size;
    //头结点
    private Node head;

    public class Node {
        //记录左子结点
        private Node left;
        //记录右子结点
        private Node right;
        //记录key
        private Key key;
        //记录value
        private Value value;

        //初始化
        public Node(Key key, Value value, Node left, Node right) {
            this.key = key;
            this.value = value;
            this.left = left;
            this.right = right;
        }

    }

    /**
     * 初始化
     */
    public BinaryTree() {
        this.size = 0;
    }

    /**
     * 往树中插入一个键值对
     *
     * @param key
     * @param value
     */
    public void put(Key key, Value value) {
        head = put(head, key, value);
    }

    /**
     * 在指定树x上,添加一个键值对,并返回添加后的新树
     *
     * @param x
     * @param key
     * @param value
     */
    public Node put(Node x, Key key, Value value) {
        //判断根结点是否为空
        if (x == null) {
            size++;
            return new Node(key, value, null, null);
        } else {
            //比较x 结点和key的大小
            int cmp = key.compareTo(x.key);
            //判断key 是否大于 当前结点的键,找出当前右子树
            if (cmp > 0) {
                x.right = put(x.right, key, value);
            } else if (cmp < 0) {
                //判断key 是否小于 当前结点的键,找出当前左子树
                x.left = put(x.left, key, value);
            } else {
                //判断key 是否等于 当前结点的键,说明该键已经存在,则替换该值
                x.value = value;
            }
        }
        return x;
    }

    /**
     * 根据key 返回value
     *
     * @param key
     * @return
     */
    public Value get(Key key) {
        return get(head, key);
    }

    /**
     * 从指定树中找出对应的值
     *
     * @param x
     * @param key
     * @return
     */
    public Value get(Node x, Key key) {
        if (x == null) {
            return null;
        }
        int cmp = key.compareTo(x.key);
        if (cmp > 0) {
            x.value = get(x.right, key);
        } else if (cmp < 0) {
            x.value = get(x.left, key);
        } else {
            return x.value;
        }
        return x.value;
    }

    /**
     * 删除key 对应的结点
     *
     * @param key
     */
    public void delete(Key key) {
        head = delete(head, key);
    }

    /**
     * 删除指定结点x 中 的key,并返回删除后的树
     *
     * @param x
     * @param key
     * @return
     */
    public Node delete(Node x, Key key) {
        if (x == null) {
            return null;
        }
        int cmp = key.compareTo(x.key);
        if (cmp > 0) {
            //新结点的key大于当前结点的key,继续找当前结点的右子结点
            x.right = delete(x.right, key);
        } else if (cmp < 0) {
            //新结点的key小于当前结点的key,继续找当前结点的左子结点
            x.left = delete(x.left, key);
        } else {
            //新结点的key等于当前结点的key,当前x就是要删除的结点
            //1.如果当前结点的右子树不存在,则直接返回当前结点的左子结点
            if (x.right == null) {
                return x.left;
            }
            //2.如果当前结点的左子树不存在,则直接返回当前结点的右子结点
            if (x.left == null) {
                return x.right;
            }
            //3.当前结点的左右子树都存在
            Node minNode = x.right;
            //3.1找到右子树中最小的结点
            while (minNode.left != null) {
                minNode = minNode.left;
            }
            //3.2删除右子树中最小的结点
            Node n = x.right;
            while (n.left != null) {
                if (n.left.left == null) {
                    n.left = null;
                } else {
                    n = n.left;
                }
            }
            //3.3让被删除结点的左子树称为最小结点minNode的左子树,让被删除结点的右子树称为最小结点minNode的右子树
            minNode.left = x.left;
            minNode.right = x.right;
            //3.4让被删除结点的父节点指向最小结点minNode
            x = minNode;
            //个数-1
            size--;
        }
        return x;
    }

    /**
     * 获取元素个数
     *
     * @return
     */
    public int size() {
        return size;
    }

    /**
     * 判断是否为空
     *
     * @return
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * 查找整个树中最小的键
     *
     * @return
     */
    public Value min() {
        return min(head).value;
    }

    /**
     * 在指定树x 中找出最小键所在的结点
     *
     * @param x
     * @return
     */
    public Node min(Node x) {
        //需要判断x 有没有左子结点,如果有,则继续向左找,如果没有,则x 就是最小键所在的结点
        if (x.left != null) {
            return min(x.left);
        } else {
            return x;
        }
    }

    /**
     * 查找整个树中最大的键
     *
     * @return
     */
    public Value max() {
        return max(head).value;
    }

    /**
     * 在指定树x 中找出最大键所在的结点
     *
     * @param x
     * @return
     */
    private Node max(Node x) {
        //判断x还有没有右子结点,如果有,则继续向有查找,如果没有,则x就是最大键所在的结点
        if (x.right != null) {
            return max(x.right);
        } else {
            return x;
        }
    }

    /**
     * 获取整个树中所有的键
     *
     * @return
     */
    public Queue<Key> preErgodic() {
        Queue<Key> keys = new Queue<>();
        preErgodic(head, keys);
        return keys;
    }

    /**
     * 获取指定树x 的所有键,并放到keys 队列中
     *
     * @param x
     * @param keys
     * @return
     */
    private void preErgodic(Node x, Queue<Key> keys) {
        if (x == null) {
            return;
        }
        //把当前结点的key放入到队列中;
        keys.enqueue(x.key);
        //递归遍历x结点的左子树
        if (x.left != null) {
            preErgodic(x.left, keys);
        }
        //递归调用x结点的右子树
        if (x.right != null) {
            preErgodic(x.right, keys);
        }
    }

    /**
     * 使用中序遍历获取所有的键
     *
     * @return
     */
    public Queue<Key> midErgodic() {
        Queue<Key> keys = new Queue<>();
        midErgodic(head, keys);
        return keys;
    }

    /**
     * 使用中序遍历获取指定x中所有的键,并存放到key中
     *
     * @param x
     * @param keys
     * @returnz
     */
    private void midErgodic(Node x, Queue<Key> keys) {
        if (x == null) {
            return;
        }
        先递归把左子树中的键放到keys中
        if (x.left != null) {
            midErgodic(x.left, keys);
        }
        //把当前结点x 的键放到keys中
        keys.enqueue(x.key);
        //再递归,把右子树的键放到keys中
        if (x.right != null) {
            midErgodic(x.right, keys);
        }
    }

    /**
     * 使用后序遍历,把整个树中所有的键返回
     *
     * @return
     */
    public Queue<Key> afterErgodic() {
        Queue<Key> keys = new Queue<>();
        afterErgodic(head, keys);
        return keys;
    }

    /**
     * 使用后序遍历,把指定x树中所有的键放入到keys 中
     *
     * @param x
     * @param keys
     * @return
     */
    private void afterErgodic(Node x, Queue<Key> keys) {
        if (x == null) {
            return;
        }
        //通过递归把左子树中所有的键放入到keys 中
        if (x.left != null) {
            afterErgodic(x.left, keys);
        }
        //通过递归右左子树中所有的键放入到keys 中
        if (x.right != null) {
            afterErgodic(x.right, keys);
        }
        //把x结点的键放入到keys中
        keys.enqueue(x.key);
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值