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小的数的个数: 只 ...
随机推荐
- 最长递增子序列问题 nyoj 17单调递增最长子序列 nyoj 79拦截导弹
一, 最长递增子序列问题的描述 设L=<a1,a2,…,an>是n个不同的实数的序列,L的递增子序列是这样一个子序列Lin=<aK1,ak2,…,akm>,其中k1< ...
- Segment Tree Query I & II
Segment Tree Query I For an integer array (index from 0 to n-1, where n is the size of this array), ...
- 如何调试lua脚本
首先感谢下ZeroBrane Studio. 这里拿cocos2dx/samples/Lua/HelloLua做例子来说明,其他的都是同样道理. 1.下载调试Lua所需的IDE,地址在这.有经济实力的 ...
- Windows下配置Tomcat服务器
Tomcat服务器是Apache开源基金会的一个项目,tomcat不仅能作为静态文件的服务器,也可以作为JSP/Servlet的web容器,而且使用广泛,性能也不错,那么下面来配置一个基本的基于tom ...
- Linux下安装firefox最新版
Linux刚安装好的时候,默认是火狐浏览器并且版本比较低,我的系统是CentOS,火狐版本号才31,用yum安装的话版本也不是最新,只要从官方网站下载最新版安装就可以了,方法如下: 首先去火狐主页,中 ...
- php的socket通信(二)
案例一:代码详解 // 设置一些基本的变量$host = "192.168.1.99";$port = 1234;// 设置超时时间set_time_limit(0);// 创建一 ...
- 在Win8中创建热点,共享网络
在Win8中创建热点,共享网络 办公室中,我独享10M光纤,没什么要下的,便想利用来更新下Ipad里面的程序,下点公开课.那在不利用软件[用很多wifi共享的软件],从win7开始 系统本身就自带相关 ...
- 打开genesis时一直在等待,后出现Timeout in communication read解决方法
运行输入:netsh winsock reset 然后重启电脑
- yum_rpm(利用dvd建立本地yum库)
#wget "http://mirrorlist.centos.org/?release=6&arch=x86_64&repo=os" 建立起了index.html ...
- JUC系列回顾之-CountDownLatch底层原理和示例
CountDownLatch 是一个同步工具类,允许一个线程或者多个线程等待其他线程完成操作,再执行. CountDownLatch(int count) 构造一个用给定计数初始化的 CountDow ...