左式堆的定义
左式堆的实现
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语言描述》