数据结构与算法---树
来源:互联网 发布:连邦软件专卖店 编辑:程序博客网 时间: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/
- 数据结构与算法---树
- 数据结构与算法分析 树
- 【数据结构与算法】二叉树
- 数据结构与算法-树1
- 数据结构与算法之----树
- 数据结构与算法-二叉树
- 算法与数据结构 - 二叉树
- 数据结构与算法:二叉树
- 数据结构与算法分析:树
- js数据结构与算法----树
- 8.4 树----数据结构与算法
- 数据结构与算法之树
- 数据结构与算法:二叉树
- 数据结构与算法-二叉树
- 数据结构与算法-伸展树
- 数据结构与算法 -- 算法
- 【数据结构与算法】浅谈数据结构与算法
- 【数据结构与算法】【Some】数据结构与算法
- 常见HTTP响应状态码
- Redis小结
- Maven
- JDK,inter IJ idea和maven的安装与配置
- HTTP常见状态码
- 数据结构与算法---树
- 设置QComboBox信号仅在点击时响应
- Mac包管理工具安装和使用
- Nagle算法
- LinkedList类的实现
- 无线通信原理学习博客
- js中的try-catch
- HDU 5912 Fraction(模拟——分子式化简求解)
- 03-quirks mode 和 standars mode