AVL 树 2016.9.3

转自《数据结构(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

事实上,这些限制条件设定得非常精妙,除了适度平衡性,还具有如下局部性

  1. 经过单次动态修改操作后,至多只有 O(1) 处局部不再满足限制条件
  2. 总可在 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;
    }
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值