二叉搜索树数据结构完整实现

文章首发于此,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
数据结构与算法 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值