首页 > 代码库 > 【算法导论学习-25】 二叉树专题3:Treaps
【算法导论学习-25】 二叉树专题3:Treaps
参考1:算法导论333页
一、Treaps介绍
参考2: http://www.cnblogs.com/huangxincheng/archive/2012/07/30/2614484.html
1. 为什么要用Treaps
1) Treap简明易懂。Treap只有两种调整方式,左旋和右旋。而且即使没有严密的数学证明和分析,Treap的构造方法啊,平衡原理也是不难理解的。只要能够理解 BST和堆的思想,理解Treap当然不在话下。
2) Treap易于编写。Treap只需维护一个满足堆序的修正值,修正值一经生成无需修改。相比较其他各种平衡树, Treap拥有最少的调整方式,仅仅两种相互对称的旋转。所以 Treap当之无愧是最易于编码调试的一种平衡树。
3) Treap稳定性佳。Treap的平衡性虽不如 AVL,红黑树,SBT等平衡树,但是 Treap也不会退化,可以保证期望 O(logN)的深度。
4) Treap具有严密的数学证明。Treap期望O(logN)的深度,是有严密的数学证明的。但这不是介绍的重点,大多略去。
5) Treap具有良好的实践效果。各种实际应用中, Treap的稳定性表现得相当出色,没有因为任何的构造出的数据而退化。于是在信息学竞赛中,不少选手习惯于使用 Treap,均取得了不俗的表现。
二、Treaps的java实现
参考1:http://www.blogjava.net/xmatthew/archive/2012/05/16/347297.html
参考2:http://www.cnblogs.com/huangxincheng/archive/2012/07/30/2614484.html
1、节点类
注意,这里的节点类中的prioity其实应该是随机生成的,但是这里给注释掉了,同时开放了setPrioity(int prioity)函数用于人工设置prioity的值,方便模拟。
/** * @author 曹艳丰 *类说明:主要既要有key,又要有prioity */ public class TreapsNode<T> { private int key; private T satelliteData; private int prioity; private TreapsNode<T> leftChild,rightChild; /*构造一个没有左右子树的treapNod作为treap的root节点*/ public TreapsNode(int key,T satelliteData) { // TODO 自动生成的构造函数存根 // prioity=new Random(System.currentTimeMillis()).nextInt(Integer.MAX_VALUE); // prioity=new Random(System.currentTimeMillis()).nextInt(20); prioity=new Random().nextInt(20); this.key=key; this.satelliteData=http://www.mamicode.com/satelliteData;>2、treaps的主体,实现了add()函数
/** * @author 曹艳丰 * 类说明:只实现了add()函数 */ public class Treap<T> { TreapsNode<T> root; public Treap() { // TODO 自动生成的构造函数存根 root=null; } public Treap(TreapsNode<T> root) { // TODO 自动生成的构造函数存根 this.root=root; } /*插入过程,只用判断两种情况 */ public TreapsNode<T> add(TreapsNode<T> root,TreapsNode<T> node){ if (root==null) { root=new TreapsNode<T>(node.getKey(), node.getSatelliteData()); } if (node.getKey()<root.getKey()) { TreapsNode<T> tempNode=add(root.getLeftChild(), node); root.setLeftChild(tempNode); //插入点为最后一次递归,根据小根堆性质,需要”左左情况旋转” if (root.getLeftChild().getPrioity()<root.getPrioity()) { root=rightRotate(root); } } if (node.getKey()>root.getKey()) { TreapsNode<T> tempNode=add(root.getRightChild(), node); root.setRightChild(tempNode); //根据小根堆性质,需要”右右情况旋转” if (root.getRightChild().getPrioity()<root.getPrioity()) { root=leftRotate(root); } } // if (node.getKey()==root.getKey()) { // root.setLeftChild(node); // } return root; } public void add(TreapsNode<T> node){ root=add(root, node); } /*右旋*/ public TreapsNode<T> rightRotate(TreapsNode<T> node){ /*tempNode是插入的节点,node是其父节点*/ TreapsNode<T> tempNode=node.getLeftChild(); node.setLeftChild(tempNode.getRightChild()); tempNode.setRightChild(node); return tempNode; } /*左旋*/ public TreapsNode<T> leftRotate(TreapsNode<T> node){ /*tempNode是插入的节点,node是其父节点*/ TreapsNode<T> tempNode=node.getRightChild(); node.setRightChild(tempNode.getLeftChild()); tempNode.setLeftChild(node); return tempNode; } public void inOrderTreeWalk(TreapsNode<T> node) { if (node != null) { inOrderTreeWalk(node.getLeftChild()); System.out.println(node.getKey() + ":" + node.getSatelliteData()); inOrderTreeWalk(node.getRightChild()); } } /*☆较简单——前序遍历递归过程 */ private void recursePreOrder(TreapsNode<T> node) { if (node != null) { System.out.println(node.getKey() + ":" + node.getSatelliteData()); recursePreOrder(node.getLeftChild()); recursePreOrder(node.getRightChild()); } } /*☆较简单——前序遍历递归过程 */ public void recursePreOrder() { recursePreOrder(root); } public void inOrderTreeWalk() { inOrderTreeWalk(root); } }3、测试
public class TreapsTest { /** * @param args */ public static void main(String[] args) { // TODO 自动生成的方法存根 TreapsNode<String> root=new TreapsNode<String>(7, "G"); root.setPrioity(4); TreapsNode<String> node1=new TreapsNode<String>(2, "B"); node1.setPrioity(2); TreapsNode<String> node2=new TreapsNode<String>(1, "A"); node2.setPrioity(1); TreapsNode<String> node3=new TreapsNode<String>(5, "E"); node3.setPrioity(23); TreapsNode<String> node5=new TreapsNode<String>(8, "H"); node5.setPrioity(5); TreapsNode<String> node6=new TreapsNode<String>(11, "K"); node6.setPrioity(63); TreapsNode<String> node8=new TreapsNode<String>(9, "I"); node8.setPrioity(73); Treap<String> treap=new Treap<>(root); treap.add(node1); treap.add(node2); treap.add(node3); treap.add(node5); treap.add(node6); treap.add(node8); treap.recursePreOrder(); } }**************************************************************
控制台输出:前序和中序符合算法导论中335页图13.10(a)
【算法导论学习-25】 二叉树专题3:Treaps