平衡二叉树java实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_37681914/article/details/83244222

写完之后,整个人心情都不太好

单元测试

package com.fly.study.structure;

import org.junit.Before;
import org.junit.Test;
import org.omg.PortableInterceptor.INACTIVE;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.IntStream;

import static org.junit.Assert.*;

/**
 * @Auther: fly
 * @Date: 2018/10/21 17:16
 * @see: <a href='https://github.com/FightingIsLife/structure'>https://github.com/FightingIsLife/structure</a>
 * @version: 1
 * @email: [email protected]
 * @Description:
 */
public class BinaryTreeTest {

    private BinaryTree<Integer> binaryTree = new BinaryTree<>(Integer::compare);

    @Test
    public void toListByPreOrder() {
        add();
        System.out.println(binaryTree.toListByPreOrder());
    }

    @Test
    public void toListByInOrder() {
        add();
        System.out.println(binaryTree.toListByInOrder());
    }

    @Test
    public void toListByPostOrder() {
        add();
        System.out.println(binaryTree.toListByPostOrder());
    }

    @Test
    public void add() {
        List<Integer> nums = Arrays.asList(4, 1, 3, 10, 7, 8, 9, 5, 2, 6);
        for (int num : nums) {
            binaryTree.add(num);
        }
        Collections.sort(nums);
        assertEquals(nums, binaryTree.toListByInOrder());
    }

    @Test
    public void remove() {
        add();
        assertTrue(binaryTree.remove(7));
        assertTrue(binaryTree.remove(9));
        assertTrue(binaryTree.remove(1));
        assertEquals(Arrays.asList(2, 3, 4, 5, 6, 8, 10), binaryTree.toListByInOrder());
    }

    @Test
    public void contains() {
        IntStream.range(1, 100).filter(this::isEven).forEach(binaryTree::add);
        assertTrue(binaryTree.contains(2));
        assertTrue(binaryTree.contains(98));
        assertFalse(binaryTree.contains(0));
        assertFalse(binaryTree.contains(99));
    }

    private boolean isEven(int num) {
        return num % 2 == 0;
    }

    @Test
    public void getSize() {
        assertEquals(0, binaryTree.getSize());
        binaryTree.add(1);
        assertEquals(1, binaryTree.getSize());
        binaryTree.add(2);
        assertEquals(2, binaryTree.getSize());
        binaryTree.add(2);
        assertEquals(2, binaryTree.getSize());
        binaryTree.remove(2);
        assertEquals(1, binaryTree.getSize());
        binaryTree.remove(0);
        assertEquals(1, binaryTree.getSize());
    }
}

实现

package com.fly.study.structure;

import java.util.*;

import static java.lang.Integer.max;

/**
 * @Auther: fly
 * @Date: 2018/10/21 12:58
 * @see: <a href='https://github.com/FightingIsLife/structure'>https://github.com/FightingIsLife/structure</a>
 * @version: 1
 * @email: [email protected]
 * @Description:
 */
public class BinaryTree<T> {

    private Comparator<T> comparator;
    private int size = 0;
    private Node<T> root;

    /**
     * 创建二叉树
     *
     * @param comparator 比较器
     */
    public BinaryTree(Comparator<T> comparator) {
        this.comparator = comparator;
    }

    /**
     * 获取先序遍历集合
     *
     * @return
     */
    public List<T> toListByPreOrder() {
        List<T> list = new ArrayList<>(size);
        toListByPreOrder(root, list);
        return list;
    }

    private void toListByPreOrder(Node<T> node, List<T> list) {
        if (node != null) {
            list.add(node.data);
            toListByPreOrder(node.leftNode, list);
            toListByPreOrder(node.rightNode, list);
        }
    }

    /**
     * 获取中序遍历集合
     *
     * @return
     */
    public List<T> toListByInOrder() {
        List<T> list = new ArrayList<>(size);
        toListByInOrder(root, list);
        return list;
    }

