左式堆的简单实现(C语言描述)

左式堆

左式堆是优先队列的一种实现,它的目的主要是为了解决二叉堆的合并问题.(你将在后面看到左式堆是如何用递归来优美地进行合并的)

零路径长

把任意节点X的零路径长(null path length, NPL) Npl(X) 定义为从X到一个没有两个儿子的节点的最短路径长。因此,具有0个或1个儿子的节点的Npl值为0,而Npl(NULL)=-1。注意,任意节点的零路径长比它的各个儿子节点的最小值多1。

堆序性质

左式堆的性质是:对于堆中的每一个节点X,左儿子的零路径长至少与右儿子的零路径长一样大。因此,下图1中,左边的二叉树是左式堆,而右边的二叉树则不是。这个性质使左式堆明显更偏重于使树向左增加深度,左式堆的名称也由此而来。

代码实现

头文件


#ifndef LEFTHEAP_LEFTHEAP_H
#define LEFTHEAP_LEFTHEAP_H

struct TreeNode;
typedef struct TreeNode *PriorityQueue;
typedef long long ElementType;
/* Minmal set of priority queue operations */
/* Note that nodes will be shared among several */
/* leftlist heaps after a merge; the user must */
/* make sure to not use the old leftist heaps */

PriorityQueue Initialize(void);

ElementType FindMin(PriorityQueue H);

int IsEmpty(PriorityQueue H);

PriorityQueue Merge(PriorityQueue H1, PriorityQueue H2);

#define Insert(X, H)(H = Insert1((X),H))

PriorityQueue Insert1(ElementType X, PriorityQueue H);

PriorityQueue DeleteMin1(PriorityQueue H);

#endif //LEFTHEAP_LEFTHEAP_H

实现


#include "LeftHeap.h"
#include <stdio.h>
#include <stdlib.h>

struct TreeNode {
    ElementType Element;

    PriorityQueue Left;
    PriorityQueue Right;

    int Npl;
};

int IsEmpty(PriorityQueue H) {
    return H->Left == NULL && H->Right->Right == NULL;
}


static void SwapChildren(PriorityQueue pNode) {
    PriorityQueue tmp = malloc(sizeof(struct TreeNode));
    *tmp = *(pNode->Left);
    *(pNode->Left) = *(pNode->Right);
    *(pNode->Right) = *(tmp);
}

static PriorityQueue Merge1(PriorityQueue H1, PriorityQueue H2) {
    if (H1->Left == NULL)
        H1->Left = H2;
    else {
        H1->Right = Merge(H1->Right, H2);
        if (H1->Left->Npl < H1->Right->Npl)
            SwapChildren(H1);

        H1->Npl = H1->Right->Npl + 1;
    }

    return H1;
}

PriorityQueue Merge(PriorityQueue H1, PriorityQueue H2) {

    if (H1 == NULL)
        return H2;
    if (H2 == NULL)
        return H1;
    if (H1->Element < H2->Element)
        return Merge1(H1, H2);
    else
        return Merge1(H2, H1);
}

void FatalError(char *message) {
    printf("%s\n", message);
    exit(1);
}

PriorityQueue Insert1(ElementType X, PriorityQueue H) {
    PriorityQueue SingleNode;

    SingleNode = malloc(sizeof(struct TreeNode));
    if (SingleNode == NULL) {
        FatalError("Out of space!!!");
    } else {
        SingleNode->Element = X;
        SingleNode->Npl = 0;
        SingleNode->Left = SingleNode->Right = NULL;
        H = Merge(SingleNode, H);
    }

    return H;
}


void Error(char *message) {
    printf("%s\n", message);
}

/* DeleteMin1 returns the new tree */
/* To get the minmum, use FindMin */
/* This is for convenience */
PriorityQueue DeleteMin1(PriorityQueue H) {
    PriorityQueue LeftHeap, RightHeap;

    if (IsEmpty(H)) {
        Error("Priority queue is empty");
        return H;
    }

    LeftHeap = H->Left;
    RightHeap = H->Right;
    free(H);
    return Merge(LeftHeap, RightHeap);
}

ElementType FindMin(PriorityQueue H) {
    return H->Element;
}


PriorityQueue Initialize(void) {

}

可以自行到网上找一些左式堆的图片加深一下理解

点赞