二叉堆和二叉搜索树进阶

1、引言

《算法竞赛进阶指南》中指出,在二叉树中,有两组非常重要的条件,分别是两类数据结构的基本性质。

其一是“堆性质”,若二叉树中的任意一个节点的权值都大于等于(小于等于)其父亲节点,则称该二叉树满足“小顶堆性质(大顶堆性质)”。

其二是“BST性质”,二叉树上的每个节点都带有一个数值,称为该节点的键值 $key$,树中的任意一个节点的 $key$ 均同时满足:大于等于其左子树中任意节点的 $key$,小于等于其右子树中任意节点的 $key$。

在日常的刷题过程中,经常会用到优先队列、set、map等STL的容器,但是实际上它们的底层实现某种程度上可以说是二叉堆或者BST,而且二叉堆和BST作为较基础的数据结构,我们应当学会如何实现。

2、二叉堆的实现

struct Heap
{
    int sz;
    int heap[maxn];
    void up(int now)
    {
        while(now>1)
        {
            int par=now>>1;
            if(heap[now]<heap[par]) //子节点小于父节点,不满足小顶堆性质
            {
                swap(heap[par],heap[now]);
                now=par;
            }
            else break;
        }
    }
    void push(int x) //插入权值为x的节点
    {
        heap[++sz]=x;
        up(sz);
    }
    inline int top(){return heap[1];}
    void down(int now)
    {
        while((now<<1)<=sz)
        {
            int nxt=now<<1;
            if(nxt+1<=sz && heap[nxt+1]<heap[nxt]) nxt++; //取左右子节点中较小的
            if(heap[now]>heap[nxt]) //子节点小于父节点,不满足小顶堆性质
            {
                swap(heap[now],heap[nxt]);
                now=nxt;
            }
            else break;
        }
    }
    void pop() //移除堆顶
    {
        heap[1]=heap[sz--];
        down(1);
    }
    void del(int p) //删除存储在数组下标为p位置的节点
    {
        heap[p]=heap[sz--];
        up(p), down(p);
    }
    inline void clr(){sz=0;}
};

3、二叉堆的应用

  3.1、POJ 1456

  3.2、二叉堆优化Dijkstra

  3.3、BZOJ 1150

4、二叉搜索树

普通的二叉搜索树每次期望复杂度为 $O(log n)$,但是非常容易退化为 $O(n)$,因此实际应用中一般使用平衡二叉查找树。

4.1、伸展树Splay

  伸展树原理:

    伸展树(Splay Tree)进阶 - 从原理到实现

  伸展树实现:

    POJ 3580 - SuperMemo - [伸展树splay]

4.2、Treap

  BZOJ 3224 - 普通平衡树 - [Treap]

原文地址:https://www.cnblogs.com/dilthey/p/9801549.html