    private void toListByInOrder(Node<T> node, List<T> list) {
        if (node != null) {
            toListByInOrder(node.leftNode, list);
            list.add(node.data);
            toListByInOrder(node.rightNode, list);
        }
    }

    /**
     * 获取后序遍历集合
     *
     * @return
     */
    public List<T> toListByPostOrder() {
        List<T> list = new ArrayList<>(size);
        toListByPostOrder(root, list);
        return list;
    }

    private void toListByPostOrder(Node<T> node, List<T> list) {
        if (node != null) {
            toListByInOrder(node.leftNode, list);
            toListByInOrder(node.rightNode, list);
            list.add(node.data);
        }
    }

    /**
     * 向二叉树添加一个元素
     *
     * @param data
     * @return true添加成功,false添加失败
     */
    public boolean add(T data) {
        boolean success = true;
        if (root == null) {
            root = new Node<>();
            root.data = data;
        } else {
            success = add(root, data);
        }
        if (success) {
            size++;
        }
        return success;
    }

    private boolean add(Node<T> node, T data) {
        int compare = comparator.compare(data, node.data);
        boolean success = true;
        if (compare < 0) {
            // 往左子树加
            if (node.leftNode == null) {
                setLeftNode(node, new Node<>(data));
            } else {
                success = add(node.leftNode, data);
            }
        } else if (compare > 0) {
            // 往右子树加
            if (node.rightNode == null) {
                setRightNode(node, new Node<>(data));
            } else {
                success = add(node.rightNode, data);
            }
        } else {
            // compare相等的值,不再重复添加
            success = false;
        }
        updateAndBalanceNode(node);
        return success;
    }

    /**
     * 向二叉树中删除一个元素
     *
     * @param data 元素
     * @return
     */
    public boolean remove(T data) {
        boolean success = removeByData(data);
        if (success) {
            size--;
        }
        return success;
    }

    public boolean removeByData(T data) {
        Node<T> node = search(root, data);
        if (node == null) {
            return false;
        }
        Node<T> balanceNode = node.parentNode;
        if (node.deep == 0) {
            setParentNode(null, node.parentNode, isLeftNode(node.parentNode, node));
            if (root == node) {
                root = null;
            }
        } else if (node.deepDiff() > 0) {
            Node<T> rightMostNode = rightMost(node.leftNode);
            balanceNode = rightMostNode;
            if (node.leftNode != rightMostNode) {
                balanceNode = rightMostNode.parentNode;
                setLeftNode(rightMostNode, node.leftNode);
            }
            setRightNode(rightMostNode, node.rightNode);
            setParentNode(null, rightMostNode.parentNode, isLeftNode(rightMostNode, rightMostNode.parentNode));
            setParentNode(rightMostNode, node.parentNode, isLeftNode(node.parentNode, node));
            if (root == node) {
                root = rightMostNode;
            }
        } else {
            Node<T> leftMostNode = leftMost(node.rightNode);
            balanceNode = leftMostNode;
            if (node.rightNode != leftMostNode) {
                balanceNode = leftMostNode.parentNode;
                setRightNode(leftMostNode, node.rightNode);
            }
            setLeftNode(leftMostNode, node.leftNode);
            setParentNode(null, leftMostNode.parentNode, isLeftNode(leftMostNode, leftMostNode.parentNode));
            setParentNode(leftMostNode, node.parentNode, isLeftNode(node.parentNode, node));
            if (root == node) {
                root = leftMostNode;
            }
        }
        reBalance(balanceNode);
        return true;
    }

    private Node<T> rightMost(Node<T> node) {
        if (node == null) {
            return null;
        }
        while (node.rightNode != null) {
            node = node.rightNode;
        }
        return node;
    }

    private Node<T> leftMost(Node<T> node) {
        if (node == null) {
            return null;
        }
        while (node.leftNode != null) {
            node = node.leftNode;
        }
        return node;
    }

    private void reBalance(Node<T> node) {
        if (node != null) {
            Node<T> parentNode = node.parentNode;
            updateAndBalanceNode(node);
            reBalance(parentNode);
        }
    }

