数据结构与算法---树

来源:互联网 发布:连邦软件专卖店 编辑:程序博客网 时间:2024/06/05 00:55

对于大量的输入数据,链表的线性访问时间太慢,不宜使用。而树是一种简单的数据结构,其大部分操作的运行时间平均为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.csdn.net/v_JULY_v/article/details/6530142/

原创粉丝点击