- 浏览: 149648 次
- 性别:
- 来自: 武汉
文章分类
最新评论
-
hardPass:
貌似二分法,没有一个合并的过程
简单_分治算法 -
zhufeng1981:
讲解的不错,支持一下。
简单_分治算法 -
a346063587:
嗯。。的确,基础很重要!
关于递归和尾递归的原理 -
zhufeng1981:
huoyj 写道基础很重要,这是永远不变的真理。 很赞同这句话 ...
关于递归和尾递归的原理 -
huoyj:
基础很重要,这是永远不变的真理。 很赞同这句话
关于递归和尾递归的原理
我们可以看到,如果一个二叉排序树节点插入的顺序是随机的,这样我们得到的二叉排序树大多数情况下是平衡的,即使存在一些极端情况,但是这种情况发生的概率很小,所以我们可以这样建立一颗二叉排序树,而不必要像AVL那样旋转,可以证明随机顺序建立的二叉排序树在期望高度是,但是某些时候我们并不能得知所有的带插入节点,打乱以后再插入。所以我们需要一种规则来实现这种想法,并且不必要所有节点。也就是说节点是顺序输入的,我们实现这一点可以用Treap。
Treap=Tree+Heap
Treap是一棵二叉排序树,它的左子树和右子树分别是一个Treap,和一般的二叉排序树不同的是,Treap纪录一个额外的数据,就是优先级。Treap在以关键码构成二叉排序树的同时,还满足堆的性质(在这里我们假设节点的优先级大于该节点的孩子的优先级)。但是这里要注意的是Treap和二叉堆有一点不同,就是二叉堆必须是完全二叉树,而Treap可以并不一定是。
貌似TreapDB用的就是Treap算法实现的,当然肯定还有其他的数据结构进行了混搭。
Treap=Tree+Heap
Treap是一棵二叉排序树,它的左子树和右子树分别是一个Treap,和一般的二叉排序树不同的是,Treap纪录一个额外的数据,就是优先级。Treap在以关键码构成二叉排序树的同时,还满足堆的性质(在这里我们假设节点的优先级大于该节点的孩子的优先级)。但是这里要注意的是Treap和二叉堆有一点不同,就是二叉堆必须是完全二叉树,而Treap可以并不一定是。
貌似TreapDB用的就是Treap算法实现的,当然肯定还有其他的数据结构进行了混搭。
package sunfa.tree; import java.util.Comparator; import java.util.Random; /** * 随机平衡二叉树Treap=Tree+heap,Tree取前3个单词,heap取后2个单词 * * 其实这棵树还是比较好理解的,与普通的BST相比节点多了个随机数,普通BST的旋转是以插入的key的大小为评判标准的,<br> * 而Treap是以节点的随机数的大小作为评判标准的。为什么要给节点弄个随机数呢?因为普通的BST之所以会退化为线性表<br> * 主要原因是顺序插入造成的。 * * @param <K> * @param <V> */ public class Treap<K, V> { public static void main(String[] args) { Treap<Integer, Integer> tree = new Treap<Integer, Integer>( new Comparator<Integer>() { public int compare(Integer o1, Integer o2) { return o1 - o2; } }); //测试200W条数据插入Treap树 时间是1600毫秒左右,树的深度:50 long start = System.currentTimeMillis(); for (int i = 0; i < tree.n; i++) { tree.put(i, i); } System.out.println(System.currentTimeMillis()-start); System.out.println("h:" + tree.h()); // tree.printTree(tree.root); } Comparator<K> comp; public Treap(Comparator<K> c) { this.comp = c; } private Entry<K, V> root; private Random ran = new Random(); private int n = 2000000; private void printTree(Entry<K, V> node) { if (node == null) return; System.out.print("[" + node.key + "=" + node.fix + "],"); printTree(node.left); printTree(node.right); } public void put(K key, V value) { put0(null, root, key, value, 2); } /** * 插入的方式和SBT类似 * @param p 根节点 * @param node 插入节点 * @param key * @param value * @param i */ private void put0(Entry<K, V> p, Entry<K, V> node, K key, V value, int i) { if (key == null) throw new NullPointerException(); if (node == null) { node = new Entry<K, V>(p, null, null, key, value, ran.nextInt(n)); if (null == this.root) this.root = node; if (i == 0) p.left = node; else if (i == 1) p.right = node; return; } int c = compare(key, node.key); if (c < 0) { put0(node, node.left, key, value, 0); if (node.left.fix < node.fix) // 之所以递归put0里面进行旋转也是为了压缩路径,改成非递归的形式就起不到路径压缩了,和SBT树的插入算法类似 rightRotate(node); } else { put0(node, node.right, key, value, 1); if (node.right.fix < node.fix) leftRotate(node); } } /** * Treap的查找和普通的BST的查找一样,并且不会改变Treap的结构 * @param key * @return */ public V get(K key) { Entry<K, V> entry = getEntry(key); return entry==null?null:entry.value; } private Entry<K, V> getEntry(K key){ if (key == null) return null; Entry<K, V> t = root; while (true) { int c = compare(key, t.key); if (c == 0) { return t; } else if (c < 0) { if (t.left != null) t = t.left; else return null; } else { if (t.right != null) t = t.right; else return null; } } } private int compare(K k1, K k2) { return this.comp != null ? (((comp).compare(k1, k2))) : (((Comparable<K>) k1).compareTo(k2)); } // public V remove(K key){ // Entry<K, V> entry = getEntry(key); // if(entry==null) // return null; // // } private void delete0(Entry<K, V> p,K key){ int c = compare(key, p.key); if(c==0){ if(p.left==null || p.right==null){ Entry<K, V> t = p; if(p.right==null){ p = p.left; }else{ p = p.right; } } } } private void leftRotate(Entry<K, V> x) { // ① Entry<K, V> y = x.right;// 分离出旋转元素的右子节点 // ② x.right = y.left;// 旋转元素的右子节点的左子节点挂接到旋转元素的右子节点处 if (y.left != null) { y.left.parent = x;// } // ③ y.parent = x.parent;// 分离出来的部分挂接到旋转元素的父节点下 if (x.parent == null) {// 如果旋转元素为根节点,就让旋转元素成为根 this.root = y; } else if (x == x.parent.left) {// 如果旋转元素是它父节点的左子节点,让旋转元素父节点的左指针指向分离出的节点 x.parent.left = y; } else {// 如果是右子节点,就用父节点的右指针指向分离节点 x.parent.right = y; } // ④ y.left = x;// 分离出来的部分的左子节点指向旋转元素 x.parent = y;// 旋转元素的父节点指向分离出的元素 } private void rightRotate(Entry<K, V> x) { // ① Entry<K, V> y = x.left;// 分离出旋转元素的右子节点 // ② x.left = y.right;// 旋转元素的右子节点的左子节点挂接到旋转元素的右子节点处 if (y.right != null) y.right.parent = x;// // ③ y.parent = x.parent;// 分离出来的部分挂接到旋转元素的父节点下 if (x.parent == null) {// 如果旋转元素为根节点,就让旋转元素成为根 this.root = y; } else if (x == x.parent.left) {// 如果旋转元素是它父节点的左子节点,让旋转元素父节点的左指针指向分离出的节点 x.parent.left = y; } else {// 如果是右子节点,就用父节点的右指针指向分离节点 x.parent.right = y; } // ④ y.right = x;// 分离出来的部分的左子节点指向旋转元素 x.parent = y;// 旋转元素的父节点指向分离出的元素 } public int h() { return h0(this.root); } private int h0(Entry<K, V> p) { if (p == null) return -1; return 1 + Math.max(h0(p.left), h0(p.right)); } static class Entry<K, V> { Entry<K, V> parent, left, right; K key; V value; int fix;//随机数 public Entry(Entry<K, V> parent, Entry<K, V> left, Entry<K, V> right, K key, V value, int fix) { super(); this.parent = parent; this.left = left; this.right = right; this.key = key; this.value = value; this.fix = fix; } } }
发表评论
-
答复: 百度一面算法题(常数时间内求栈中最大值)
2011-11-04 23:36 2325yeshaoting 写道 算法描 ... -
<转>李开复:算法的力量
2011-11-04 19:17 747算法是计算机科学领域最重要的基石之一,但却受到了国内一些程序员 ... -
简单_分治算法
2011-10-29 19:44 1963分治算法,多么简单的思想!可是它无处不在。btree,b+树中 ... -
由HashMap的实现联想到的
2011-10-25 21:42 890首先温故一下java.util.HashMap的实现 int ... -
关于递归和尾递归的原理
2011-10-25 21:05 3040基础很重要,这是永远不变的真理。 package sunf ... -
关于Swing打印二叉树
2011-10-21 21:52 2335[img][/img]最近研究二叉树一类的树结构,总用调试的办 ... -
简单_伸展树(Splay tree)
2011-10-21 21:00 1639如果你注意观察你会发现,输入法就打某个字,如果你下次还打那个字 ... -
简单_Trie树与三叉Trie树
2011-10-20 21:10 2484package sunfa.tree; import ... -
简单_快速选择算法(RANDOMIZED-SELECT)
2011-10-19 23:32 5876package sunfa.midNum; impo ... -
字符匹配算法(KMP)
2011-10-18 22:15 1439package sunfa.kmp; /** * ... -
简单_堆排序算法
2011-10-18 16:19 1333package sunfa.sort; import ... -
简单_插入排序(Insertion-sort)
2011-10-18 10:48 1029package sunfa.sort; import ... -
简单_二叉堆
2011-10-16 13:40 1180堆是一种比较有用的数据结构,是二叉树的一种数组的表示形式。 ... -
关于:一道腾讯面试题:从大量数字中取出top100
2011-10-14 23:51 1851一道腾讯面试题:从大量数字中取出top100 http://w ... -
BloomFilter(布隆过滤器)
2011-10-11 19:30 1057package sunfa; import java ... -
图解双链表
2011-09-28 10:48 1112以java.util.LinkedList源码结合本人用XP自 ... -
简单_快速排序
2011-09-19 23:20 1037/** 快速排序方法 */ public static ... -
简单_二分法算法
2011-09-11 10:53 1081package sunfa; //二分法查找 pu ... -
简单_基本二叉树(BST)
2011-09-11 10:52 1656package sunfa.tree; import ... -
简单_单链表
2011-09-11 10:49 935package sunfa; import java ...
相关推荐
查找算法,平衡二叉树,大话数据结构里面的。
输入一组关键字序列,并以此顺序建立一棵平衡二叉树(提示:为简化运算,可采用含有左、右子树高度和指向父母的指针的三叉链表表示),并在建树过程中用逆中序法输出每次插入新结点后的平衡二叉树形状。
详细的二叉树画法,和其他的有所不同,很有特色的。
将平衡二叉树的增删改查集成到了一起,提供友好的界面。
平衡二叉树,又称为AVL树,是1962年由Adelsonr Velskii 和Landis 提出并以他们的名字命名的,它是具有如下性质的二叉树:
数据结构c语言源代码,包括链表操作、二叉树排序等经典算法
代码实现了二叉树基本操作:实现二叉树的基本操作(包括前序、中序、后序遍历);从键盘读数,利用前面实现的基本操作,生成一棵二叉查找树;通过遍历二叉树,输出该二叉树的叶节点数;通过遍历二叉树,求二叉树的...
图形化打印二叉树 方便在控制台中浏览你所生成的二叉树
输入字符,建立平衡二叉树,再输出字符,中序,抛砖引玉
利用平衡二叉树实现一个动态查找表 实现动态查找表的三种基本功能:查找、插入和删除
平衡二叉树的插入 删除和查找 分裂 合并等操作
201900302030_邵嘉明_实验五 二叉树操作1
15_平衡二叉树.pdf
平衡二叉树Java实现,平衡二叉树Java实现,平衡二叉树Java实现,平衡二叉树Java实现,
许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个结点最多只能有两棵子树,且有左右之...
用JAVASCRIPT+VML实现平衡二叉树里增加节点删除节点的功能,目的是把二叉树的平衡算法记录在这里(备忘)。 目前只做了增加删除节点时二叉树自动平衡,保证这棵树什么时候都是平衡状态;如何将一棵不平衡的二叉树...
实现二叉树链表表示的二叉树: 建立一棵二叉树; 按先序、中序和后序遍历二叉树; 按层次遍历; 求一棵二叉树的高度; 交换一棵二叉树的左右子树; 复制一棵二叉树。
二叉树遍历 包括先序遍历 中序遍历 后序遍历 求结点个数 求树的深度
1_树和二叉树实验一.cpp
按先序扩展序列建立二叉树,先序、中序、后序遍历的递归算法,二叉树遍历的非递归算法,层次的非递归算法,求二叉树的深度。