博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Treap树
阅读量:6705 次
发布时间:2019-06-25

本文共 7547 字,大约阅读时间需要 25 分钟。

Treap树包含所有二叉树的性质,但是以一个随机的优先值排序。《算法导论》关于这个Treap树的原理和实现描述非常少,我就直接给代码吧,原理大家自己百度了。

首先定义的个类

template 
class tp_tree {public: typedef struct _tp_type { _tp_type(_tp_type *_p, _tp_type *_left, _tp_type *_right, T _key, int _pr) : parent(_p), left(_left), right(_right), key(_key), priority(_pr) {} T key; int priority; _tp_type *left, *right, *parent; }tp_type, *ptp_type; tp_tree(T *A, int n) :root(NULL) { R = hash_mod(n, 3); priority_table = new T[R*R];//哈希表 seed = hash_seed(NULL, R); memset(priority_table, 0, sizeof(T)*R*R); printf("R=%d, Max slot=%d\n", R, R*R); for (int i = 0; i < n; i++) tp_insert(A[i]); } ~tp_tree() { tp_empty(root); hash_seed_free(seed); hash_seed_free(priority_table); } void left_rotate(ptp_type x); void right_rotate(ptp_type x); void tp_insert(T key); ptp_type tp_search(T key); void tp_delete(T key); void tp_empty(ptp_type x); void tp_show(ptp_type x); ptp_type tp_root();private: int hash_mod(int n, int iCheck);//取大小 int *hash_seed(int *pKey, int R);//获取种子 void hash_seed_free(int *v);//释放种子 int hash(int key, int R, int *v);//哈希映射 void tp_insert_fixup(ptp_type x); //测试使用 int tp_max_depth(ptp_type x); int tp_min_depth(ptp_type x); ptp_type root; int *seed, R; T *priority_table;//用于保留T对象,下标是优先值};

关于各个成员实现

left_roate函数

template 
void tp_tree
::left_rotate(typename tp_tree
::ptp_type x) { ptp_type y = x->right;//y非空 x->right = y->left; if (y->left) y->left->parent = x;//交换子节点 y->parent = x->parent;//更新父节点 if (x->parent == NULL)//将y连接到x的父节点 root = y; else { if (x == x->parent->left) x->parent->left = y; else x->parent->right = y; } y->left = x; x->parent = y;}

right_rotate函数

template 
void tp_tree
::right_rotate(typename tp_tree
::ptp_type x) { ptp_type y = x->left; x->left = y->right; if (y->right) y->right->parent = x; y->parent = x->parent; if (x->parent == NULL) root = y; else { if (x == x->parent->left) x->parent->left = y; else x->parent->right = y; } y->right = x; x->parent = y;}

tp_insert函数

template 
void tp_tree
::tp_insert(T key) { ptp_type z = NULL, x = root, y = NULL; //生成优先值 int m = hash(key, R, seed);//T类对象,一定要自己实现一个operator int(),使用指针就不需要了 while (priority_table[m])//循环检查优先表是否被占用 m = (m + 1) % (R*R); priority_table[m] = key; z = new tp_type(NULL, NULL, NULL, key, m); while (x) { y = x;//保留根节点 if (key < x->key) x = x->left; else x = x->right; } if (y == NULL) root = z; else { if (key < y->key) y->left = z; else y->right = z; z->parent = y; } tp_insert_fixup(z);}

tp_insert_fixup成员,插入后修复函数

template 
void tp_tree
::tp_insert_fixup(typename tp_tree
::ptp_type x) { ptp_type y; while ((y = x->parent) && x->parent->priority > x->priority) {
//始终保持父节点的优先值最小 if (y->right == x) left_rotate(y); else if (y->left == x) right_rotate(y); }}

tp_search成员函数

template 
typename tp_tree
::ptp_type tp_tree
::tp_search(T key) { ptp_type x = root; while (x != NULL && key != x->key) { if (key < x->key) x = x->left; else x = x->right; } return x;}

tp_delete成员函数,采用堆删除方式,在删除的同时中,就修复了节点

template 
void tp_tree
::tp_delete(T key) { ptp_type x = tp_search(key), y; if (x == NULL) return; while (x->left != NULL && x->right != NULL) {
//treap堆式删除,将需要的删除的节点通过旋转,移动出来 if (x->left->priority < x->right->priority) right_rotate(x); else left_rotate(x); } y = x;//保留待删除节点 if (x == root) root = x->left ? x->left : x->right; else if (x->parent->right == x) x->parent->right = x->left ? x->left : x->right; else x->parent->left= x->left ? x->left : x->right; //清理哈希优先表 int m = hash(key, R, seed);//T类对象,一定要自己实现一个operator int(),使用指针就不需要了 while (priority_table[m]) {
//循环检查优先表是否被占用 if (priority_table[m] == key) break;//T类对象还要实现一个operator =(),使用指针就不需要了 m = (m + 1) % (R*R); } priority_table[m] = 0; //printf("key=%d,hash priority=%d\n", key, m); delete y;}

tp_empty成员函数,删除所有节点

template 
void tp_tree
::tp_empty(typename tp_tree
::ptp_type x) { if (x != NULL) { tp_empty(x->left); tp_empty(x->right); tp_delete(x->key); }}

tp_show成员,显示节点,用了AVL树的求深度算法,方便观察并验证算法是否正确

template 
void tp_tree
::tp_show(typename tp_tree
::ptp_type x) { if (x != NULL) { tp_show(x->left); if (x == root) printf("[root]key=%d, priority=%d (%d, %d)\n", x->key, x->priority, tp_max_depth(x),tp_min_depth(x)); else printf("key=%d, priority=%d (%d, %d)\n", x->key, x->priority, tp_max_depth(x), tp_min_depth(x)); tp_show(x->right); }}
//测试使用template 
int tp_tree
::tp_max_depth(typename tp_tree
::ptp_type x) { if (x == NULL) return 0; int l = tp_max_depth(x->left); int r = tp_max_depth(x->right); return (l > r ? l : r) + 1;}template
int tp_tree
::tp_min_depth(typename tp_tree
::ptp_type x) { if (x == NULL) return 0; int l = tp_min_depth(x->left); int r = tp_min_depth(x->right); return (l < r ? l : r) + 1;}

tp_root成员函数

template 
typename tp_tree
::ptp_type tp_tree
::tp_root() { return root;}

下面几个成员函数,基本来自于之前我写的hash算法那章节,所以没什么好说的

template 
int tp_tree
::hash_mod(int n, int iCheck) { int iStart = n / iCheck, prime = (iStart == 1) ? 2 : iStart; assert(iCheck >= 0 && iCheck <= 8); //odd起始要跳过已经判断了的奇数 for (int j = 0, odd = (iStart % 2 == 0) ? iStart / 2 : (iStart - 1) / 2 + 1; j < 8 - iCheck; odd++) { //生成一个素数 bool fPrime = true; for (int k = 2; k <= sqrt(prime); k++) if (prime % k == 0) { fPrime = false; break; } if (fPrime) //记录素数 j++; prime = odd * 2 + 1;//待判断的奇数 } return prime - 2;}template
int *tp_tree
::hash_seed(int *pKey, int R) { int *v = new int[R], key; memset(v, 0, R * sizeof(R)); if (pKey == NULL) { srand(time(NULL)); for (int i = 0; i < R; i++) v[i] = rand() % R; } else { key = *pKey; for (int i = 0; i < R && key; i++) { v[i] = key % R; key = key / R; } } return v;}template
void tp_tree
::hash_seed_free(int *v) { delete[] v;}template
int tp_tree
::hash(int key, int R, int *v) { int slot = 0, M = R*R; int *numV = hash_seed(&key, R); for (int i = 0; i < R; i++) slot += numV[i] * v[i]; hash_seed_free(numV); return slot % M;}

 

所有代码均经过测试,结果正确!

转载于:https://www.cnblogs.com/dalgleish/p/9071387.html

你可能感兴趣的文章
java.lang.UnsupportedClassVersionError: Bad version number in .class file
查看>>
grub启动引导装载程序总结。
查看>>
XIV(3)--Read/Write Operations
查看>>
route OS(MikroTik)2.9.27初探
查看>>
tomcat配置优化
查看>>
[转]Javascript 中 String.replace( ) 的妙用
查看>>
分布式系统开发的一些相关理论基础——CAP、ACID、BASE
查看>>
探讨防火墙内核监听模式:ISA2006系列之十六
查看>>
android滑动一个路线后 人物图片按此路线移动的实现
查看>>
【电信增值业务学习笔记】9基于智能网的增值业务实现技术和应用
查看>>
Winform文件下载之WebClient
查看>>
【REACT NATIVE 系列教程之六】重写SHOULDCOMPONENTUPDATE指定组件是否进行重绘
查看>>
《完美软件》读书笔记11:信息摄取
查看>>
剖析SQL Server 2005查询通知之基础篇
查看>>
Windows 2003系统下桌面清理向导
查看>>
Exchange2007中使用各种限制选项
查看>>
NeHe OpenGL第四十四课:3D光晕
查看>>
eclipse + JBoss 5 + EJB3开发指南(13):在Servlet中访问应用程序管制EntityManager对象...
查看>>
NHibernate测试的几个小问题
查看>>
Idea开发Java WEB 应用入门教程
查看>>