    /**
     * 查询二叉树中是否包含data
     */
    public boolean contains(T data) {
        return search(root, data) != null;
    }

    private Node<T> search(Node<T> node, T data) {
        if (node != null) {
            int compare = comparator.compare(data, node.data);
            if (compare == 0) {
                return node;
            } else if (compare < 0) {
                return search(node.leftNode, data);
            } else {
                return search(node.rightNode, data);
            }
        }
        return null;
    }


    private void updateAndBalanceNode(Node<T> node) {
        node.updateDeep();
        balance(node);
    }

    /**
     * 使二叉树的node节点平衡
     *
     * @param node 要平衡的节点
     */
    private void balance(Node<T> node) {
        int deepDiff = node.deepDiff();
        if (deepDiff == 2) {
            if (node.leftNode.deepDiff() == -1) {
                leftRotate(node.leftNode);
            }
            rightRotate(node);
        } else if (deepDiff == -2) {
            if (node.rightNode.deepDiff() == 1) {
                rightRotate(node.rightNode);
            }
            leftRotate(node);
        }
    }

    private void leftRotate(Node<T> node) {
        Node<T> rightNode = node.rightNode;
        Node<T> parentNode = node.parentNode;
        setRightNode(node, rightNode.leftNode);
        setLeftNode(rightNode, node);
        setParentNode(rightNode, parentNode, isLeftNode(parentNode, node));
        if (node == root) {
            root = rightNode;
        }
    }

    private void rightRotate(Node<T> node) {
        Node<T> leftNode = node.leftNode;
        Node<T> parentNode = node.parentNode;
        setLeftNode(node, leftNode.rightNode);
        setRightNode(leftNode, node);
        setParentNode(leftNode, parentNode, isLeftNode(parentNode, node));
        if (node == root) {
            root = leftNode;
        }
    }

    private boolean isLeftNode(Node<T> parentNode, Node<T> node) {
        return parentNode != null && parentNode.leftNode == node;
    }

    private void setLeftNode(Node<T> node, Node<T> leftNode) {
        if (leftNode != null) {
            leftNode.parentNode = node;
        }
        if (node != null) {
            node.leftNode = leftNode;
            node.updateDeep();
        }
    }

    private void setRightNode(Node<T> node, Node<T> rightNode) {
        if (rightNode != null) {
            rightNode.parentNode = node;
        }
        if (node != null) {
            node.rightNode = rightNode;
            node.updateDeep();
        }
    }

    private void setParentNode(Node<T> node, Node<T> parentNode, boolean isLeft) {
        if (node != null) {
            node.parentNode = parentNode;
        }
        if (parentNode != null) {
            if (isLeft) {
                parentNode.leftNode = node;
            } else {
                parentNode.rightNode = node;
            }
        }
    }

    public static class Node<T> {
        private Node<T> parentNode;
        /**
         * 树的深度: deep = Max(leftNode.deep,rightNode.deep)+1
         *
         * @see this#updateDeep()
         */
        private int deep;
        private T data;
        private Node<T> leftNode;
        private Node<T> rightNode;

        public Node() {
        }

        public Node(T data) {
            this.data = data;
        }

        private void updateDeep() {
            deep = max(getDeep(leftNode), getDeep(rightNode)) + 1;
        }

        /**
         * 左右子树的深度差
         */
        private int deepDiff() {
            return getDeep(leftNode) - getDeep(rightNode);
        }

        private int getDeep(Node<T> node) {
            return node == null ? -1 : node.deep;
        }

        @Override
        public String toString() {
            return "Node{" +
                    "data=" + data +
                    '}';
        }
    }

    public int getSize() {
        return size;
    }

    @Override
    public String toString() {
        return "BinaryTree{" +
                "size=" + size +
                ", root=" + root +
                '}';
    }
}

猜你喜欢

转载自blog.csdn.net/m0_37681914/article/details/83244222