树-二叉循环树

什么是二叉搜索树

二叉搜索树(Binary Search Tree),是最基础,且相对简单的一种数据结构,支持Insert,Delete,Search,Min,Max,Successor,Predecessor等操作。最大的特点是每一个节点有不超过两个子节点,并且左子节点小于或者等于父节点,而右节点大于或者等于父节点。说它基础,是因为很多其它树形数据结构以它为原型而扩展,比如红黑树,B树。

二叉搜索树:

       1.所有非叶子结点至多拥有两个儿子(Left和Right);

       2.所有结点存储一个关键字;

       3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树;

       如:

       

       B树的搜索,从根结点开始,如果查询的关键字与结点的关键字相等,那么就命中;

否则,如果查询关键字比结点关键字小,就进入左儿子;如果比结点关键字大,就进入

右儿子;如果左儿子或右儿子的指针为空,则报告找不到相应的关键字;

       如果B树的所有非叶子结点的左右子树的结点数目均保持差不多(平衡),那么B树

的搜索性能逼近二分查找;但它比连续内存空间的二分查找的优点是,改变B树结构

(插入与删除结点)不需要移动大段的内存数据,甚至通常是常数开销;

       如:

      

   但B树在经过多次插入与删除后,有可能导致不同的结构:

 

   右边也是一个B树,但它的搜索性能已经是线性的了;同样的关键字集合有可能导致不同的

树结构索引;所以,使用B树还要考虑尽可能让B树保持左图的结构,和避免右图的结构,也就

是所谓的“平衡”问题;      

       实际使用的B树都是在原B树的基础上加上平衡算法,即“平衡二叉树”;如何保持B树

结点分布均匀的平衡算法是平衡二叉树的关键;平衡算法是一种在B树中插入和删除结点的

策略;

package com.qjm.xj.action;

/**

 * 二叉树:删除头结点,会从左节点或者右结点拿一个作为头结点

 *

 * **/

public class BinaryTree<T extends Comparable<T>> { 

    private Node<T> root; 

 

