1. 程式人生 > >手寫二叉排序樹(查詢樹、搜尋樹)

手寫二叉排序樹(查詢樹、搜尋樹)

二叉排序樹(查詢樹,搜尋樹)或者是一顆空樹,或者是一顆具有如下性質的樹:
1)若左子樹不為空,那麼左子樹上面的所有節點的關鍵字值都比根節點的關鍵字值小
2)若右子樹不為空,那麼右子樹上面的所有節點的關鍵字值都比根節點的關鍵字值大
3)左右子樹都為二叉樹
4)沒有重複值(這一點在實際中可以忽略)

public class SearchBinaryTree {

    //根節點
    public TreeNode root;


    /**
     * 新增節點
     */
    public TreeNode put(int data) {
        TreeNode newNode = new TreeNode(data);
        if (root == null) {
            root = newNode;
            return newNode;
        }
        TreeNode treeNode = root;
        TreeNode parent = null;
        while (treeNode != null) {
            parent = treeNode;
            if (data < treeNode.data) {
                treeNode = treeNode.leftChild;
            } else if (data > treeNode.data) {
                treeNode = treeNode.rightChild;
            } else {//相等情況不考慮 不插入
                return treeNode;
            }
        }

        newNode.parent = parent;
        if (data < parent.data) {
            parent.leftChild = newNode;
        } else {
            parent.rightChild = newNode;
        }

        return newNode;
    }

    /**
     * 查詢節點
     */
    public TreeNode search(int data) {
        if (root == null) {
            return null;
        }
        TreeNode node = root;
        while (node != null) {
            if (data < node.data) {
                node = node.leftChild;
            } else if (data > node.data) {
                node = node.rightChild;
            } else {
                return node;
            }
        }

        return null;

    }

    /**
     * 刪除節點
     */
    public void deleteNode(TreeNode node) {
        if (node == null) {
            throw new NoSuchElementException();
        } else {
            //先得到父親
            TreeNode parent = node.parent;

            //1.是葉子
            if (node.leftChild == null && node.rightChild == null) {
                //特別情況 1.樹上只有一個節點 或者空樹
                if (parent == null) {
                    root = null;
                } else if (parent.leftChild == node) {
                    parent.leftChild = null;
                } else {
                    parent.rightChild = null;
                }
                node.parent = null;
            } else if (node.leftChild != null && node.rightChild == null) {
                //只有左孩子
                if (parent==null){//是根節點
                    node.leftChild.parent=null;
                    root=node.leftChild;
                }else {
                    if (node==parent.leftChild){//要刪除的節點在父親左邊
                        parent.leftChild=node.leftChild;
                    }else {//要刪除節點在父親右邊
                        parent.rightChild=parent.leftChild;
                    }
                    node.leftChild.parent=parent;
                }
                node.parent=null;
                node.leftChild=null;
            } else if (node.leftChild == null && node.rightChild != null) {
                //只有右孩子
                if (parent==null){//是根節點
                    node.rightChild.parent=null;
                    root=node.rightChild;
                }else {
                    node.rightChild.parent=parent;
                    if (node==parent.leftChild){//要刪除的節點在父親左邊
                        parent.leftChild=node.rightChild;
                    }else {//要刪除節點在父親右邊
                        parent.rightChild=node.rightChild;
                    }
                }
                node.parent=null;
                node.rightChild=null;
            } else {//有左右兩個孩子
                if (node.rightChild.leftChild==null){//如果右子樹的左子樹為空 就直接補上右子樹
                    node.rightChild.leftChild=node.leftChild;
                    node.leftChild.parent=node.rightChild;
                    if (parent==null){
                        root=node.rightChild;
                    }else {
                        if (parent.leftChild==node){
                            parent.leftChild=node.rightChild;
                            node.rightChild.parent=parent;
                        }else {
                            parent.rightChild=node.rightChild;
                            node.rightChild.parent=parent;
                        }
                    }
                }else {//否則就補上右子樹的左子樹上最小的一個
                    TreeNode leftNode=getMinLeftTreeNode(node.rightChild);
                    leftNode.leftChild=node.leftChild;
                    node.leftChild.parent=leftNode;
                    if (parent==null){
                        root=node.rightChild;
                    }else {
                        if (parent.leftChild==node){
                            parent.leftChild=node.rightChild;
                            node.rightChild.parent=parent;
                        }else {
                            parent.rightChild=node.rightChild;
                            node.rightChild.parent=parent;
                        }
                    }

                }
                node.parent=null;
                node.rightChild=null;
                node.leftChild=null;
            }

        }

    }

    private TreeNode getMinLeftTreeNode(TreeNode node) {
            TreeNode curRoot=null;
            if (node==null){
                return null;
            }else {
                curRoot=node;
                while (curRoot.leftChild!=null){
                    curRoot=curRoot.leftChild;
                }
            }
            return curRoot;
    }


    /**
     * 中序遍歷
     */
    public void midOrderTraverse(TreeNode root) {
        if (root == null) {
            return;
        }
        //LDR
        midOrderTraverse(root.leftChild);
        System.out.print(root.data + " ");
        midOrderTraverse(root.rightChild);
    }


    public static class TreeNode {
        int data;
        TreeNode leftChild;
        TreeNode rightChild;
        TreeNode parent;

        public TreeNode(int data) {
            this.data = data;
            this.leftChild = null;
            this.rightChild = null;
            this.parent = null;
        }
    }

}

 測試結果

 /*
            5
          2     8
        1  4  6   9
          3    7
     */
    @Test
    public void testBinaryTree(){
        int[] array={5,2,8,6,8,5,9,4,1,7,3,9};
        SearchBinaryTree searchBinaryTree=new SearchBinaryTree();

        for (int i:array){
            searchBinaryTree.put(i);
        }
        searchBinaryTree.midOrderTraverse(searchBinaryTree.root);


        System.out.println();
        System.out.println(searchBinaryTree.search(8).data);
        SearchBinaryTree.TreeNode node=searchBinaryTree.search(5);
        searchBinaryTree.deleteNode(node);
        System.out.println();
        searchBinaryTree.midOrderTraverse(searchBinaryTree.root);
    }

列印結果看是正確的 

1 2 3 4 5 6 7 8 9 
8

1 2 3 4 6 7 8 9