美文网首页
左偏树和斜堆

左偏树和斜堆

作者: 胡哈哈哈 | 来源:发表于2016-05-20 21:31 被阅读616次

左偏树的性质

  • 本节点的键值key小于其左右子节点键值key(与二叉堆相同);
  • 本节点的左子节点的距离大于等于本节点的右子节点(这意味着每个节点中除了要存储键值外, 还需要一个额外的dist存储距离);
  • 节点的距离是其右子节点的距离+1(这意味着, 一个节点的dist是从它出发到达最近终端节点的距离);

斜堆的性质

  • 本节点的键值key小于其左右子节点键值key;
  • 斜堆节点不存储距离dist值, 取而代之的是在每次合并操作时都做swap处理(节省了存储空间);

核心操作

  • 合并操作
  • 插入操作
  • 取最小操作

实现

左偏树(堆)merge函数具体实现

  • 采用递归实现;
  • 每层递归中, 当roota->val > rootb->val时, 交换rootarootb;
  • 向下递归;
  • 如左子节点距离小于右子节点距离, 交换左右子节点;
  • 更新本节点距离值;
  • 返回本节点指针;

斜堆merge函数具体实现

--采用递归实现(也有非递归算法);
--每层递归中, 当roota->val > rootb->val时, 交换roota和rootb;
--向下递归;
--交换左右子节点;
--返回本节点指针;

代码

左偏树

typedef int elemType;
struct leftistTreeNode {
    elemType data;
    unsigned int dist;
    leftistTreeNode *lchild, *rchild;
    leftistTreeNode(const elemType &val): data(val), dist(0), lchild(NULL), rchild(NULL) {}
};
template <typename type>
void swapPtr(type &x, type &y) {
    type t = x;
    x = y; y = t;
}

leftistTreeNode *createLeftistTree(const vector<elemType> &vec);
void destroyLeftistTree(leftistTreeNode *&root);
leftistTreeNode *mergeLeftistTree(leftistTreeNode *&roota, leftistTreeNode *&rootb);
void insertLeftistTreeNode(leftistTreeNode *&root, const elemType &dt);
leftistTreeNode *extractMinNode(leftistTreeNode *&root);

leftistTreeNode *createLeftistTree(const vector<elemType> &vec) {
    leftistTreeNode *root = NULL;
    for (int i = 0; i != vec.size(); ++i)
        insertLeftistTreeNode(root, vec[i]);
    return root;
}
void destroyLeftistTree(leftistTreeNode *&root) {
    leftistTreeNode *left = root->lchild, *right = root->rchild;
    delete(root); root = NULL;
    if (left) destroyLeftistTree(left);
    if (right) destroyLeftistTree(right);
}
leftistTreeNode *mergeLeftistTree(leftistTreeNode *&roota, leftistTreeNode *&rootb) {//核心部分
    if (!roota || !rootb)
        return roota ? roota : rootb;
    if (roota->data > rootb->data)
        swapPtr<leftistTreeNode*>(roota, rootb);//注意: 此处交换的是指针值
    roota->rchild = mergeLeftistTree(roota->rchild, rootb);
    if (!roota->lchild || roota->lchild->dist < roota->rchild->dist)
        swapPtr<leftistTreeNode*>(roota->lchild, roota->rchild);
    if (!roota->rchild)
        roota->dist = 0;
    else
        roota->dist = roota->rchild->dist + 1;
    return roota;
}
void insertLeftistTreeNode(leftistTreeNode *&root, const elemType &dt) {
    leftistTreeNode *cur = new leftistTreeNode(dt);
    root = mergeLeftistTree(root, cur);
}
leftistTreeNode *extractMinNode(leftistTreeNode *&root) {
    leftistTreeNode *min = root;
    root = mergeLeftistTree(root->lchild, root->rchild);
    return min;
}

斜堆

typedef int elemType;
struct skewHeapNode {
    elemType data;
    skewHeapNode *lchild, *rchild;
    skewHeapNode(const elemType &val): data(val), lchild(NULL), rchild(NULL) {}
};

