普通平衡树是什么?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1111个文字,预计阅读时间需要5分钟。
题目描述:实现一个基于Treap的模板题,要求描述题目思路、使用Treap结构的原因以及给出相关代码。
思路:
1.使用Treap结构存储元素,利用其随机性维护平衡,保证操作效率。
2.在插入、删除和查找元素时,利用旋转操作维护Treap的平衡。
3.对于查找、插入和删除操作,分别处理元素相同的情况。
使用Treap结构的原因:
1.Treap结构结合了平衡二叉树和堆的性质,既保证了操作效率,又具有随机性。
2.Treap结构可以快速进行插入、删除和查找操作,适合处理大量数据的动态变化。
模板题代码:
cpp
#include #include using namespace std;struct Node { int key, priority, left, right; Node(int k=0, int p=0, int l=0, int r=0) : key(k), priority(p), left(l), right(r) {}};
int root=0; // Treap的根节点
// 查找元素int search(int key) { int cur=root; while (cur) { if (key==Node(cur).key) { return cur; } else if (key // 插入元素void insert(int key) { int cur=root, parent=0, direction=0; while (cur) { parent=cur; direction=(key // 删除元素void remove(int key) { int cur=root, parent=0, direction=0; while (cur && key !=Node(cur).key) { parent=cur; direction=(key key; next_parent=Node(next_parent).left; next_direction=0; } Node(cur).key=next; if (next_direction) { Node(cur).right=Node(next_parent).left; } else { Node(cur).left=Node(next_parent).left; } delete Node(next_parent).left; Node(next_parent).left=cur; }} int main() { // 示例:插入、删除和查找元素 insert(10); insert(20); insert(30); insert(40); insert(50); cout << Search 20: << (search(20) ? Found : Not Found) < remove(20); cout << Search 20: << (search(20) ? Found : Not Found) < return 0;} 注意:代码仅为示例,实际使用时可能需要根据具体题目要求进行调整。 Treap 模板题 #include <cstdio>
#include <cstdlib>
#include <ctime>
const int MAX = 110000 + 5;
int n, m, rt, tot, inf = 0x7f3f3f3f, ot;
char str[100];
struct Node {
int lc, rc, key, size, cnt, pri;
#define lc(x) t[x].lc
#define rc(x) t[x].rc
#define pri(x) t[x].pri
#define key(x) t[x].key
#define size(x) t[x].size
#define cnt(x) t[x].cnt
} t[MAX];
inline void write(int x) {
if (x == 0) { putchar('0'); return; }
if (x < 0) putchar('-'), x = -x;
ot = 0;
while (x) str[++ot] = x % 10 + '0', x /= 10;
while (ot) putchar(str[ot--]);
}
inline int read() {
int s = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
return s * f;
}
void show(int x) {
printf("%d %d %d %d %d %d\n", lc(x), rc(x), pri(x), key(x), size(x), cnt(x));
if (lc(x)) show(lc(x));
if (rc(x)) show(rc(x));
}
void pushup(int r) {
size(r) = size(lc(r)) + size(rc(r)) + cnt(r);
}
void zig(int &r) {
int s = lc(r);
lc(r) = rc(s);
rc(s) = r;
size(s) = size(r);
pushup(r);
r = s;
}
void zag(int &r) {
int s = rc(r);
rc(r) = lc(s);
lc(s) = r;
size(s) = size(r);
pushup(r);
r = s;
}
void insert(int &r, int k) {
if (!r) {
r = ++tot; pri(r) = rand(); key(r) = k;
lc(r) = rc(r) = 0;
size(r) = cnt(r) = 1;
return;
} else ++size(r);
if (key(r) == k) ++cnt(r);
else if (k < key(r)) {
insert(lc(r), k);
if (pri(lc(r)) < pri(r)) zig(r);
} else {
insert(rc(r), k);
if (pri(rc(r)) < pri(r)) zag(r);
}
}
void del(int &r, int k) {
if (key(r) == k) {
if (cnt(r) >= 2) --cnt(r), --size(r);
else if (!lc(r) || !rc(r)) r = lc(r) + rc(r);
else if (pri(lc(r)) < pri(rc(r))) {
zig(r), del(r, k);
} else {
zag(r), del(r, k);
}
return;
}
--size(r);
if (k < key(r)) del(lc(r), k);
else del(rc(r), k);
}
int queryPre(int k) {
int r = rt, res = inf;
while (r) {
if (k > key(r)) res = key(r), r = rc(r);
else r = lc(r);
}
return res;
}
int queryNxt(int k) {
int r = rt, res = inf;
while (r) {
if (k < key(r)) res = key(r), r = lc(r);
else r = rc(r);
}
return res;
}
int queryKth(int k) {
int r = rt, res = inf;
while (r) {
if (size(lc(r)) < k && size(lc(r)) + cnt(r) >= k) return key(r);
else if (size(lc(r)) >= k) r = lc(r);
else k -= size(lc(r)) + cnt(r), r = rc(r);
}
return res;
}
int queryRand(int k) {
int r = rt, res = 0;
while (r) {
if (k == key(r)) return res + size(lc(r)) + 1;
else if (k < key(r)) r = lc(r);
else res += size(lc(r)) + cnt(r), r = rc(r);
}
return res;
}
int main() {
srand(time(NULL));
n = read();
for (int i = 1, p, q; i <= n; ++i) {
p = read(), q = read();
// printf("%d %d\n", p, q);
switch(p) {
case 1: insert(rt, q); break;
case 2: del(rt, q); break;
case 3: m = queryRand(q); write(m); puts(""); break;
case 4: m = queryKth(q); write(m); puts(""); break;
case 5: m = queryPre(q); write(m); puts(""); break;
case 6: m = queryNxt(q); write(m); puts("");
}
// show(rt);
}
return 0;
}题目描述
思路
代码
本文共计1111个文字,预计阅读时间需要5分钟。
题目描述:实现一个基于Treap的模板题,要求描述题目思路、使用Treap结构的原因以及给出相关代码。
思路:
1.使用Treap结构存储元素,利用其随机性维护平衡,保证操作效率。
2.在插入、删除和查找元素时,利用旋转操作维护Treap的平衡。
3.对于查找、插入和删除操作,分别处理元素相同的情况。
使用Treap结构的原因:
1.Treap结构结合了平衡二叉树和堆的性质,既保证了操作效率,又具有随机性。
2.Treap结构可以快速进行插入、删除和查找操作,适合处理大量数据的动态变化。
模板题代码:
cpp
#include #include using namespace std;struct Node { int key, priority, left, right; Node(int k=0, int p=0, int l=0, int r=0) : key(k), priority(p), left(l), right(r) {}};
int root=0; // Treap的根节点
// 查找元素int search(int key) { int cur=root; while (cur) { if (key==Node(cur).key) { return cur; } else if (key // 插入元素void insert(int key) { int cur=root, parent=0, direction=0; while (cur) { parent=cur; direction=(key // 删除元素void remove(int key) { int cur=root, parent=0, direction=0; while (cur && key !=Node(cur).key) { parent=cur; direction=(key key; next_parent=Node(next_parent).left; next_direction=0; } Node(cur).key=next; if (next_direction) { Node(cur).right=Node(next_parent).left; } else { Node(cur).left=Node(next_parent).left; } delete Node(next_parent).left; Node(next_parent).left=cur; }} int main() { // 示例:插入、删除和查找元素 insert(10); insert(20); insert(30); insert(40); insert(50); cout << Search 20: << (search(20) ? Found : Not Found) < remove(20); cout << Search 20: << (search(20) ? Found : Not Found) < return 0;} 注意:代码仅为示例,实际使用时可能需要根据具体题目要求进行调整。 Treap 模板题 #include <cstdio>
#include <cstdlib>
#include <ctime>
const int MAX = 110000 + 5;
int n, m, rt, tot, inf = 0x7f3f3f3f, ot;
char str[100];
struct Node {
int lc, rc, key, size, cnt, pri;
#define lc(x) t[x].lc
#define rc(x) t[x].rc
#define pri(x) t[x].pri
#define key(x) t[x].key
#define size(x) t[x].size
#define cnt(x) t[x].cnt
} t[MAX];
inline void write(int x) {
if (x == 0) { putchar('0'); return; }
if (x < 0) putchar('-'), x = -x;
ot = 0;
while (x) str[++ot] = x % 10 + '0', x /= 10;
while (ot) putchar(str[ot--]);
}
inline int read() {
int s = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
return s * f;
}
void show(int x) {
printf("%d %d %d %d %d %d\n", lc(x), rc(x), pri(x), key(x), size(x), cnt(x));
if (lc(x)) show(lc(x));
if (rc(x)) show(rc(x));
}
void pushup(int r) {
size(r) = size(lc(r)) + size(rc(r)) + cnt(r);
}
void zig(int &r) {
int s = lc(r);
lc(r) = rc(s);
rc(s) = r;
size(s) = size(r);
pushup(r);
r = s;
}
void zag(int &r) {
int s = rc(r);
rc(r) = lc(s);
lc(s) = r;
size(s) = size(r);
pushup(r);
r = s;
}
void insert(int &r, int k) {
if (!r) {
r = ++tot; pri(r) = rand(); key(r) = k;
lc(r) = rc(r) = 0;
size(r) = cnt(r) = 1;
return;
} else ++size(r);
if (key(r) == k) ++cnt(r);
else if (k < key(r)) {
insert(lc(r), k);
if (pri(lc(r)) < pri(r)) zig(r);
} else {
insert(rc(r), k);
if (pri(rc(r)) < pri(r)) zag(r);
}
}
void del(int &r, int k) {
if (key(r) == k) {
if (cnt(r) >= 2) --cnt(r), --size(r);
else if (!lc(r) || !rc(r)) r = lc(r) + rc(r);
else if (pri(lc(r)) < pri(rc(r))) {
zig(r), del(r, k);
} else {
zag(r), del(r, k);
}
return;
}
--size(r);
if (k < key(r)) del(lc(r), k);
else del(rc(r), k);
}
int queryPre(int k) {
int r = rt, res = inf;
while (r) {
if (k > key(r)) res = key(r), r = rc(r);
else r = lc(r);
}
return res;
}
int queryNxt(int k) {
int r = rt, res = inf;
while (r) {
if (k < key(r)) res = key(r), r = lc(r);
else r = rc(r);
}
return res;
}
int queryKth(int k) {
int r = rt, res = inf;
while (r) {
if (size(lc(r)) < k && size(lc(r)) + cnt(r) >= k) return key(r);
else if (size(lc(r)) >= k) r = lc(r);
else k -= size(lc(r)) + cnt(r), r = rc(r);
}
return res;
}
int queryRand(int k) {
int r = rt, res = 0;
while (r) {
if (k == key(r)) return res + size(lc(r)) + 1;
else if (k < key(r)) r = lc(r);
else res += size(lc(r)) + cnt(r), r = rc(r);
}
return res;
}
int main() {
srand(time(NULL));
n = read();
for (int i = 1, p, q; i <= n; ++i) {
p = read(), q = read();
// printf("%d %d\n", p, q);
switch(p) {
case 1: insert(rt, q); break;
case 2: del(rt, q); break;
case 3: m = queryRand(q); write(m); puts(""); break;
case 4: m = queryKth(q); write(m); puts(""); break;
case 5: m = queryPre(q); write(m); puts(""); break;
case 6: m = queryNxt(q); write(m); puts("");
}
// show(rt);
}
return 0;
}题目描述
思路
代码

