BST & Treap
二叉查找树递归定义:
二叉查找树是空树或不是空树
二叉查找树的左二叉查找树的值一定小于二叉查找树的值或左二叉查找树为空树
二叉查找树的右二叉查找树的值一定大于二叉查找树的值或右二叉查找树为空树
不维护父亲域的,坑爹啊。
放上代码:
#include <iostream>
#include <string>
using namespace std; #define NEW(d) new BST(d) struct BST {
BST *lc, *rc;
int data;
BST() : lc(0), rc(0) {}
BST(int d) : lc(0), rc(0), data(d) {}
}*root = NULL; typedef BST* tree; void insert(int d) {
if(root == NULL) { root = NEW(d); return;}
tree t, now = root;
//二分找到合适的位置,t是指向这个合适的位置的指针
while(now != NULL) {
t = now;
if(now-> data > d) now = now-> lc;
else now = now-> rc;
}
//插入新值到左边(或右边)
if(t-> data > d) t-> lc = NEW(d);
else t-> rc = NEW(d);
}
//没有父亲域的这个就是巨坑
void del(int d) {
tree t, q = root, rt = root;
while(rt != NULL && rt-> data != d) {
q = rt;
if(rt-> data > d) rt = rt-> lc;
else rt = rt-> rc;
}
//如果删除的是root
if(q == root) {delete root; root = NULL; return;}
//如果不存在
if(rt == NULL) return;
//如果有一边是空的,那么将另一棵子树拉上来即可,在这里,已经包含了当两边都是空树时
if(rt-> lc == NULL) {
if(q-> lc == rt) q-> lc = rt-> rc;
else q-> rc = rt-> rc;
delete rt;
return;
}
if(rt-> rc == NULL) {
if(q-> lc == rt) q-> lc = rt-> lc;
else q-> rc = rt-> lc;
delete rt;
return;
}
t = rt;
q = rt-> rc;
while(q-> lc) {
t = q;
q = q-> lc;
}
rt-> data = q-> data;
if(t != rt) t-> lc = q-> rc;
else t-> rc = q-> rc;
delete q;
} tree search(int d) {
tree ret = root;
while(ret != NULL && ret-> data != d) {
if(ret-> data > d) ret = ret-> lc;
else ret = ret-> rc;
}
return ret;
} tree max(){
if(root == NULL) return NULL;
tree ret = root;
while(ret-> rc) ret = ret-> rc;
return ret;
} tree min(){
if(root == NULL) return NULL;
tree ret = root;
while(ret-> lc) ret = ret-> lc;
return ret;
} void out(string str) {
cout << str;
} int main() {
out("1: insert\n2: del\n3: search\n4: max\n5: min\n");
int c, t;
tree a;
while(cin >> c) {
switch(c) {
case 1: cin >> t;
insert(t);
break;
case 2: cin >> t;
del(t);
break;
case 3: cin >> t;
if(search(t) == NULL) out("Not here\n");
else out("Is here!\n");
break;
case 4: a = max();
if(a != NULL) cout << a-> data << endl;
else out("Warn!\n");
break;
case 5: a = min();
if(a != NULL) cout << a-> data << endl;
else out("Warn!\n");
break;
default:
break;
}
}
return 0;
}
因为有些坑爹,所以还是写递归版的del
void del(tree& rt, int d) {
if(rt == NULL) return;
if(rt-> data > d) del(rt-> lc, d);
else if(rt-> data < d) del(rt-> rc, d);
else {
tree q, t;
if(rt-> lc == NULL) {
q = rt;
rt = rt-> rc;
delete q;
return;
}
if(rt-> rc == NULL) {
q = rt;
rt = rt-> lc;
delete q;
return;
}
q = rt-> rc, t = rt;
//找后继
while(q-> lc != NULL) {
t = q;
q = q-> lc;
}
rt-> data = q-> data;
//当后继就是右子女,那么要将后继的右子女接到节点右边
if(rt == t) t-> rc = q-> rc;
//否则就要给后继的父亲的左子女赋值为后继的右子女
else t-> lc = q-> rc;
delete q;
}
}
写个简洁的把,,,维护个父亲域。。旋转也好写了= =。
#include <iostream>
#include <string>
using namespace std; #define NEW(d) new BST(d) struct BST {
BST *lc, *rc, *pa;
int data;
BST() : lc(0), rc(0), pa(0) {}
BST(int d) : lc(0), rc(0), pa(0), data(d) {}
//BST operator= (BST& a) { lc = a.lc; rc = a.rc; pa = a.pa; data = a.data; return *this; }
}*root = NULL; typedef BST* tree; void insert(int d) {
if(root == NULL) { root = NEW(d); return;}
tree t, now = root;
//二分找到合适的位置,t是指向这个合适的位置的指针
while(now != NULL) {
t = now;
if(now-> data > d) now = now-> lc;
else now = now-> rc;
}
//插入新值到左边(或右边)
if(t-> data > d) t-> lc = NEW(d), t-> lc-> pa = t;
else t-> rc = NEW(d), t-> rc-> pa = t;
} tree search(int d) {
tree ret = root;
while(ret != NULL && ret-> data != d) {
if(ret-> data > d) ret = ret-> lc;
else ret = ret-> rc;
}
return ret;
} void del(int d) {
tree rt = search(d), t, q;
if(rt == root) { delete root; root = NULL; return; }
if(rt == NULL) return;
if(rt-> lc == NULL) {
if(rt-> pa-> lc == rt) rt-> pa-> lc = rt-> rc;
else rt-> pa-> rc = rt-> rc;
delete rt;
return;
}
if(rt-> rc == NULL) {
if(rt-> pa-> lc == rt) rt-> pa-> lc = rt-> lc;
else rt-> pa-> rc = rt-> lc;
delete rt;
return;
}
q = rt-> rc, t = rt;
while(q-> lc) {
t = q;
q = q-> lc;
}
rt-> data = q-> data;
if(t != rt) t-> rc = q-> rc;
else t-> lc = q-> rc;
delete q;
} tree max(){
if(root == NULL) return NULL;
tree ret = root;
while(ret-> rc) ret = ret-> rc;
return ret;
} tree min(){
if(root == NULL) return NULL;
tree ret = root;
while(ret-> lc) ret = ret-> lc;
return ret;
} void out(string str) {
cout << str;
} int main() {
out("1: insert\n2: del\n3: search\n4: max\n5: min\n");
int c, t;
tree a;
while(cin >> c) {
switch(c) {
case 1: cin >> t;
insert(t);
break;
case 2: cin >> t;
del(t);
break;
case 3: cin >> t;
if(search(t) == NULL) out("Not here\n");
else out("Is here!\n");
break;
case 4: a = max();
if(a != NULL) cout << a-> data << endl;
else out("Warn!\n");
break;
case 5: a = min();
if(a != NULL) cout << a-> data << endl;
else out("Warn!\n");
break;
default:
break;
}
}
return 0;
}
BST & Treap的更多相关文章
- hihocoder-平衡树·SBT
http://hihocoder.com/problemset/problem/1337 #1337 : 平衡树·SBT 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 ...
- 模板库 ~ Template library
TOC 建议使用 Ctrl+F 搜索 . 目录 小工具 / C++ Tricks NOI Linux 1.0 快速读入 / 快速输出 简易小工具 无序映射器 简易调试器 文件 IO 位运算 Smart ...
- fhq treap最终模板
新学习了fhq treap,厉害了 先贴个神犇的版, from memphis /* Treap[Merge,Split] by Memphis */ #include<cstdio> # ...
- COGS 2421.[HZOI 2016]简单的Treap 题解
题目大意: 给定n个数及其优先级,求对应的符合最小堆性质的Treap的先序遍历. n<=500000. 解法: 目前为止我只想到了三种解法,其中第三种是正解. 1.暴力1 以优先级为关键字排序, ...
- Treap树的基础知识
原文 其它较好的的介绍:堆排序 AVL树 树堆,在数据结构中也称Treap(事实上在国内OI界常称为Traep,与之同理的还有"Tarjan神犇发明的"Spaly),是指有一个随 ...
- Treap和名次树
Treap名字的来源:Tree+Heap,正如名字一样,就是一颗简单的BST,一坨堆的合体.BST的不平衡的根本原因在于基于左<=根<=右的模式吃单调序列时候会无脑成长链,而Treap则添 ...
- 斜堆,非旋转treap,替罪羊树
一.斜堆 斜堆是一种可以合并的堆 节点信息: struct Node { int v; Node *ch[]; }; 主要利用merge函数 Node *merge(Node *x, Node *y) ...
- 查找——图文翔解Treap(树堆)
之前我们讲到二叉搜索树,从二叉搜索树到2-3树到红黑树到B-树. 二叉搜索树的主要问题就是其结构与数据相关,树的深度可能会非常大,Treap树就是一种解决二叉搜索树可能深度过大的还有一种数据结构. T ...
- 数据结构录 之 BST的高级应用。
BST就是二叉检索树,或者是二叉排序树,或者叫二叉搜索树等等. BST的平衡问题可以去学习AVL树或者Treap或者Splay这些平衡树. BST的一些高级应用: 1,求BST中比k小的数的个数: 只 ...
随机推荐
- python 之验证码
验证码原理在于后台自动创建一张带有随机内容的图片,然后将内容通过img标签输出到页面. 安装图像处理模块: pip3 install pillow
- django-cms 代码研究(六)plugin的深入分析
示例代码: https://github.com/divio/djangocms-picture 以上一个图片的插件,安装后可在页面中添加图片,效果如下图: 以此为切入点,分析plugin的逻辑: 分 ...
- Having与Where的区别
where 子句的作用是在对查询结果进行分组前,将不符合where条件的行去掉,即在分组之前过滤数据,where条件中不能包含聚组函数,使用where条件过滤出特定的行. having 子句的作用是筛 ...
- 《ASP.NET1200例》<ItemTemplate>标签在html里面有什么具体的作用
严格的来说 <ItemTemplate> 在html中无意义,他只是针对诸如 Repeater.DataList.GridView中的一个模板 至于里面的含义,你可以这样想,既然Repea ...
- C++使用throw抛出异常
引用: c++ 使用throw抛出异常 抛出异常(也称为抛弃异常)即检测是否产生异常,在C++中,其采用throw语句来实现,如果检测到产生异常,则抛出异常.该语句的格式为:throw 表达式; ...
- js ==与===区别(两个等号与三个等号)
1.对于string,number等基础类型,==和===是有区别的 1)不同类型间比较,==之比较“转化成同一类型后的值”看“值”是否相等,===如果类型不同,其结果就是不等 2)同类型比较,直接进 ...
- Windows下配置Apache服务器并支持php
php环境的配置相对来说比较繁琐,网上教程大部分都是放一起说,总体感觉比较乱,其实Apache是一款通用的服务器软件,可以用来配置支持静态页面,php.Python.Java甚至asp等服务端语言,要 ...
- Android开发数据库三层应用-DataSnap
Android开发数据库三层应用-DataSnap http://www.2ccc.com/news/Html/?1517.html 核心提示:我觉得Delphi最强大的的功能之一就是开发数据库三层应 ...
- canvas实践小实例二 —— 扇形
俗话说:发图不留种,菊花万人捅!我这里想延伸一下:教学不给例,说你是傻逼!哎呀,还挺押韵,嘻嘻,开个玩笑! 我们都讲了四期API的知识了,估计大家看的也是枯燥的很啊,前面的小实例也是太简单,简直不解渴 ...
- iOS通过设置info.plist参数使用iTunes导入导出Documents目录下的文件
参考网址: http://my.oschina.net/hmj/blog/112592 http://www.cnblogs.com/taintain1984/archive/2013/05/27/3 ...