二叉搜索樹數據結構完整實現

文章首發於此,BST是後面自平衡二叉樹AVL樹,B樹等數據結構的基礎,所以理解BST的基本性質和操作很有必要,如果讀者對BST不是很瞭解可以查下wiki或者是參考嚴蔚敏的《數據結構與算法》或者《算法導論》,對於該數據結構有較詳細解釋,下面是我查詢資料實現的Java版本。

package com.mars.search;

public class BinarySeachTree {
    private Node mRoot;

    private Node getRoot() {
        return mRoot;
    }

    public int search(Node root, int key) {
        if (root == null) {
            return 0xffffffff;
        }
        if (key < root.key) {
            return search(root.leftNode, key);
        }
        if (key > root.key) {
            return search(root.rightNode, key);
        } else {
            return key;
        }
    }

    public void insert(int data) {
        if (mRoot == null) {
            mRoot = new Node(data, null, null);
            // mRoot.key = data;
        }
        Node root = mRoot;
        while (root != null) {
            if (data == root.key) {
                return;
            } else if (data < root.key) {
                if (root.leftNode == null) {
                    root.leftNode = new Node(data, null, null);
                    return;
                } else {
                    root = root.leftNode;
                }
            } else {
                if (root.rightNode == null) {
                    root.rightNode = new Node(data, null, null);
                    return;
                } else {
                    root = root.rightNode;
                }
            }
        }
    }

    /*
     * http://courses.csail.mit.edu/6.006/spring11/rec/rec03.pdf Description:
     * Remove the node x from the binary search tree, making the necessary
     * adjustments to the binary search tree to maintain its properties. (Note
     * that this operation removes a specified node from the tree. If you wanted
     * to delete a key k from the tree, you would have to first call find(k) to
     * find the node with key k and then call delete to remove that node) Case 1:
     * x has no children. Just delete it (i.e. change parent node so that it
     * doesn’t point to x) Case 2: x has one child. Splice out x by linking x’s
     * parent to x’s child Case 3: x has two children. Splice out x’s successor
     * and replace x with x’s successor
     * 
     * BST刪除分析可以看這裏 http://webdocs.cs.ualberta.ca/~holte/T26/del-from-bst.html
     */
    public boolean delete(int key) {
        Node root = deleteNode(this.mRoot, key);

        if (root != null) {
            return true;
        }
        return false;
    }

    /**
     * 
     * 刪除有左右子樹節點的時候其實等價於:1將右子樹的最左葉子節點的值覆蓋要刪除節點的值,
     * 然後刪除右子樹最左葉子節點。 遞歸的過程中找到刪除節點然後將右子樹的最左子葉子節點的
     * 值賦給刪除節點,然後刪除右子樹的最左葉子節點。這步在遞歸退出的時候就做了,如果想不
     * 通可以細細的看下第一個if語句
     * 
     * */

    private Node deleteNode(Node root, int key) {
        if (key < root.key) {
            if (root.leftNode != null) {
                root.leftNode = deleteNode(root.leftNode, key);
            } else {
                return null;
            }
        } else if (key > root.key) {
            if (root.rightNode != null) {
                root.rightNode = deleteNode(root.rightNode, key);
            } else {
                return null;
            }
        } else {
            if (root.leftNode == null) {
                root = root.rightNode;
            } else if (root.rightNode == null) {
                root = root.leftNode;
            } else {
                Node newRoot = findMin(root);
                root.key = newRoot.key;
                // 此步遞歸調用相當於把右子樹的最左子樹的左葉子給刪了,因爲遞歸退出的時候leftNode = null;
                //如果Node的結構裏有指向parent的引用,刪除會方便些
                root.rightNode = deleteNode(root.rightNode, root.key);
            }
        }
        return root;
    }

    // 左子樹的最右葉子節點
    private Node findMin(Node root) {
        Node newRoot = root.rightNode;
        while (newRoot.leftNode != null) {
            newRoot = newRoot.leftNode;
        }
        return newRoot;
    }

    public void travel(Node root) {
        Node node = root;
        if (node == null) {
            return;
        }
        travel(node.leftNode);
        System.out.print(node.key + " ");
        travel(node.rightNode);
    }

    public static class Node {
        int key;
        Node leftNode;
        Node rightNode;

        Node(int key, Node left, Node right) {
            this.key = key;
            this.leftNode = left;
            this.rightNode = right;
        }
    }

    public static void main(String[] args) {
        BinarySeachTree bst = new BinarySeachTree();
        int[] a = {
                0, 4, 3, 2, 5, 1, 7, 6, 8, 9
        };

        for (int i : a) {
            bst.insert(i);
        }
        bst.travel(bst.getRoot());

        int i = bst.search(bst.getRoot(), 3);
        System.out.println("\nsearch :" + i);

        System.out.println("after delete:");
        bst.delete(4);
        bst.travel(bst.getRoot());
    }
}

參考資料http://en.wikipedia.org/wiki/Binary_search_tree
數據結構與算法 

 

發佈了89 篇原創文章 · 獲贊 2 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章