优先队列——斜堆

来源:互联网 发布:手机淘宝怎么关注达人 编辑:程序博客网 时间:2024/04/29 17:35

【0】README

0.1)本文部分内容转自  http://www.cnblogs.com/skywang12345/p/3638493.html, 旨在理解 优先队列——斜堆 的基础知识
0.2) for original source code , please visit https://github.com/pacosonTang/dataStructure-algorithmAnalysis/tree/master/chapter6/p150_skew_heap


【1】优先队列——斜堆相关

1.0)斜堆定义: 斜堆是具有堆序性的二叉树, 与左式堆的差别在于没有零路径属性,故merge操作后,不需要考虑左右子堆的零路径大小,而是无条件交换左右子堆;(干货——斜堆定义)

1.1)定义:斜堆(Skew heap)也叫自适应堆(self-adjusting heap),它是左式堆的一个变种。和左式堆一样,它通常也用于实现优先队列。它的合并操作的时间复杂度也是O(log n)。
1.2)相比于左倾堆,斜堆的节点没有”零距离”这个属性: 除此之外,它们斜堆的合并操作也不同。
1.3)斜堆的合并操作算法如下:

  • case1) 如果一个空斜堆与一个非空斜堆合并,返回非空斜堆。
  • case2) 如果两个斜堆都非空,那么比较两个根节点,取较小堆的根节点为新的根节点。将”较小堆的根节点的右孩子”和”较大堆”进行合并。
  • case3) 合并后,交换新堆根节点的左孩子和右孩子。

Attention)

  • A1)第3步是斜堆和左式堆的合并操作差别的关键所在,如果是左式堆,则合并后要比较左右孩子的零距离大小,若右孩子的零距离 > 左孩子的零距离,则交换左右孩子;最后,在设置根的零距离。
  • A2) 下面是一个关于斜堆的干货荔枝:

【2】source code + printing results

2.1)source code at a glance

#include "skew_heap.h" // swap the left and the right in priority queue.void swap(PriorityQueue h1){    PriorityQueue temp;    temp = h1->left;    h1->left = h1->right;    h1->right = temp;}// analog print directories and files name in the BinaryTree, which involves postorder traversal. void printPreorder(int depth, TreeNode root){               int i;    if(root)     {              for(i = 0; i < depth; i++)            printf("    ");             printf("%d\n", root->value);        printPreorder(depth + 1, root->left);          // Attention: there's difference between traversing binary tree and common tree.        printPreorder(depth + 1, root->right);    }    else     {        for(i = 0; i < depth; i++)            printf("    ");             printf("NULL\n");    }}// insert an element with value into the priority queue.PriorityQueue insert(ElementType value, PriorityQueue pq){    TreeNode node;              node = (TreeNode)malloc(sizeof(struct TreeNode));    if(!node)    {        Error("failed inserting, for out of space !");        return pq;    }    node->left = NULL;    node->right = NULL;     node->value = value;        if(pq == NULL) // means that just only creating a node with value.    {        return node;    }    else    {        return merge(node, pq);         }}// return the minimal between a and b.int minimal(int a, int b){    return a > b ? b : a;}// merge the priority queue h1 and h2.PriorityQueue merge(PriorityQueue h1, PriorityQueue h2){           if(h1 == NULL)    {        return h2;    }    else if(h2 == NULL)    {        return h1;    }       if(h1->value > h2->value)    {        return innerMerge(h2, h1);    }    else    {        return innerMerge(h1, h2);    }   }// merge the priority queue h1 and h2.PriorityQueue innerMerge(PriorityQueue h1, PriorityQueue h2){     if(h1->left == NULL)    {        h1->left = h2;    }    else    {        h1->right = merge(h1->right, h2);        swap(h1);           }           return h1;} int main(){    PriorityQueue h1;    PriorityQueue h2;       int data[] =  {21, 10, 23, 14, 3, 26, 17, 8};       int data2[] = {18, 7, 37, 6, 24, 33, 12, 18};       int i;    h1 = insert(data[0], NULL);    for(i=1; i<8; i++)    {        h1 = insert(data[i], h1);    }    printf("\n=== after the leftist heap h1 is merged===\n");    printPreorder(1, h1);    h2 = insert(data2[0], NULL);    for(i=1; i<8; i++)    {        h2 = insert(data2[i], h2);    }    printf("\n=== after the leftist heap h2 is merged===\n");    printPreorder(1, h2);    h1 = merge(h1, h2);    printf("\n=== after both h1 and h2 are merged===\n");    printPreorder(1, h1);      return  0;}

2.2) printing results

0 0