转自《数据结构(C++语言版)》邓俊辉著 (好书
http://www.cnblogs.com/QG-whz/p/5167238.html
一、定义
AVL 树是最先发明的自平衡二叉查找树算法(由 G. M. Adelson-Velsky 和 E. M. Landis 于1962年发明,并以他们名字的首字母命名)
具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过 1,并且左右两个子树都是一棵 AVL 树
我们知道,对于一般的二叉搜索树(Binary Search Tree),其期望高度(即为一棵平衡树时)为 logn,其各操作的时间复杂度 O(logn) 同时也由此而决定
但是,在某些极端的情况下(如在插入的序列是有序的时),二叉搜索树将退化成近似链或链,此时,其操作的时间复杂度将退化成线性的,即 O(n)
我们可以通过随机化建立二叉搜索树来尽量的避免这种情况,但是在进行了多次的操作之后,由于在删除时,我们总是选择将待删除节点的后继代替它本身,这样就会造成总是右边的节点数目减少,以至于树向左偏沉。这同时也会造成树的平衡性受到破坏,提高它的操作的时间复杂度
在平衡二叉搜索树中,我们可以看到,其高度一般都良好地维持在 O(logn),大大降低了操作的时间复杂度
二、等价变换
1、等价二叉搜索树
如图 1 所示,若两棵二叉搜索树的中序遍历序列相同,则称它们彼此等价;反之亦然
图 1 由同一组共 11 个节点组成,相互等价的两棵二叉搜索树(二者在拓扑上的差异,以阴影圈出)
由该图也不难看出,虽然等价二叉树中各节点的垂直高度可能有所不同,但水平次序完全一致
这一特点可概括为“上下可变,左右不乱”,它也是以下等价变换的基本特性
2、局部性
平衡二叉树的适度平衡性,都是通过对树中的每一局部增加某种限制条件来保证的
比如,在 AVL 树中,兄弟节点的高度相差不过 1
事实上,这些限制条件设定得非常精妙,除了适度平衡性,还具有如下局部性
- 经过单次动态修改操作后,至多只有 O(1) 处局部不再满足限制条件
- 总可在 O(logn) 时间内,使这 O(1) 处局部(以至全树)重新满足限制条件
这就意味着:刚刚失去平衡的二叉搜索树,必然可以迅速转换为一棵等价的平衡二叉搜索树
等价二叉搜索树之间的上述准换过程,也称作等价变换
这里的局部性至关重要
比如,尽管任何二叉搜索树都可等价变换至理想平衡的完全二叉树,然而鉴于二者的拓扑结构可能相去甚远,在最坏情况下我们为此将不得不花费O(n)时间
反观图 1 中相互等价的两棵二叉搜索树,右侧属于AVL树,而左侧不是。鉴于二者的差异仅限于某一局部(阴影区域),故可轻易地将后者转换为前者
那么,此类局部性的失衡,具体地可以如何修复?如何保证修复的速度?
三、旋转调整
最基本的修复手段,就是通过围绕特定节点的旋转,实现等价前提下的局部拓扑调整
1、zig 和 zag
图 2 zig(v):顺时针旋转
如图 2(a) 所示, 设 c 和 Z 是 v 的左孩子、右子树, X 和 Y 是 c 的左、右子树
所谓以v为轴的 zig 旋转, 即如图(b)所示, 重新调整这两个节点与三棵子树的联接关系:
将 X 和 v 作为 c 的左子树、右孩子, Y和Z分别作为v的左、右子树
可见, 尽管局部结构以及子树根均有变化,但中序遍历序列仍是 { ...,,X, c, Y, v, Z, ... },故 zig 旋转属于等价变换
图 3 zag(v):逆时针旋转
对称地如图 3(a)所示, 设 X 和 c 是 v 的左子树、 右孩子, Y 和 Z 分别是 c 的左、右子树
所谓以 v 为轴的 zag 旋转, 即如图(b)所示, 重新调整这两个节点与三棵子树的联接关系:
将 v 和 Z 作为 c 的左孩子、 右子树, X 和 Y 分别作为 v 的左、右子树
同样地,旋转之后中序遍历序列依然不变,故 zag 旋转亦属等价变换
2、效率与效果
zig 和 zag 旋转均属局部操作,仅涉及常数个节点及其之间的联接关系, 故均可在常数时间内完成
正因如此, 在后面实现各种二叉搜索树平衡化算法时, 它们都是支撑性的基本操作
就与树相关的指标而言,经一次 zig 或 zag 旋转之后,节点 v 的深度加一,节点 c 的深度减一
这一局部子树(乃至全树) 的高度可能发生变化,但上、下幅度均不超过一层
四、AVL 树
通过合理设定适度平衡的标准, 并借助以上等价变换, AVL 树( AVL tree)可以实现近乎理想的平衡
在渐进意义下, AVL 树可始终将其高度控制在 O(logn) 以内,从而保证每次查找、插入或删除操作, 均可在 O(logn) 的时间内完成
1、平衡因子
任一节点 v 的平衡因子( balance factor) 定义为“其左、右子树的高度差” , 即 balFac(v) = height(lc(v)) - height(rc(v))
注意,我们将空树高度取 -1,单节点子树(叶节点)高度取 0,与以上定义没有冲突
所谓 AVL 树,即平衡因子受限的二叉搜索树 -- 其中各节点平衡因子的绝对值均不超过 1
2、平衡性
在完全二叉树中各节点的平衡因子非 0 即 1,故完全二叉树必是 AVL 树;不难举例说明,反之不然
可以证明,高度为 h 的 AVL 树至少包含 fib(h + 3) - 1 个节点。为此需做数学归纳
作为归纳基,当 h = 0 时, T 中至少包含 fib(3) - 1 = 2 - 1 = 1 个节点,命题成立
当 h = 1 时, T 中至少包含 fib(4) - 1 = 3 - 1 = 2 个节点,命题也成立
假设对于高度低于 h 的任何 AVL 树,以上命题均成立
现考查高度为 h 的所有 AVL 树,并取 S 为其中节点最少的任何一棵(请注意,这样的 S 可能不止一棵)
图 4 在高度固定为 h 的前提下,节点最少的 AVL 树
如图 4,设 S 的根节点为 r, r 的左、右子树分别为 SL 和 SR,将其高度记作 hL 和 hR,其规模记作 |SL| 和 |SR|
于是就有:|S| = 1 + |SL| + |SR|
作为 S 的子树, SL 和 SR 也都是 AVL 树,而且高度不超过 h - 1
进一步地,在考虑到 AVL 树有关平衡因子的要求的同时,既然 S 中的节点数最少,故 SL 和 SR 的高度只能是一个为 h - 1,另一个为 h - 2
不失一般性,设 hL = h - 1, hR = h - 2。而且,在所有高度为 hL( hR)的 AVL 树中,SL( SR)中包含的节点也应该最少
因此,根据归纳假设,可得如下关系:
|S| = 1 + (fib(h + 2) - 1) + (fib(h + 1) - 1)
根据 Fibonacci 数列的定义,可得:
|S| = fib(h + 2) + fib(h + 1) - 1 = fib(h + 3) - 1
总而言之,高度为 h 的 AVL 树的确至少包含 fib(h + 3) - 1 个节点。于是反过来, 包含 n 个节点的 AVL 树的高度应为 O(logn)
因此就渐进意义而言, AVL 树的确是平衡的
3、失衡与重平衡
AVL 树与常规的二叉搜索树一样,也应支持插入、删除等动态修改操作
但经过这类操作之后,节点的高度可能发生变化,以致于不再满足 AVL 树的条件
图 5 经节点删除和插入操作后,AVL 树可能失衡(加减号示意平衡因子,双圈表示失衡节点)
以插入操作为例, 考查图 5(b) 中的AVL树,其中的关键码为字符类型
现插入关键码 ‘M’,于是如图 (c) 所示,节点 'N'、 'R' 和 'G' 都将失衡
类似地,摘除关键码'Y'之后,也会如图 (a) 所示导致节点 'R' 的失衡
如此因节点 x 的插入或删除而暂时失衡的节点,构成失衡节点集,记作 UT(x)
请注意,若 x 为被摘除的节点,则 UT(x) 仅含单个节点;但若 x 为被引入的节点,则 UT(x) 可能包含多个节点
以下, 我们从对 UT(x) 的分析入手,分别介绍使失衡搜索树重新恢复平衡的调整算法
五、节点插入
1、失衡节点集
不难看出,新引入节点 x 后, UT(x) 中的节点都是 x 的祖先,且高度不低于 x 的祖父
以下,将其中的最深者记作 g(x)。 在 x 与 g(x) 之间的通路上, 设 p 为 g(x) 的孩子, v 为 p 的孩子
注意,既然 g(x) 不低于 x 的祖父,则 p 必是 x 的真祖先
2、单旋
图 6 节点插入后,通过单旋操作使 AVL 树重新平衡
如图 6(a) 所示,设 v 是 p 的右孩子,且 p 是 g 的右孩子
这种情况下,必是由于在子树 v 中刚插入某节点 x, 而使 g(x) 不再平衡
图中以虚线联接的每一对灰色方块中, 其一对应于节点 x,另一为空
此时, 可做逆时针旋转 zag(g(x)),得到如图 (b) 所示的另一棵等价二叉搜索树
可见, 经如此调整之后, g(x) 必将恢复平衡
不难验证, 通过 zig(g(x)) 可以处理对称的失衡
3、双旋
如图 7(a) 所示,设节点 v 是 p 的左孩子,而 p 是 g(x) 的右孩子
图 7 节点插入后通过连续的两次旋转操作使 AVL 树重新平衡
这种情况,也必是由于在子树v中插入了新节点 x, 而致使 g(x) 不再平衡
同样地,在图中以虚线联接的每一对灰色方块中,其一对应于新节点 x,另一为空
此时,可先做顺时针旋转 zig(p),得到如图 (b) 所示的一棵等价二叉搜索树
再做逆时针旋转 zag(g(x)),得到如图 (c) 所示的另一棵等价二叉搜索树
此类分别以父子节点为轴、 方向互逆的连续两次旋转,合称“ 双旋调整”
可见,经如此调整之后, g(x) 亦必将重新平衡
不难验证,通过 zag(p) 和 zig(g(x)) 可以处理对称的情况
HDU 4006 The kth great number
注意:该题数据会重复哦
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
#include <cctype>
#include <bitset>
#include <ctime>
using namespace std;
#define REP(i, n) for (int i = 0; i < (n); ++i)
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;
const ull mod = 1e9 + 7;
const int INF = 0x7fffffff;
template <typename T> struct AVL_Node {
AVL_Node(T value, AVL_Node<T>* Left, AVL_Node<T>* Right) : key(value), lson(Left), rson(Right) {
repeat = height = size = 1;
}
T key;
int height, size, repeat;
AVL_Node<T>* lson;
AVL_Node<T>* rson;
};
template <typename T> class AVL {
public:
AVL() : root(nullptr) {};
~AVL();
void insert(T key);
T find_by_order(int k);
int size();
int height();
void destory();
private:
AVL_Node<T>* root;
AVL_Node<T>* insert(AVL_Node<T>* &pnode, T key);
T find_by_order(AVL_Node<T>* pnode, int k);
int height(AVL_Node<T>* pnode);
int size(AVL_Node<T>* pnode);
int max(int a, int b);
AVL_Node<T>* zag(AVL_Node<T>* pnode);
AVL_Node<T>* zig(AVL_Node<T>* pnode);
AVL_Node<T>* zag_zig(AVL_Node<T>* pnode);
AVL_Node<T>* zig_zag(AVL_Node<T>* pnode);
void destory(AVL_Node<T>* &pnode);
};
int n, k;
char cmd[1];
int cmd_num;
int main()
{
#ifdef __AiR_H
freopen("in.txt", "r", stdin);
#endif // __AiR_H
while (scanf("%d %d", &n, &k) != EOF) {
AVL<int> avl;
while (n--) {
scanf("%s", cmd);
if (cmd[0] == 'I') {
scanf("%d", &cmd_num);
avl.insert(cmd_num);
} else {
printf("%d\n", avl.find_by_order(avl.size() + 1 - k));
}
}
}
return 0;
}
template <typename T> AVL<T>::~AVL(void)
{
destory();
}
template <typename T> T AVL<T>::find_by_order(int k)
{
return find_by_order(root, k);
}
template <typename T> int AVL<T>::max(int a, int b)
{
return a > b ? a : b;
}
template <typename T> T AVL<T>::find_by_order(AVL_Node<T>* pnode, int k)
{
int lsize = size(pnode->lson);
if (k <= lsize) {
return find_by_order(pnode->lson, k);
} else if (k > lsize+pnode->repeat) {
return find_by_order(pnode->rson, k-lsize-pnode->repeat);
}
return pnode->key;
}
template <typename T> void AVL<T>::insert(T key)
{
insert(root, key);
}
template <typename T> AVL_Node<T>* AVL<T>::insert(AVL_Node<T>* &pnode, T key)
{
if (pnode == nullptr) {
pnode = new AVL_Node<T>(key, nullptr, nullptr);
} else if (key > pnode->key) {
pnode->rson = insert(pnode->rson, key);
if (height(pnode->rson) - height(pnode->lson) == 2) {
if (key > pnode->rson->key) {
pnode = zag(pnode);
} else {
pnode = zig_zag(pnode);
}
}
} else if (key < pnode->key) {
pnode->lson = insert(pnode->lson, key);
if (height(pnode->lson) - height(pnode->rson) == 2) {
if (key < pnode->lson->key) {
pnode = zig(pnode);
} else {
pnode = zag_zig(pnode);
}
}
} else {
++pnode->repeat;
}
pnode->height = max(height(pnode->lson), height(pnode->rson)) + 1;
pnode->size = size(pnode->lson) + size(pnode->rson) + pnode->repeat;
return pnode;
}
template <typename T> AVL_Node<T>* AVL<T>::zag(AVL_Node<T>* pnode)
{
AVL_Node<T>* prson = pnode->rson;
pnode->rson = prson->lson;
prson->lson = pnode;
pnode->height = max(height(pnode->lson), height(pnode->rson)) + 1;
pnode->size = size(pnode->lson) + size(pnode->rson) + pnode->repeat;
prson->height = max(height(prson->lson), height(prson->rson)) + 1;
prson->size = size(prson->lson) + size(prson->rson) + prson->repeat;
return prson;
}
template <typename T> AVL_Node<T>* AVL<T>::zig(AVL_Node<T>* pnode)
{
AVL_Node<T>* plson = pnode->lson;
pnode->lson = plson->rson;
plson->rson = pnode;
pnode->height = max(height(pnode->lson), height(pnode->rson)) + 1;
pnode->size = size(pnode->lson) + size(pnode->rson) + pnode->repeat;
plson->height = max(height(plson->lson), height(plson->rson)) + 1;
plson->size = size(plson->lson) + size(plson->rson) + plson->repeat;
return plson;
}
template <typename T> AVL_Node<T>* AVL<T>::zag_zig(AVL_Node<T>* pnode)
{
pnode->lson = zag(pnode->lson);
return zig(pnode);
}
template <typename T> AVL_Node<T>* AVL<T>::zig_zag(AVL_Node<T>* pnode)
{
pnode->rson = zig(pnode->rson);
return zag(pnode);
}
template <typename T> int AVL<T>::size()
{
return size(root);
}
template <typename T> int AVL<T>::size(AVL_Node<T>* pnode)
{
if (pnode == nullptr) {
return 0;
}
return pnode->size;
}
template <typename T> int AVL<T>::height(void)
{
return height(root);
}
template <typename T> int AVL<T>::height(AVL_Node<T>* pnode)
{
if (pnode != nullptr) {
return pnode->height;
}
return 0;
}
template <typename T> void AVL<T>::destory(void)
{
destory(root);
}
template <typename T> void AVL<T>::destory(AVL_Node<T>* &pnode)
{
if (pnode != nullptr) {
destory(pnode->lson);
destory(pnode->rson);
delete pnode;
pnode = nullptr;
}
}
POJ 2418 Hardwood Species
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
#include <cctype>
#include <bitset>
#include <ctime>
#include <iomanip>
using namespace std;
#define REP(i, n) for (int i = 0; i < (n); ++i)
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;
const ull mod = 1e9 + 7;
const int INF = 0x7fffffff;
template <typename T> struct AVL_Node {
AVL_Node(T value, AVL_Node<T>* Left, AVL_Node<T>* Right) : lson(Left), rson(Right) {
key = new char[40];
strcpy(key, value);
repeat = height = size = 1;
}
T key;
int height, size, repeat;
AVL_Node<T>* lson;
AVL_Node<T>* rson;
};
template <typename T> class AVL {
public:
AVL() : root(NULL) {};
~AVL();
void insert(T key);
void In_Traverse(void);
int size();
int height();
void destory();
private:
AVL_Node<T>* root;
AVL_Node<T>* insert(AVL_Node<T>* &pnode, T key);
void In_Traverse(AVL_Node<T>* pnode);
int height(AVL_Node<T>* pnode);
int size(AVL_Node<T>* pnode);
int max(int a, int b);
AVL_Node<T>* zag(AVL_Node<T>* pnode);
AVL_Node<T>* zig(AVL_Node<T>* pnode);
AVL_Node<T>* zag_zig(AVL_Node<T>* pnode);
AVL_Node<T>* zig_zag(AVL_Node<T>* pnode);
void destory(AVL_Node<T>* &pnode);
};
AVL<char*> avl;
char name[40];
int main()
{
#ifdef __AiR_H
freopen("in.txt", "r", stdin);
#endif // __AiR_H
while (gets(name)) {
avl.insert(name);
}
avl.In_Traverse();
return 0;
}
template <typename T> AVL<T>::~AVL(void)
{
destory();
}
template <typename T> void AVL<T>::In_Traverse()
{
In_Traverse(root);
}
template <typename T> void AVL<T>::In_Traverse(AVL_Node<T>* pnode)
{
if (pnode == NULL) {
return;
}
In_Traverse(pnode->lson);
printf("%s %.4f\n", pnode->key, 100.0 * (double)pnode->repeat / (double)avl.size());
In_Traverse(pnode->rson);
}
template <typename T> int AVL<T>::max(int a, int b)
{
return a > b ? a : b;
}
template <typename T> void AVL<T>::insert(T key)
{
insert(root, key);
}
template <typename T> AVL_Node<T>* AVL<T>::insert(AVL_Node<T>* &pnode, T key)
{
if (pnode == NULL) {
pnode = new AVL_Node<T>(key, NULL, NULL);
} else if (strcmp(key, pnode->key) > 0) {
pnode->rson = insert(pnode->rson, key);
if (height(pnode->rson) - height(pnode->lson) == 2) {
if (strcmp(key, pnode->rson->key) > 0) {
pnode = zag(pnode);
} else {
pnode = zig_zag(pnode);
}
}
} else if (strcmp(key, pnode->key) < 0) {
pnode->lson = insert(pnode->lson, key);
if (height(pnode->lson) - height(pnode->rson) == 2) {
if (strcmp(key, pnode->lson->key) < 0) {
pnode = zig(pnode);
} else {
pnode = zag_zig(pnode);
}
}
} else {
++pnode->repeat;
}
pnode->height = max(height(pnode->lson), height(pnode->rson)) + 1;
pnode->size = size(pnode->lson) + size(pnode->rson) + pnode->repeat;
return pnode;
}
template <typename T> AVL_Node<T>* AVL<T>::zag(AVL_Node<T>* pnode)
{
AVL_Node<T>* prson = pnode->rson;
pnode->rson = prson->lson;
prson->lson = pnode;
pnode->height = max(height(pnode->lson), height(pnode->rson)) + 1;
pnode->size = size(pnode->lson) + size(pnode->rson) + pnode->repeat;
prson->height = max(height(prson->lson), height(prson->rson)) + 1;
prson->size = size(prson->lson) + size(prson->rson) + prson->repeat;
return prson;
}
template <typename T> AVL_Node<T>* AVL<T>::zig(AVL_Node<T>* pnode)
{
AVL_Node<T>* plson = pnode->lson;
pnode->lson = plson->rson;
plson->rson = pnode;
pnode->height = max(height(pnode->lson), height(pnode->rson)) + 1;
pnode->size = size(pnode->lson) + size(pnode->rson) + pnode->repeat;
plson->height = max(height(plson->lson), height(plson->rson)) + 1;
plson->size = size(plson->lson) + size(plson->rson) + plson->repeat;
return plson;
}
template <typename T> AVL_Node<T>* AVL<T>::zag_zig(AVL_Node<T>* pnode)
{
pnode->lson = zag(pnode->lson);
return zig(pnode);
}
template <typename T> AVL_Node<T>* AVL<T>::zig_zag(AVL_Node<T>* pnode)
{
pnode->rson = zig(pnode->rson);
return zag(pnode);
}
template <typename T> int AVL<T>::size()
{
return size(root);
}
template <typename T> int AVL<T>::size(AVL_Node<T>* pnode)
{
if (pnode == NULL) {
return 0;
}
return pnode->size;
}
template <typename T> int AVL<T>::height(void)
{
return height(root);
}
template <typename T> int AVL<T>::height(AVL_Node<T>* pnode)
{
if (pnode != NULL) {
return pnode->height;
}
return 0;
}
template <typename T> void AVL<T>::destory(void)
{
destory(root);
}
template <typename T> void AVL<T>::destory(AVL_Node<T>* &pnode)
{
if (pnode != NULL) {
destory(pnode->lson);
destory(pnode->rson);
delete pnode;
pnode = NULL;
}
}
六、节点删除
1、失衡节点集
与插入操作十分不同,在摘除节点 x 后,以及随后的调整过程中,失衡节点集 UT(x) 始终至多只含一个节点
而且若该节点 g(x) 存在,其高度必与失衡前相同
另外还有一点重要的差异是, g(x) 有可能就是 x 的父亲
2、单旋
如图 8(a)所示,由于在 T3 中删除了节点而致使 g(x) 不再平衡,但 p 的平衡因子非负时,通过以 g(x) 为轴顺时针旋转一次即可恢复局部的平衡
平衡后的局部子树如图 (b) 所示
图 8 节点删除后经一次旋转恢复局部平衡
同样地这里约定,图中以虚线联接的灰色方块所对应的节点, 不能同时为空
T2 底部的灰色方块所对应的节点, 可能为空,也可能非空
3、双旋
如图 9(a) 所示, g(x) 失衡时若 p 的平衡因子为 -1, 则经过以 p 为轴的一次逆时针旋转之后(图(b)),即可转化为图 8(a) 的情况
图 9 节点删除后通过两次旋转恢复局部平衡
接着再套用上一情况的处理方法,以 g(x) 为轴顺时针旋转, 即可恢复局部平衡( 图(c))
4、失衡传播
与插入操作不同,在删除节点之后,尽管也可通过单旋或双旋调整使局部子树恢复平衡,但就全局而言, 依然可能再次失衡
若能仔细观察图 8(b) 和图 9(c),则不难发现: g(x )恢复平衡之后, 局部子树的高度却可能降低
这与引入节点之后的重平衡后完全不同,后者不仅能恢复子树的平衡性,也同时能恢复子树的高度
设 g(x) 复衡之后, 局部子树的高度的确降低
此时,若 g(x) 原本属于某一更高祖先的更短分支,则因为该分支现在又进一步缩短,从而会致使该祖先失衡
在摘除节点之后的调整过程中,这种由于低层失衡节点的重平衡而致使其更高层祖先失衡的现象, 称作“失衡传播”
请注意,失衡传播的方向必然自底而上,而不致于影响到后代节点
在此过程中的任一时刻,至多只有一个失衡的节点
高层的某一节点由平衡转为失衡,只可能发生在下层失衡节点恢复平衡之后
UESTC 1339 郭大侠与线上游戏
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
#include <cctype>
#include <bitset>
#include <ctime>
using namespace std;
#define REP(i, n) for (int i = 0; i < (n); ++i)
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;
const ull mod = 1e9 + 7;
const int INF = 0x7fffffff;
template <typename T> struct AVL_Node {
AVL_Node(T value, AVL_Node<T>* Left, AVL_Node<T>* Right) : key(value), lson(Left), rson(Right) {
repeat = height = size = 1;
}
T key;
int height, size, repeat;
AVL_Node<T>* lson;
AVL_Node<T>* rson;
};
template <typename T> class AVL {
public:
AVL() : root(nullptr) {};
~AVL();
void insert(T key);
void remove(T key);
T find_by_order(int k);
bool find(T key);
T max();
T min();
int size();
int height();
void destory();
private:
AVL_Node<T>* root;
AVL_Node<T>* insert(AVL_Node<T>* &pnode, T key);
AVL_Node<T>* remove(AVL_Node<T>* &pnode, T key);
T find_by_order(AVL_Node<T>* pnode, int k);
bool find(AVL_Node<T>* pnode, T key);
AVL_Node<T>* max(AVL_Node<T>* pnode);
AVL_Node<T>* min(AVL_Node<T>* pnode);
int height(AVL_Node<T>* pnode);
int size(AVL_Node<T>* pnode);
int max(int a, int b);
AVL_Node<T>* zag(AVL_Node<T>* pnode);
AVL_Node<T>* zig(AVL_Node<T>* pnode);
AVL_Node<T>* zag_zig(AVL_Node<T>* pnode);
AVL_Node<T>* zig_zag(AVL_Node<T>* pnode);
void destory(AVL_Node<T>* &pnode);
};
int n, cmd, x;
queue<int> Q;
int main()
{
#ifdef __AiR_H
freopen("in.txt", "r", stdin);
#endif // __AiR_H
AVL<int> avl;
int n;
scanf("%d", &n);
while (n--) {
scanf("%d", &cmd);
if (cmd == 1) {
scanf("%d", &x);
Q.push(x);
avl.insert(x);
} else if (cmd == 2) {
avl.remove(Q.front());
Q.pop();
} else {
printf("%d\n", avl.find_by_order(Q.size() / 2 + 1));
}
}
return 0;
}
template <typename T> AVL<T>::~AVL(void)
{
destory();
}
template <typename T> bool AVL<T>::find(T key)
{
return find(root, key);
}
template <typename T> bool AVL<T>::find(AVL_Node<T>* pnode, T key)
{
while (pnode != nullptr) {
if (pnode->key == key) {
return true;
} else if (key < pnode->key) {
pnode = pnode->lson;
} else {
pnode = pnode->rson;
}
}
return false;
}
template <typename T> void AVL<T>::remove(T key)
{
remove(root, key);
}
template <typename T> AVL_Node<T>* AVL<T>::remove(AVL_Node<T>* &pnode, T key)
{
if (pnode == nullptr) {
return nullptr;
}
if (key == pnode->key) {
if (pnode->repeat > 1) {
--pnode->repeat;
} else if (pnode->lson != nullptr && pnode->rson != nullptr) {
if (height(pnode->lson) > height(pnode->rson)) {
AVL_Node<T>* pmax = max(pnode->lson);
pnode->key = pmax->key;
pnode->lson = remove(pnode->lson, pmax->key);
} else {
AVL_Node<T>* pmin = min(pnode->rson);
pnode->key = pmin->key;
pnode->rson = remove(pnode->rson, pmin->key);
}
} else {
AVL_Node<T>* pt = pnode;
if (pnode->lson != nullptr) {
pnode = pnode->lson;
} else {
pnode = pnode->rson;
}
delete pt;
pt = nullptr;
}
} else if (key > pnode->key) {
pnode->rson = remove(pnode->rson, key);
if (height(pnode->lson) - height(pnode->rson) == 2) {
if (height(pnode->lson->lson) > height(pnode->lson->rson)) {
pnode = zig(pnode);
} else {
pnode = zag_zig(pnode);
}
}
} else {
pnode->lson = remove(pnode->lson, key);
if (height(pnode->rson) - height(pnode->lson) == 2) {
if (height(pnode->rson->rson) > height(pnode->rson->lson)) {
pnode = zag(pnode);
} else {
pnode = zig_zag(pnode);
}
}
}
if (pnode == nullptr) {
return nullptr;
}
pnode->height = max(height(pnode->lson), height(pnode->rson)) + 1;
pnode->size = size(pnode->lson) + size(pnode->rson) + pnode->repeat;
return pnode;
}
template <typename T> T AVL<T>::max()
{
AVL_Node<T>* pret = max(root);
if (pret != nullptr) {
return pret->key;
}
}
template <typename T> AVL_Node<T>* AVL<T>::max(AVL_Node<T>* pnode)
{
if (pnode == nullptr) {
return nullptr;
}
while (pnode->rson != nullptr) {
pnode = pnode->rson;
}
return pnode;
}
template <typename T> T AVL<T>::min()
{
AVL_Node<T>* pret = min(root);
if (pret != nullptr) {
return pret->key;
}
}
template <typename T> AVL_Node<T>* AVL<T>::min(AVL_Node<T>* pnode)
{
if (pnode == nullptr) {
return nullptr;
}
while (pnode->lson != nullptr) {
pnode = pnode->lson;
}
return pnode;
}
template <typename T> T AVL<T>::find_by_order(int k)
{
return find_by_order(root, k);
}
template <typename T> int AVL<T>::max(int a, int b)
{
return a > b ? a : b;
}
template <typename T> T AVL<T>::find_by_order(AVL_Node<T>* pnode, int k)
{
int lsize = size(pnode->lson);
if (k <= lsize) {
return find_by_order(pnode->lson, k);
} else if (k > lsize+pnode->repeat) {
return find_by_order(pnode->rson, k-lsize-pnode->repeat);
}
return pnode->key;
}
template <typename T> void AVL<T>::insert(T key)
{
insert(root, key);
}
template <typename T> AVL_Node<T>* AVL<T>::insert(AVL_Node<T>* &pnode, T key)
{
if (pnode == nullptr) {
pnode = new AVL_Node<T>(key, nullptr, nullptr);
} else if (key > pnode->key) {
pnode->rson = insert(pnode->rson, key);
if (height(pnode->rson) - height(pnode->lson) == 2) {
if (key > pnode->rson->key) {
pnode = zag(pnode);
} else {
pnode = zig_zag(pnode);
}
}
} else if (key < pnode->key) {
pnode->lson = insert(pnode->lson, key);
if (height(pnode->lson) - height(pnode->rson) == 2) {
if (key < pnode->lson->key) {
pnode = zig(pnode);
} else {
pnode = zag_zig(pnode);
}
}
} else {
++pnode->repeat;
}
pnode->height = max(height(pnode->lson), height(pnode->rson)) + 1;
pnode->size = size(pnode->lson) + size(pnode->rson) + pnode->repeat;
return pnode;
}
template <typename T> AVL_Node<T>* AVL<T>::zag(AVL_Node<T>* pnode)
{
AVL_Node<T>* prson = pnode->rson;
pnode->rson = prson->lson;
prson->lson = pnode;
pnode->height = max(height(pnode->lson), height(pnode->rson)) + 1;
pnode->size = size(pnode->lson) + size(pnode->rson) + pnode->repeat;
prson->height = max(height(prson->lson), height(prson->rson)) + 1;
prson->size = size(prson->lson) + size(prson->rson) + prson->repeat;
return prson;
}
template <typename T> AVL_Node<T>* AVL<T>::zig(AVL_Node<T>* pnode)
{
AVL_Node<T>* plson = pnode->lson;
pnode->lson = plson->rson;
plson->rson = pnode;
pnode->height = max(height(pnode->lson), height(pnode->rson)) + 1;
pnode->size = size(pnode->lson) + size(pnode->rson) + pnode->repeat;
plson->height = max(height(plson->lson), height(plson->rson)) + 1;
plson->size = size(plson->lson) + size(plson->rson) + plson->repeat;
return plson;
}
template <typename T> AVL_Node<T>* AVL<T>::zag_zig(AVL_Node<T>* pnode)
{
pnode->lson = zag(pnode->lson);
return zig(pnode);
}
template <typename T> AVL_Node<T>* AVL<T>::zig_zag(AVL_Node<T>* pnode)
{
pnode->rson = zig(pnode->rson);
return zag(pnode);
}
template <typename T> int AVL<T>::size()
{
return size(root);
}
template <typename T> int AVL<T>::size(AVL_Node<T>* pnode)
{
if (pnode == nullptr) {
return 0;
}
return pnode->size;
}
template <typename T> int AVL<T>::height(void)
{
return height(root);
}
template <typename T> int AVL<T>::height(AVL_Node<T>* pnode)
{
if (pnode != nullptr) {
return pnode->height;
}
return 0;
}
template <typename T> void AVL<T>::destory(void)
{
destory(root);
}
template <typename T> void AVL<T>::destory(AVL_Node<T>* &pnode)
{
if (pnode != nullptr) {
destory(pnode->lson);
destory(pnode->rson);
delete pnode;
pnode = nullptr;
}
}
OpenJudge 打牌
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
#include <cctype>
#include <bitset>
#include <ctime>
using namespace std;
#define REP(i, n) for (int i = 0; i < (n); ++i)
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;
const ull mod = 1e9 + 7;
const int INF = 0x7fffffff;
template <typename T> struct AVL_Node {
AVL_Node(T value, AVL_Node<T>* Left, AVL_Node<T>* Right) : key(value), lson(Left), rson(Right) {
repeat = height = size = 1;
}
T key;
int height, size, repeat;
AVL_Node<T>* lson;
AVL_Node<T>* rson;
};
template <typename T> class AVL {
public:
AVL() : root(nullptr) {};
~AVL();
void insert(T key);
void remove(T key);
T find_by_order(int k);
bool find(T key);
T max();
T min();
int size();
int height();
void destory();
private:
AVL_Node<T>* root;
AVL_Node<T>* insert(AVL_Node<T>* &pnode, T key);
AVL_Node<T>* remove(AVL_Node<T>* &pnode, T key);
T find_by_order(AVL_Node<T>* pnode, int k);
bool find(AVL_Node<T>* pnode, T key);
AVL_Node<T>* max(AVL_Node<T>* pnode);
AVL_Node<T>* min(AVL_Node<T>* pnode);
int height(AVL_Node<T>* pnode);
int size(AVL_Node<T>* pnode);
int max(int a, int b);
AVL_Node<T>* zag(AVL_Node<T>* pnode);
AVL_Node<T>* zig(AVL_Node<T>* pnode);
AVL_Node<T>* zag_zig(AVL_Node<T>* pnode);
AVL_Node<T>* zig_zag(AVL_Node<T>* pnode);
void destory(AVL_Node<T>* &pnode);
};
int N, M;
char cmd[10];
int cmd_num;
int main()
{
#ifdef __AiR_H
freopen("in.txt", "r", stdin);
#endif // __AiR_H
AVL<int> avl;
scanf("%d %d", &N, &M);
int num;
while (N--) {
scanf("%d", &num);
avl.insert(num);
}
while (M--) {
scanf("%s %d", cmd, &cmd_num);
if (cmd[0] == 'i') {
avl.insert(cmd_num);
} else if (cmd[0] == 'd') {
if (!avl.find(cmd_num)) {
printf("invalid number!\n");
} else {
avl.remove(cmd_num);
}
} else {
if (cmd_num > avl.size()) {
printf("invalid K!\n");
} else {
printf("%d\n", avl.find_by_order(avl.size() + 1 - cmd_num));
}
}
}
return 0;
}
template <typename T> AVL<T>::~AVL(void)
{
destory();
}
template <typename T> bool AVL<T>::find(T key)
{
return find(root, key);
}
template <typename T> bool AVL<T>::find(AVL_Node<T>* pnode, T key)
{
while (pnode != nullptr) {
if (pnode->key == key) {
return true;
} else if (key < pnode->key) {
pnode = pnode->lson;
} else {
pnode = pnode->rson;
}
}
return false;
}
template <typename T> void AVL<T>::remove(T key)
{
remove(root, key);
}
template <typename T> AVL_Node<T>* AVL<T>::remove(AVL_Node<T>* &pnode, T key)
{
if (pnode == nullptr) {
return nullptr;
}
if (key == pnode->key) {
if (pnode->lson != nullptr && pnode->rson != nullptr) {
if (height(pnode->lson) > height(pnode->rson)) {
AVL_Node<T>* pmax = max(pnode->lson);
pnode->key = pmax->key;
pnode->lson = remove(pnode->lson, pmax->key);
} else {
AVL_Node<T>* pmin = min(pnode->rson);
pnode->key = pmin->key;
pnode->rson = remove(pnode->rson, pmin->key);
}
} else {
AVL_Node<T>* pt = pnode;
if (pnode->lson != nullptr) {
pnode = pnode->lson;
} else {
pnode = pnode->rson;
}
delete pt;
pt = nullptr;
}
} else if (key > pnode->key) {
pnode->rson = remove(pnode->rson, key);
if (height(pnode->lson) - height(pnode->rson) == 2) {
if (height(pnode->lson->lson) > height(pnode->lson->rson)) {
pnode = zig(pnode);
} else {
pnode = zag_zig(pnode);
}
}
} else {
pnode->lson = remove(pnode->lson, key);
if (height(pnode->rson) - height(pnode->lson) == 2) {
if (height(pnode->rson->rson) > height(pnode->rson->lson)) {
pnode = zag(pnode);
} else {
pnode = zig_zag(pnode);
}
}
}
if (pnode == nullptr) {
return nullptr;
}
pnode->height = max(height(pnode->lson), height(pnode->rson)) + 1;
pnode->size = size(pnode->lson) + size(pnode->rson) + pnode->repeat;
return pnode;
}
template <typename T> T AVL<T>::max()
{
AVL_Node<T>* pret = max(root);
if (pret != nullptr) {
return pret->key;
}
}
template <typename T> AVL_Node<T>* AVL<T>::max(AVL_Node<T>* pnode)
{
if (pnode == nullptr) {
return nullptr;
}
while (pnode->rson != nullptr) {
pnode = pnode->rson;
}
return pnode;
}
template <typename T> T AVL<T>::min()
{
AVL_Node<T>* pret = min(root);
if (pret != nullptr) {
return pret->key;
}
}
template <typename T> AVL_Node<T>* AVL<T>::min(AVL_Node<T>* pnode)
{
if (pnode == nullptr) {
return nullptr;
}
while (pnode->lson != nullptr) {
pnode = pnode->lson;
}
return pnode;
}
template <typename T> T AVL<T>::find_by_order(int k)
{
return find_by_order(root, k);
}
template <typename T> int AVL<T>::max(int a, int b)
{
return a > b ? a : b;
}
template <typename T> T AVL<T>::find_by_order(AVL_Node<T>* pnode, int k)
{
int lsize = size(pnode->lson);
if (k <= lsize) {
return find_by_order(pnode->lson, k);
} else if (k > lsize+pnode->repeat) {
return find_by_order(pnode->rson, k-lsize-pnode->repeat);
}
return pnode->key;
}
template <typename T> void AVL<T>::insert(T key)
{
insert(root, key);
}
template <typename T> AVL_Node<T>* AVL<T>::insert(AVL_Node<T>* &pnode, T key)
{
if (pnode == nullptr) {
pnode = new AVL_Node<T>(key, nullptr, nullptr);
} else if (key > pnode->key) {
pnode->rson = insert(pnode->rson, key);
if (height(pnode->rson) - height(pnode->lson) == 2) {
if (key > pnode->rson->key) {
pnode = zag(pnode);
} else {
pnode = zig_zag(pnode);
}
}
} else if (key < pnode->key) {
pnode->lson = insert(pnode->lson, key);
if (height(pnode->lson) - height(pnode->rson) == 2) {
if (key < pnode->lson->key) {
pnode = zig(pnode);
} else {
pnode = zag_zig(pnode);
}
}
} else {
++pnode->repeat;
}
pnode->height = max(height(pnode->lson), height(pnode->rson)) + 1;
pnode->size = size(pnode->lson) + size(pnode->rson) + pnode->repeat;
return pnode;
}
template <typename T> AVL_Node<T>* AVL<T>::zag(AVL_Node<T>* pnode)
{
AVL_Node<T>* prson = pnode->rson;
pnode->rson = prson->lson;
prson->lson = pnode;
pnode->height = max(height(pnode->lson), height(pnode->rson)) + 1;
pnode->size = size(pnode->lson) + size(pnode->rson) + pnode->repeat;
prson->height = max(height(prson->lson), height(prson->rson)) + 1;
prson->size = size(prson->lson) + size(prson->rson) + prson->repeat;
return prson;
}
template <typename T> AVL_Node<T>* AVL<T>::zig(AVL_Node<T>* pnode)
{
AVL_Node<T>* plson = pnode->lson;
pnode->lson = plson->rson;
plson->rson = pnode;
pnode->height = max(height(pnode->lson), height(pnode->rson)) + 1;
pnode->size = size(pnode->lson) + size(pnode->rson) + pnode->repeat;
plson->height = max(height(plson->lson), height(plson->rson)) + 1;
plson->size = size(plson->lson) + size(plson->rson) + plson->repeat;
return plson;
}
template <typename T> AVL_Node<T>* AVL<T>::zag_zig(AVL_Node<T>* pnode)
{
pnode->lson = zag(pnode->lson);
return zig(pnode);
}
template <typename T> AVL_Node<T>* AVL<T>::zig_zag(AVL_Node<T>* pnode)
{
pnode->rson = zig(pnode->rson);
return zag(pnode);
}
template <typename T> int AVL<T>::size()
{
return size(root);
}
template <typename T> int AVL<T>::size(AVL_Node<T>* pnode)
{
if (pnode == nullptr) {
return 0;
}
return pnode->size;
}
template <typename T> int AVL<T>::height(void)
{
return height(root);
}
template <typename T> int AVL<T>::height(AVL_Node<T>* pnode)
{
if (pnode != nullptr) {
return pnode->height;
}
return 0;
}
template <typename T> void AVL<T>::destory(void)
{
destory(root);
}
template <typename T> void AVL<T>::destory(AVL_Node<T>* &pnode)
{
if (pnode != nullptr) {
destory(pnode->lson);
destory(pnode->rson);
delete pnode;
pnode = nullptr;
}
}