查找二--二叉排序树

一、二叉查找树的定义

1)左子树上所有结点的值均小于根结点的值;
2)右子树上所有结点的值均大于根结点的值;
3)它的左、右子树也都分别是二叉查找树。


查找原理
   若二叉查找树为空,则查找不成功;否则
  1)KEY值等于根结点,则查找成功;
  2)KEY值小于根结点,则继续在左子树上进行查找;
  3)KEY值大于根结点,则继续在右子树上进行查找。


插入操作
二叉查找树进行中序遍历得到的是一个有序序列,所以二叉查找树实质上是一个有序表。
如果查找不成功,则用这个KEY值 与 parentNode保存的最后一个不为空的节点 进行对比。将KEY作 parentNode 的子节点


删除操作
分三种情况。
1)无子节点,直接删除。
2)只是左子节点,或右子节点,将该节点的子节点替换该节点

3)左右子节点都存在,前面提过(二叉查找树的中序遍历是一个有序序列),所以用该节点的前驱替换该节点。


如图:
假设要删除节点48,执行程序的过程如下:
1、中序遍历找到48的前缀37,中序出来遍历的数肯定不会再有右节点的。
2、将37的左节点36替换原37的位置。
3、将37的左节点修改为 key值的左节点(35。
4、再将37的右节点修改为 key值的右节点(51)。

5、将37替换48. 




package graph.binary;

/**
 * Created with .
 * Date: 14-3-19
 * Time: 上午9:01
 * To change this template use File | Settings | File Templates.
 */

class Node {
    int data;
    Node parentNode;
    Node left;
    Node right;

    Node(int data) {
        this.data = data;
    }
}

public class Binary {
    Node root;

    public boolean search(Node key) {
        return search(key, root);
    }

    /**
     * 查找
     *
     * @param key
     * @param src
     * @return
     */
    public boolean search(Node key, Node src) {
        if (src == null || key == null) return false;
        if (key.data == src.data) return true;
        if (key.data < src.data) return search(key, src.left);
        if (key.data > src.data) return search(key, src.right);
        return false;
    }

    /**
     * 插入
     *
     * @param key
     */
    public void insert(Node key) {
        if (root == null) {
            root = key;
        } else if (!search(key)) {
            Node parentNode = root;
            while (true) {
                if (parentNode.data < key.data) {
                    if (parentNode.right == null) {
                        parentNode.right = key;
                        key.parentNode = parentNode;
                        return;
                    }
                    parentNode = parentNode.right;
                } else if (parentNode.data > key.data) {
                    if (parentNode.left == null) {
                        parentNode.left = key;
                        key.parentNode = parentNode;
                        return;
                    }
                    parentNode = parentNode.left;
                }
            }
        }
    }

    /**
     * 删除
     *
     * @param key
     */
    public void delete(Node key) {
        if (root == null || key == null) return;
        Node node = root;
        while (node != null) {
            if (node.data == key.data) {
                _delete(node);
                break;
            } else if (node.data < key.data) {
                node = node.right;
            } else if (node.data > key.data) {
                node = node.left;
            }
        }
    }

    private void _delete(Node keyNode) {
        Node node = null;
        if (keyNode.parentNode == null) {
            root = null;
        } else {
            if (keyNode.right == null) {
                node = keyNode.left;
            } else if (keyNode.left == null) {
                node = keyNode.right;
            } else if (keyNode.left != null && keyNode.right != null) {
                node = keyNode.left;//中序遍历curNode的前缀节点。用于替换curNode;
                while (node.right != null) {
                    node = node.right;
                }

                node.parentNode.right = node.left;
                if (node.left != null) node.left.parentNode = node.parentNode;

                node.left = keyNode.left;
                keyNode.left.parentNode = node;

                node.right = keyNode.right;
                keyNode.right.parentNode = node;
            }

            if (keyNode.data > keyNode.parentNode.data) { //在右边
                keyNode.parentNode.right = node;
                node.parentNode = keyNode.parentNode;
            } else if (keyNode.data < keyNode.parentNode.data) {//在左边
                keyNode.parentNode.left = node;
                node.parentNode = keyNode.parentNode;
            }


        }
    }

    /**
     * 中缀遍历找印
     *
     * @param node
     */
    public void print(Node node) {
        if (node == null) return;
        print(node.left);
        System.out.print(node.data);
        System.out.print("  ");
        print(node.right);
    }

    public static void main(String[] args) {
        Binary binary = new Binary();

        binary.insert(new Node(62));
        binary.insert(new Node(58));
        binary.insert(new Node(88));


        binary.insert(new Node(48));
        binary.insert(new Node(35));
        binary.insert(new Node(51));
        binary.insert(new Node(29));
        binary.insert(new Node(37));
        binary.insert(new Node(36));

        binary.insert(new Node(51));
        binary.insert(new Node(49));
        binary.insert(new Node(50));
        binary.insert(new Node(56));

        binary.insert(new Node(88));
        binary.insert(new Node(73));
        binary.insert(new Node(99));
        binary.insert(new Node(93));


        Node key = new Node(48);
        binary.delete(key);

        key = new Node(37);
        binary.delete(key);

        binary.print(binary.root);
    }

}

打印结果

29  35  36  37  48  49  50  51  56  58  62  73  88  93  99

删除48后,打印:

29  35  36  37  49  50  51  56  58  62  73  88  93  99

删除48和51后,打印:

29  35  36  37  49  50  56  58  62  73  88  93  99 













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值