    public void insert(T element) { 

        if (element == null) { 

            throw new IllegalArgumentException("element can not be null"); 

        } 

 

        if (root == null) { //如果root=null,就是第一个结点,就创建结点。

            root = new Node<T>(null, element); 

        } else

            Node<T> node = root; 

            while (true) { 

                if (element.compareTo(node.value) <= 0) {  //字符串比较,"a".compareTo("b") >0

                    if (node.left == null) { 

                        Node<T> newNode = new Node<T>(node, element); 

                        node.left = newNode; 

                        break

                    } else

                        node = node.left; 

                    } 

                } else

                    if (node.right == null) { 

                        Node<T> newNode = new Node<T>(node, element); 

                        node.right = newNode; 

                        break

                    } else

                        node = node.right; 

                    } 

                } 

            } 

        } 

    } 

 

    private int childCount(Node<T> node) { 

        if (node == null) { 

            throw new IllegalArgumentException("node can not be null"); 

        } 

 

        int count = 0; 

 

        if (node.left != null) { 

            count++; 

        } 

 

        if (node.right != null) { 

            count++; 

        } 

 

        return count; 

    } 

 

    public void delete(Node<T> node) { 

        if (node == null) { 

            throw new IllegalArgumentException("node can not be null"); 

        } 

 

        int childCount = childCount(node); //查看是否有左右结点

        Node<T> parentNode = node.parent; 

 

        if (childCount == 0) { 

            if (parentNode == null) { 

                // node is root 

                root = null

            } else

                if (node == parentNode.left) { 

                    parentNode.left = null

                } else

                    parentNode.right = null

                } 

            } 

        } else if (childCount == 1) { 

            if (parentNode == null) { 

                // node is root, set child of node to be new root 

                if (node.left != null) { 

                    root = node.left;  //如果当前结点的左节点不为空,就把左节点赋给一个Node,然后让Node的左节点的父节点置为空

                    node.left.parent = null

                } else

                    root = node.right; 

                    node.right.parent = null

                } 

            } else

                if (node == parentNode.left) { 

                    if (node.left != null) { 

                        parentNode.left = node.left; 

                        node.left.parent = parentNode; 

                    } else

                        parentNode.left = node.right; 

                        node.right.parent = parentNode; 

                    } 

                } else

                    if (node.left != null) { 

                        parentNode.right = node.left; 

                        node.left.parent = parentNode; 

                    } else

                        parentNode.right = node.right; 

                        node.right.parent = parentNode; 

                    } 

                } 

            } 

        } else

            // successor has no left child 

            Node<T> successor = min(node); //获取最小的左节点

 

            if (successor != node.right) { 

                transplant(successor, successor.right); 

 

                successor.right = node.right; 

                node.right.parent = successor; 

            } 

 

            transplant(node, successor); 

 

            successor.left = node.left; 

            node.left.parent = successor; 

        } 

    } 

   /**

    * param1:当前结点

    * param12:最小左节点(最小结点)

    * 替换,把要删除的结点的左右结点指向删除结点的父节点

    * **/

    private void transplant(Node<T> u, Node<T> v) { 

        if (u == null) { 

            throw new IllegalArgumentException("node can not be null"); 

        } 

 

        if (u.parent == null) { 

            root = v; 

        } else if (u == u.parent.left) { 

            u.parent.left = v; 

        } else

            u.parent.right = v; 

        } 

 

        if (v != null) { 

            v.parent = u.parent; 

        } 

    } 

 

    public Node<T> search(T element) { 

        if (element == null) { 

            throw new IllegalArgumentException("element can not be null"); 

        } 

 

        Node<T> node = root; 

        while (node != null) { 

            if (node.value.equals(element)) {  //先查找是否等于当前结点

                return node; 

            } else if (element.compareTo(node.value) < 0) {//如果小于结点,就查找它的左孩子,并把左孩子赋给当前孩子,做循环查找

                node = node.left; 

            } else

                node = node.right;  //反正查找右结点

            } 

        } 

 

        return null

    } 

 

    public Node<T> min(Node<T> rootNode) { 

        if (rootNode == null) { 

            throw new IllegalArgumentException("node can not be null"); 

        } 

 

        Node<T> node = rootNode; 

        while (node.left != null) { 

            node = node.left; 

        } 

 

        return node; 

    } 

 

    public Node<T> min() { 

        if (root != null) { 

            return min(root); 

        } else

            return null

        } 

    } 

 

    public Node<T> max(Node<T> rootNode) { 

        if (rootNode == null) { 

            throw new IllegalArgumentException("node can not be null"); 

        } 

 

        Node<T> node = rootNode; 

        while (node.right != null) { 

            node = node.right; 

        } 

 

        return node; 

    } 

 

    public Node<T> max() { 

        if (root != null) { 

            return max(root); 

        } else

            return null

        } 

    } 

 

    public Node<T> successor(Node<T> node) { 

        if (node == null) { 

            throw new IllegalArgumentException("node can not be null"); 

        } 

 

        if (node.right != null) { 

            return min(node.right); 

        } 

 

        Node<T> processNode = node; 

        Node<T> parent = processNode.parent; 

        while (parent != null && processNode == parent.right) { 

            processNode = parent; 

            parent = processNode.parent; 

        } 

 

        return parent; 

    } 

 

    public Node<T> predecesssor(Node<T> node) { 

        if (node == null) { 

            throw new IllegalArgumentException("node can not be null"); 

        } 

 

        if (node.left != null) { 

            return max(node.left); 

        } 

 

        Node<T> processNode = node; 

        Node<T> parent = processNode.parent; 

        while (parent != null && processNode == parent.left) { 

            processNode = parent; 

            parent = processNode.parent; 

        } 

 

        return parent; 

    } 

 

    public void print() { 

        print(root); 

    } 

    //这个查找非常经典  

    public void print(Node<T> node) { 

        if (node == null) { 

            return

        } 

 

        print(node.left); 

        System.out.print("  " + node.value.toString() + "  "); 

        print(node.right); 

    } 

 

    public static class Node<T extends Comparable<T>> { 

        private Node<T> parent;//父节点 

        private Node<T> left;  //左孩子

        private Node<T> right;  //右孩子

 

        private T value;  //值

 

        public Node(Node<T> parent, T value) { 

            this.parent = parent; 

            this.value = value; 

        } 

 

        public Node<T> getParent() { 

            return parent; 

        } 

 

        public void setParent(Node<T> parent) { 

            this.parent = parent; 

        } 

 

        public Node<T> getLeft() { 

            return left; 

        } 

 

        public void setLeft(Node<T> left) { 

            this.left = left; 

        } 

 

        public Node<T> getRight() { 

            return right; 

        } 

 

        public void setRight(Node<T> right) { 

            this.right = right; 

        } 

 

        public T getValue() { 

            return value; 

        } 

 

        public void setValue(T value) { 

            this.value = value; 

        } 

    } 

 

    public static void main(String[] args) { 

        BinaryTree<String> tree = new BinaryTree<String>(); 

 

        tree.insert("Hello"); 

 

        tree.insert("World"); 

 

        tree.insert("Money"); 

 

        tree.insert("Money");

 

        tree.insert("Loney");

 

        tree.insert("Aoney");

 

        tree.insert("Doney");

 

        tree.insert("Xoney");

 

        tree.insert("Noney");

 1-8

        tree.print(); 

        System.out.println(); 

 

        Node<String> moneyNode = tree.search("Money"); 

        tree.print(moneyNode); 

        System.out.println("**************"); 

 

        tree.insert("Like"); 

        tree.print(moneyNode); 

        System.out.println(); 

 

        tree.delete(moneyNode); 

        tree.print(); 

        System.out.println(); 

    } 

}

 

本文转载至:http://blog.csdn.net/kimylrong/article/details/21872909

转载于:https://www.cnblogs.com/qjm201000/p/qjm_3.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值