二叉排序树java代码实现

package com.ccnu.edu.cn;

import java.util.ArrayDeque;
import java.util.Comparator;

/**
 * Created by 董乐强 on 2017/12/3.
 * 二叉搜索树的实现
 * 为了使用compare这个方法,所以要继承SortClassImpl这个类,因为这个类中存在_compare(),重构代码的时候,可以_compare()作为一个公具类来操作
 */
public class BinarySearchTree<K, V> extends SortClassImpl<K> {

    private Comparator<? extends K> comparator;
    //二叉搜索树中的元素个数
    private int count;
    //二叉搜素树的根结点
    private Node<K, V> root;
    //用于存储遍历的元素
    //能不能将count直接赋值到数组中,作为数组的大小,答案是不可以的
    private Node<K, V>[] datas;
    private Object[] data;
    private int index;

    //内部类,定义二叉树的一个节点
    private class Node<K, V> {
        private K key;
        private V value;
        private Node<K, V> leftChild;
        private Node<K, V> rightChild;

        public Node(K key, V value) {
            this.key = key;
            this.value = value;
        }
    }

    public BinarySearchTree() {
        this.comparator = null;
    }

    //传入一个比较器
    public BinarySearchTree(Comparator<? extends K> comparator) {
        this.comparator = comparator;
    }

    public int getCount() {
        return count;
    }

    /**
     * 得到二叉排序树中的所有key     *
     * @return
     */
    public Object[] getKeys() {
        data = new Object[count];
        if (datas.length > 0) {
            for (int i = 0; i < count; i++) {
                data[i] = datas[i].key;
            }
        }
        return data;
    }

    /**
     * 得到二叉排序树中的所有value     *
     * @return
     */
    public Object[] getValues() {
        data = new Object[count];
        if (datas.length > 0) {
            for (int i = 0; i < count; i++) {
                data[i] = datas[i].value;
            }
        }
        return data;
    }


    /**
     * 递归实现将元素插入到二叉排序树中
     *
     * @param key
     * @param value
     */
    public void insert(K key, V value) {
        root = _insert(root, key, value);
    }

    /**
     * 非递归实现,将元素插入到二叉排序树中
     *
     * @param key
     * @param value
     */
    public void insert1(K key, V value) {
        root = _insert1(root, key, value);
    }

    /**
     * 二叉树是否包含key     *
     * @param key
     * @return
     */
    public boolean containKeys(K key) {
        boolean flag = _containKeys(root, key);
        return flag;
    }

    /**
     * 通过得到key得到value     *
     * @param key
     * @return
     */
    public V getValue(K key) {
        if (!_containKeys(root, key))
            throw new RuntimeException("Binary search tree don't have key");
        return _getValue(root, key);
    }

    /**
     * 二叉树的前序遍历、中序遍历、后续遍历,遍历的数据存入一个数组中。
     */
    public void tranverse(int i) {
        datas = new Node[count];
        index = 0;
        if (i == 0)
            //前序遍历
            _preOrder(root);
        else if (i == 1)
            //中序遍历
            _middleOrder(root);
        else if (i == 2)
            //后续遍历
            _afterOrder(root);
    }

    /**
     * 递归实现,得到二叉树中最大值的节点
     *
     * @return
     */
    public Node<K, V> getMaxKeyNode() {
        if (root != null)
            return _getMaxKeyNode(root);
        else
            return null;
    }

    /**
     * 得到二叉排序树中的最小值节点
     *
     * @return
     */
    public Node<K, V> getMinKeyNode() {
        if (root == null)
            return null;
        return _getMinKeyNode(root);
    }

    public Node<K, V> removeMaxNode() {
        return _removeMaxNode(root);
    }

    public Node<K, V> removeMinNode() {
        return _removeMinNode(root);
    }

    public Node<K, V> removeKey(K key) {
        return _removeKey(root, key);
    }

    /**
     * 在二叉树中以node为节点的根移除值为key的节点,同时返回node
     * 这个算法是二叉排序树中最难的一个点,二叉排序树的插入和删除都可以做很多文章,平衡二叉树,红黑树等都在插入和删除的时候就行应用的.
     *
     * @param node
     * @param key
     * @return
     */
    private Node<K, V> _removeKey(Node<K, V> node, K key) {
        if (_compare(key, node.key) == 1) {
            node.rightChild = _removeKey(node.rightChild, key);
            return node;
        } else if (_compare(key, node.key) == -1) {
            node.leftChild = _removeKey(node.leftChild, key);
            return node;
        } else {

            if (node.leftChild == null) {
                count--;
                return node.rightChild;
            }
            if (node.rightChild == null) {
                count--;
                return node.leftChild;
            }
            //左右子树都不为空的情况下删除,算法的核心,也是最麻烦的地方
            //首先得到要替换的根结点
            Node<K, V> rootNode = _getMinKeyNode(node.rightChild);
            rootNode.leftChild = node.leftChild;
            rootNode.rightChild = _removeMinNode(node.rightChild);
            count--;
            return rootNode;
        }
    }

    /**
     * node为根结点,移除最大值结点,返回node
     *
     * @param node
     * @return
     */
    private Node<K, V> _removeMaxNode(Node<K, V> node) {
        if (node.rightChild == null) {
            count--;
            return node.leftChild;
        }
        //这一步是算法的核心,仔细体会一下
        node.rightChild = _removeMaxNode(node.rightChild);
        return node;
    }

