C实现左式堆(leftist heap)

309 阅读2分钟

左式堆的定义

左式堆的实现

fatal.h

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

#define Error( Str )        FatalError( Str )
#define FatalError( Str )   fprintf( stderr, "%s\n", Str ), exit( 1 )

leftheap.h

 typedef int ElementType;

/* START: fig6_25.txt */
        #ifndef _LeftHeap_H
        #define _LeftHeap_H

        struct TreeNode;
        typedef struct TreeNode *PriorityQueue;

        /* Minimal set of priority queue operations */
        /* Note that nodes will be shared among several */
        /* leftist 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 ) )
        /* DeleteMin macro is left as an exercise */

        PriorityQueue Insert1( ElementType X, PriorityQueue H );
        PriorityQueue DeleteMin1( PriorityQueue H );

        #endif

/* END */

leftheap.c

#include "leftheap.h"
        #include "fatal.h"
        #include <stdlib.h>


        struct TreeNode
        {
            ElementType   Element;  // 元素项
            PriorityQueue Left;     // 左子左式堆
            PriorityQueue Right;    // 右左式堆
            int           Npl;      // 右侧 null path length 也就是Npl 零路径长 
        };

        PriorityQueue
        Initialize( void )
        {
            // 初始化函数不用做额外的事情 等于把一个元素与NULL合并即可 主要的实现在于合并操作是如何进行的
            return NULL;
        }
        static PriorityQueue Merge1( PriorityQueue H1, PriorityQueue H2 );

/* START: fig6_26.txt */
        PriorityQueue
        Merge( PriorityQueue H1, PriorityQueue H2 )
        {
/* 1*/      if( H1 == NULL )
/* 2*/          return H2;
/* 3*/      if( H2 == NULL )
/* 4*/          return H1;
            // 保证H1的元素小于H2
/* 5*/      if( H1->Element < H2->Element )
/* 6*/          return Merge1( H1, H2 );
            else
/* 7*/          return Merge1( H2, H1 );
        }
/* END */

        void
        SwapChildren( PriorityQueue H )
        {
            PriorityQueue Tmp;
            // 交换左右子堆
            Tmp = H->Left;
            H->Left = H->Right;
            H->Right = Tmp;
        }

/* START: fig6_27.txt */
        static PriorityQueue
        Merge1( PriorityQueue H1, PriorityQueue H2 )
        {
            // 应为是递归调用merge方法,最终会一直递归到一个没有右子节点的节点 如果它没有左子节点 说明抵达了一个单个节点
/* 1*/      if( H1->Left == NULL )  /* Single node */
/* 2*/          H1->Left = H2;      /* H1->Right is already NULL,
                                       H1->Npl is already 0 */
            else
            {
/* 3*/          H1->Right = Merge( H1->Right, H2 );
                // 递归调用完成一层返回的时候检查合并后的新堆 是否比左堆 npl 大
/* 4*/          if( H1->Left->Npl < H1->Right->Npl )
/* 5*/              SwapChildren( H1 );

/* 6*/          H1->Npl = H1->Right->Npl + 1;
            }
/* 7*/      return H1;
        }
/* END */

/* START: fig6_29.txt */

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

/* 1*/      SingleNode = malloc( sizeof( struct TreeNode ) );
/* 2*/      if( SingleNode == NULL )
/* 3*/          FatalError( "Out of space!!!" );
            else
            {
/* 4*/          SingleNode->Element = X; SingleNode->Npl = 0;
/* 5*/          SingleNode->Left = SingleNode->Right = NULL;
                // 插入单个节点就是等同于一次 堆与单个节点的堆的合并
/* 6*/          H = Merge( SingleNode, H );
            }
/* 7*/      return H;
        }
/* END */


/* START: fig6_30.txt */
        /* DeleteMin1 returns the new tree; */
        /* To get the minimum, use FindMin */
        /* This is for convenience */

        PriorityQueue
        DeleteMin1( PriorityQueue H )
        {
            PriorityQueue LeftHeap, RightHeap;

/* 1*/      if( IsEmpty( H ) )
            {
/* 2*/          Error( "Priority queue is empty" );
/* 3*/          return H;
            }
        
            // 由于堆序性 删除根节点 然后合并左右子堆即可 新的左式堆依旧满足左式堆的条件
/* 4*/      LeftHeap = H->Left;
/* 5*/      RightHeap = H->Right;
/* 6*/      free( H );
/* 7*/      return Merge( LeftHeap, RightHeap );
        }
/* END */

        ElementType
        FindMin( PriorityQueue H )
        {
            if( !IsEmpty( H ) )
                return H->Element;
            Error( "Priority Queue is Empty" );
            return  0;
        }

        int
        IsEmpty( PriorityQueue H )
        {
            return H == NULL;
        }

参考资料:

《数据结构与算法分析: C语言描述》