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

被折叠的 条评论
为什么被折叠?



