数据结构与算法---树

对于大量的输入数据,链表的线性访问时间太慢,不宜使用。而树是一种简单的数据结构,其大部分操作的运行时间平均为O(log N)

二叉树

二叉树是一棵树,其中每个节点都不能有多于两个的儿子。
实现

class BinaryNode(){
    Object element;
    BinaryNode left;
    BinaryNode right;
}

查找树ADT — 二叉查找树

使二叉树成为二叉查找树的性质是,对于树中的每个节点X,他的左子树中所有项的值小于X中的项,而它的右子树中所有项的值小于X中的项

public class BinarySearchTree <E extends Comparable<? super E>>{

            private static class BinaryNode<E>{
                BinaryNode(E theElement) {
                    this(theElement,null,null);
                }

                BinaryNode(E element, BinaryNode<E> left, BinaryNode<E> right) {
                    this.element = element;
                    this.left = left;
                    this.right = right;
                }

                E element;
                BinaryNode<E> left;
                BinaryNode<E> right;
            }

            private BinaryNode<E> root;

            public BinarySearchTree(){root = null;}

            public void makeEmpty(){root = null;}

            public boolean isEmpty(){return root == null;}

            public boolean contains(E x){
                return contains(x, root);
            }

            public E findMin(){
                if(isEmpty()) throw new BufferUnderflowException();
                return findMin(root).element;
            }

            public E findMax(){
                if(isEmpty()) throw new BufferUnderflowException();
                return findMax(root).element;
            }

            public void insert(E x){root = insert(x, root);}

            public void remove(E x){root = remove(x, root);}

            public void printTree(){};

            private BinaryNode<E> remove(E x, BinaryNode<E> root) {
                if (root == null) return root;
                int compareResult = x.compareTo(root.element);
                if (compareResult < 0) root.left = remove(x, root.left);
                else if (compareResult > 0) root.right = remove(x, root.right);
                else if (root.left != null && root.right != null) {
                    root.element = findMin(root.right).element;
                    root.right = remove(root.element,root.right);
                }
                else root = (root.left != null)?root.left:root.right;
                return root;
            }

            private BinaryNode<E> insert(E x, BinaryNode<E> root) {
                if (root == null) return new BinaryNode<E>(x, null, null);
                int compareResult = x.compareTo(root.element);

                if (compareResult < 0) root.left = insert(x, root.left);
                else if (compareResult > 0) root.right = insert(x, root.right);
                else ;
                return root;
            }

            private BinaryNode<E> findMax(BinaryNode<E> root) {
               if(root != null)
                   while (root.right != null)
                       root = root.right;
                return root;
            }

            private BinaryNode<E> findMin(BinaryNode<E> root) {
                if (root ==null) return null;
                else if (root.left ==null) return root;
                return  findMin(root.left);
            }

            private boolean contains(E x, BinaryNode<E> root) {
                if(root == null) return false;
                int compareResult = x.compareTo(root.element);
                if(compareResult < 0) return contains(x, root.left);
                else if(compareResult > 0) return contains(x, root.right);
                else return true;
            }

AVL树

AVL树是带有平衡条件的二叉查找树。这个平衡条件必须要容易保持。空树的高度定义为 -1 。每一个几点保留高度信息。
在插入数据时会破坏的平衡结构,所以每次插入删除操作都需要对树进行修正。修正的方法很简单,我们这个操作为旋转。
分别为单旋转和双旋转,具体实现可以上网查阅资料。

public class AvlTree<E extends Comparable<? super E> >{

    private static class AvlNode<E>{

        AvlNode(E element) {
            this(element, null, null);
        }

        AvlNode(E element, AvlNode<E> left, AvlNode<E> right) {
            this.element = element;
            this.left = left;
            this.right = right;
        }

        E element;
        AvlNode<E> left;
        AvlNode<E> right;
        int height;
    }

    private AvlNode<E> root;
    public void insert(E x){root = insert(x,root);}
    private int height(AvlNode<E> root) {
        return root == null ?  -1 : root.height;
    }


    private AvlNode<E> insert(E x, AvlNode<E> t){
        System.out.println("插入"+ x);

        if(t == null) {
            System.out.println("插入根节点"+x);
            return new AvlNode<E>(x, null, null);
        }

        int compareResult = x.compareTo(t.element);
        if(compareResult < 0){
            System.out.println("插入比根节点小的值");
            t.left = insert(x,t.left);
            if(height(t.left) - height(t.right) == 2)
                if (x.compareTo(t.left.element) < 0) {
                    System.out.println("插入比根节点小的值,单旋");
                    t = rotateWithLeftChild(t);
                }
                else{
                    System.out.println("插入比根节点小的值,双旋");
                    t = doubleWithLeftChild(t);}
        }
        else if (compareResult > 0){
            System.out.println("插入比根节点大的值");
            t.right = insert(x, t.right);
            if(height(t.right) - height(t.left) == 2)
                if(x.compareTo(t.right.element) > 0){
                    System.out.println("插入比根节点大的值,单旋");
                    t = rotateWithRightChild(t);}
                else{
                    System.out.println("插入比根节点大的值,双旋");
                    t = doubleWithRightChild(t);}
        }
        else ;
        t.height = Math.max(height(t.left),height(t.right)) + 1;
        return t;

    }
    private AvlNode<E> rotateWithRightChild(AvlNode<E> k2) {
        AvlNode<E> k1 = k2.right;
        k2.right = k1.left;
        k1.left = k2;
        k2.height = Math.max(height(k2.right),height(k2.right))+1;
        k1.height = Math.max(height(k1.right),k2.height)+1;
        return k1;
    }
    private AvlNode<E> doubleWithRightChild(AvlNode<E> k3) {
        k3.right = rotateWithLeftChild(k3.right);
        return rotateWithRightChild(k3);
    }



    private AvlNode<E> rotateWithLeftChild(AvlNode<E> k2) {
        AvlNode<E> k1 = k2.left;
        k2.left = k1.right;
        k1.right = k2;
        k2.height = Math.max(height(k2.right),height(k2.right))+1;;
        k1.height = Math.max(height(k1.left),k2.height)+1;

        return k1;
    }

    private AvlNode<E> doubleWithLeftChild(AvlNode<E> k3) {
        k3.left = rotateWithRightChild(k3.left);
        return rotateWithLeftChild(k3);
    }



}

伸展树

伸展树的基本想法是,当一个节点被访问后,它就要经过一系列AVL树的旋转被推到根上。如果一个节点很深,那么其路径上就存在许多也相对较深的节点,通过重新构造可以减少对所有这些节点很深,那么在其路径上就存在许多也相对较深的节点,通过重新构造可以减少对所有这些节点的进一步访问所花费的时间。因此,那我们要求重新构造应具有平衡这棵树的作用。

树的遍历

树的遍历方式有三种
- 先序遍历
当前节点在其儿子节点之前处理
- 中序遍历
先处理左子树,然后是当前节点,再处理右子树,其总的运行时间是O(N)
- 后序遍历
当前节点在其儿子节点之后处理,比如计算树的高度时
- 层序遍历
所有深度为d的节点要在深度d+1之前进行处理,与上述三种遍历方式不同的是它不使用递归方式进行,他用到队列

B树

详见
http://blog.youkuaiyun.com/v_JULY_v/article/details/6530142/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值