📜  倾斜堆(1)

📅  最后修改于: 2023-12-03 15:22:30.203000             🧑  作者: Mango

倾斜堆介绍

什么是倾斜堆

倾斜堆(Skew Heap)是一种二叉堆(Binary Heap)的变种。倾斜堆中,每个节点最多有一个子节点不为空,因此它的形状可以看作是一棵高度不超过$logn$的斜树。

倾斜堆具有平衡性较弱的特点,但由于其构建和调整操作简单,效率较高,被广泛应用于各种算法和数据结构中。

倾斜堆的性质
  • 一棵倾斜堆 $T$ 满足任意一棵子树 $T'$ 的每个节点 $x$ 的关键字(Key)均不大于 $x$ 的父节点的关键字。
  • 倾斜堆中,左右儿子的高度差不能超过 $1$,因此其高度不超过 $logn$。
倾斜堆的操作
构建

倾斜堆的构建较为简单,只需将每个节点看作一棵单节点的倾斜堆,然后依次做合并操作即可。合并操作会将两个堆 $S$ 和 $T$ 合并成一个新堆 $H$,并保证 $S$ 和 $T$ 的关键字仍然满足倾斜堆的性质。

struct SkewHeap {
    SkewHeap *l, *r;
    int key;

    SkewHeap(int k): key(k), l(NULL), r(NULL) {}
};

SkewHeap* merge(SkewHeap* h1, SkewHeap* h2) {
    if (!h1) return h2;
    if (!h2) return h1;
    if (h1->key > h2->key) swap(h1, h2);
    h1->r = merge(h1->r, h2);
    swap(h1->l, h1->r);
    return h1;
}

SkewHeap* build(vector<int> &a) {
    SkewHeap* h = NULL;
    for (int i = 0; i < a.size(); i++) {
        h = merge(h, new SkewHeap(a[i]));
    }
    return h;
}
插入

倾斜堆的插入操作和构建类似,只需将待插入节点看作一个单节点的倾斜堆,然后与原堆合并即可。

void insert(SkewHeap*& h, int x) {
    h = merge(h, new SkewHeap(x));
}
弹出堆顶元素

倾斜堆弹出堆顶元素的操作同样简单,只需将其左右子树合并即可。

int pop(SkewHeap*& h) {
    int key = h->key;
    SkewHeap* l = h->l;
    SkewHeap* r = h->r;
    delete h;
    h = merge(l, r);
    return key;
}
倾斜堆的应用
  • Dijkstra算法中的优先队列。
  • 堆排序的实现。
  • 合并多个有序序列的算法。
  • 费用流算法中的路径优化。
总结

倾斜堆是一种高效的二叉堆变种,具有构建和调整操作简单的优点,被广泛应用于各种算法和数据结构中。虽然其平衡性较弱,但在很多场合下,可以满足我们的需求。