    /**
     * node为根结点,移除最小值结点,返回node
     *
     * @param node
     * @return
     */
    private Node<K, V> _removeMinNode(Node<K, V> node) {
        if (node.leftChild == null) {
            count--;
            return node.rightChild;
        }
        node.leftChild = _removeMinNode(node.leftChild);
        return node;
    }

    /**
     * 得到以node节点为根的二叉树中最大值节点,也就是以node节点为根的二叉树,右孩子为空的节点
     *
     * @param node
     * @return
     */
    private Node<K, V> _getMaxKeyNode(Node<K, V> node) {
        if (node.rightChild == null)
            return node;
        else
            return _getMaxKeyNode(node.rightChild);
    }

    /**
     * 得到以node节点为根的二叉树中最小值节点,也就是以node节点为根的二叉树,左孩子为空的节点
     *
     * @param node
     * @return
     */
    private Node<K, V> _getMinKeyNode(Node<K, V> node) {
        if (node.leftChild == null)
            return node;
        return _getMinKeyNode(node.leftChild);
    }

    /**
     * node为节点,进行中序遍历
     *
     * @param node
     */
    private void _middleOrder(Node<K, V> node) {
        if (node == null)
            return;
        _middleOrder(node.leftChild);
        datas[index++] = node;
        _middleOrder(node.rightChild);

    }

    /**
     * node为节点进行前序遍历
     *
     * @param node
     */
    private void _preOrder(Node<K, V> node) {
        if (node == null)
            return;
        datas[index++] = node;
        _preOrder(node.leftChild);
        _preOrder(node.rightChild);
    }

    /**
     * node为节点进行后续遍历
     *
     * @param node
     */
    private void _afterOrder(Node<K, V> node) {
        if (node == null)
            return;
        _afterOrder(node.leftChild);
        _afterOrder(node.rightChild);
        datas[index++] = node;
    }

    /**
     * 层次遍历,需要一个辅助队列
     */
    public void transLevel() {
        //得到一个辅助队列,来进行层序遍历
        ArrayDeque<Node<K, V>> queue = new ArrayDeque();
        //不能带着泛型,来创建数组
        datas = new Node[count];
        //根结点入队
        queue.addLast(root);
        while (!queue.isEmpty()) {
            Node<K, V> head = queue.getFirst();
            datas[index++] = queue.pop();
            if (head.leftChild != null)
                queue.addLast(head.leftChild);
            if (head.rightChild != null)
                queue.addLast(head.rightChild);
        }
    }

    /**
     * node为根结点中,查找key对应的value
     *
     * @param node
     * @param key
     * @return
     */
    private V _getValue(Node<K, V> node, K key) {
        if (_compare(node.key, key) == 0)
            return node.value;
        //以左孩子为节点进行寻找
        if (_compare(node.key, key) == 1)
            return _getValue(node.leftChild, key);
        else
            return _getValue(node.rightChild, key);
    }


    /**
     * node为节点中,是否包含键值key
     *
     * @param node
     * @param key
     * @return
     */
    private boolean _containKeys(Node<K, V> node, K key) {
        if (node == null)
            return false;
        //以左孩子为根结点进行查找
        if (_compare(node.key, key) == 1)
            return _containKeys(node.leftChild, key);

            //以右孩子为根结点进行查找
        else if (_compare(node.key, key) == -1)
            return _containKeys(node.rightChild, key);
        else
            return true;
    }

    /**
     * 二分排序树的插入,非递归实现
     *
     * @param key
     * @param value
     */
    private Node<K, V> _insert1(Node<K, V> root, K key, V value) {
        //得到一个新节点
        Node<K, V> newNode = new Node<>(key, value);
        //当前指向的节点
        Node<K, V> currentNode = root;
        //父节点,必须要有父节点,因为currentNode走到null时,其父节点决定当前节点的插入位置
        Node<K, V> parentNode = root;
        if (root == null) {
            count++;
            root = newNode;
        } else {
            //寻找要插入的节点,如果currentNode == null,则找到要插入的节点
            while (currentNode != null) {
                parentNode = currentNode;
                if (_compare(currentNode.key, key) == 1)
                    currentNode = currentNode.leftChild;
                else if (_compare(currentNode.key, key) == -1)
                    currentNode = currentNode.rightChild;
                else {
                    currentNode.key = key;
                    break;
                }
            }
            if (currentNode == null) {
                count++;
                if (_compare(parentNode.key, key) == 1)
                    parentNode.leftChild = newNode;
                else
                    parentNode.rightChild = newNode;
            }
        }
        //返回根结点
        return root;
    }

    /**
     * 二分查找树,插入一个节点
     * 递归实现
     * node为节点的二叉树中插入节点
     *
     * @param node
     * @param key
     * @param value
     * @return
     */
    private Node<K, V> _insert(Node<K, V> node, K key, V value) {

        //得到一个新结点
        Node<K, V> newNode = new Node<>(key, value);

        if (node == null) {
            count++; //这个是递归的结束条件,程序一定会走到这一步如果
            return newNode;
        }
        if (_compare(node.key, key) == -1)
            node.rightChild = _insert(node.rightChild, key, value);
        else if (_compare(node.key, key) == 1)
            node.leftChild = _insert(node.leftChild, key, value);
        else {
            node.key = key;
            return node;
        }

        return node;
    }

}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值