template <typename type>
void swapPtr(type &x, type &y) {
    type t = x;
    x = y; y = t;
}

skewHeapNode *createskewHeap(const vector<elemType> &vec);
void destroyskewHeap(skewHeapNode *&root);
skewHeapNode *mergeskewHeap(skewHeapNode *&roota, skewHeapNode *&rootb);
void insertskewHeapNode(skewHeapNode *&root, const elemType &dt);
skewHeapNode *extractMinNode(skewHeapNode *&root);

skewHeapNode *createskewHeap(const vector<elemType> &vec) {
    skewHeapNode *root = NULL;
    for (int i = 0; i != vec.size(); ++i)
        insertskewHeapNode(root, vec[i]);
    return root;
}
void destroyskewHeap(skewHeapNode *&root) {
    skewHeapNode *left = root->lchild, *right = root->rchild;
    delete(root); root = NULL;
    if (left) destroyskewHeap(left);
    if (right) destroyskewHeap(right);
}
skewHeapNode *mergeskewHeap(skewHeapNode *&roota, skewHeapNode *&rootb) {//此处与左偏堆不同, 不判断左右子节点距离
    if (!roota || !rootb)
        return roota ? roota : rootb;
    if (roota->data > rootb->data)
        swapPtr<skewHeapNode*>(roota, rootb);
    roota->rchild = mergeskewHeap(roota->rchild, rootb);
    swapPtr(roota->lchild, rootb->rchild);
    return roota;
}
void insertskewHeapNode(skewHeapNode *&root, const elemType &dt) {
    skewHeapNode *cur = new skewHeapNode(dt);
    root = mergeskewHeap(root, cur);
}
skewHeapNode *extractMinNode(skewHeapNode *&root) {
    skewHeapNode *min = root;
    root = mergeskewHeap(root->lchild, root->rchild);
    return min;
}

相关文章

  • 左偏树和斜堆

    左偏树的性质 本节点的键值key小于其左右子节点键值key(与二叉堆相同); 本节点的左子节点的距离大于等于本节点...

  • 数据结构: 可合并堆-左偏树 Leftist Tree

    数据结构: 可合并堆-左偏树 来自维基百科左偏树(英语: leftist tree或leftist heap), ...

  • 数据结构:左偏堆

    左偏堆简介 又称左偏树、左倾堆,这么多名字都带个左,那就是因为它向左倾斜,和二叉堆一样都是一种优先队列实现方式。 ...

  • 左偏树

    bzoj1455 罗马游戏Description罗马皇帝很喜欢玩杀人游戏。 他的军队里面有n个人,每个人都是一个独...

  • 可合并堆之左偏树的简介与应用

    前言 在之前的这篇文章里,笔者详细讲解了二叉堆这种简单有效的数据结构,并且讨论了优先队列的实现方式。现在有个新的问...

  • LUOGU 3377 左偏树

    Description 如题,一开始有个小根堆,每个堆包含且仅包含一个数。接下来需要支持两种操作:操作1 将...

  • 左偏和右偏

    偏态分布为统计学概念,即统计数据峰值与平均值不相等的频率分布。根据峰值小于或大于平均值可分为正偏函数和负偏函...

  • 左式堆、斜堆、二项队列

    左式堆 设计一种堆结构像二叉堆那样高效地支持合并操作(即以 时间处理一次 Merge)而且只使用一个数组似乎很困难...

  • 数据结构|堆和树

    堆 堆是一种比较特殊的数据结构,可以看成一颗树的数组对象。 堆中的某个节点的值总是不大于或不小于其父节点的值 堆是...

  • 故里归

    故里归一 几堆小坟新置,几缕炊烟轻飘。村头十里路不识,寻得记忆又差错,斜斜草树夕阳照,一人孤影泪迷离。 ...

网友评论

      本文标题: 左偏树和斜堆

      本文链接:https://www.haomeiwen.com/subject/hbbnrttx.html