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小的数的个数: 只 ...
随机推荐
- 《转》常用Petri网模拟软件工具简介
本文转载自liusj2003,如给您带来不便之处,请联系博主. 首先要介绍的的一个非常有名的Petri 网网站--Petri Nets World: http://www.informatik.uni ...
- iOS NSOperation的使用
先给出NSOpetation的官方指导https://developer.apple.com/library/ios/documentation/Cocoa/Reference/NSOperation ...
- Android 和iOS中 Gesture 和 Touch
先谈谈在开发中遇到的手势问题: 今天在开发android程序时,在 View.OnTouchListener 的 onTouch(View view, MotionEvent motionEvent) ...
- msysgit ls 中文显示
2013年10月17日 14:54:15 安装了新版的msysgit后,在其自带的 git bash 命令行下就可以输入中文汉字了 但是创建了中文名字命名的文件后,再用 ls 命令查询时会出现乱码的情 ...
- Bootstrap分页插件:bootstrap-paginator
今天和大家分享一个Bootstrap的分页插件:bootstrap-paginator. 插件地址: https://github.com/lyonlai/bootstrap-paginator 先看 ...
- UVALive 7269 Snake Carpet (构造)
题目:传送门. 题意:构造出一个矩阵,使得矩阵含有n条蛇,每条蛇的长度是1到n,并且奇数长度的蛇有奇数个拐弯,偶数长度 的蛇有偶数个拐弯. 奇数和偶数分开构造,奇数可以是: 1357 3357 555 ...
- sublime text 3 使用过程总结记录
自定义的设置: "save_on_focus_lost": true //在文件失去焦点的时候自动保存
- CSS鼠标样式整理
鼠标样式的标签: cursor:*; //该属性定义了鼠标指针放在一个元素边界范围内时所用的光标形状: 鼠标样式: 值 描述 url 需使用的自定义光标的 URL. 注释:请在此列表的末端始终定义一 ...
- 仓鼠找sugar(洛谷 3398)
题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而他的基友同时要从他的卧室(c) ...
- Tomcat热部署和虚拟目录配置
1.Tomcat如何配置热部署 默认就是 <Host appBase="webapps" autoDeploy="true" name="loc ...