左式堆,是一種二叉樹,但它是趨於左邊極不平衡的二叉樹。
結構性質:趨於左邊極不平衡的二叉樹
堆序性質:最小值在根節點上
NPL:從X節點到一個沒有兩個兒子的節點的最短路徑的長度,稱爲X節點的NPL
特殊要求:左子樹的NPL不小於右子樹的NPL
設計目的:合併操作效率高
合併操作思想:如果兩個堆中有一個爲空,那麼我們可以返回另外一個堆,否則,需要比較它們的根,將具有較大根值的堆與具
有較小根值的堆的右子堆進行合併。如此遞歸下去,如果合併得到的堆違反了“左子樹的NPL不小於右子樹的
NPL”這條性質,則將堆的左右兩個子堆交換即可。
左式堆C語言實現如下:
#include<stdio.h>
#include<stdlib.h>
struct Left_Heap {
int data;
struct Left_Heap *lchild;
struct Left_Heap *rchild;
int npl;
};
struct Left_Heap *merger(struct Left_Heap *H1,struct Left_Heap *H2);
//交換左式堆的左右兩個子左式堆位置
void swapChildren(struct Left_Heap *H)
{
struct Left_Heap *left = H->lchild;
H->lchild = H->rchild;
H->rchild = left;
}
struct Left_Heap *merger1(struct Left_Heap *H1,struct Left_Heap *H2)
{
//單節點
if(NULL == H1->lchild)
H1->lchild = H2;
//注意:這裏不存在沒有左子樹,只有右子樹情況,否則不滿足左式堆性質(左兒子的npl不小於右兒子的npl)
//肯定左右兩個子樹同時存在,按照左式堆合併策略,將H1的右子樹與H2進行合併
else
{
H1->rchild = merger(H1->rchild,H2);
//當不滿足左式堆性質(左兒子的npl不小於右兒子的npl)時,需要交換左右子樹
if(H1->lchild->npl < H1->rchild->npl)
swapChildren(H1);
//更新npl
H1->npl = H1->rchild->npl + 1;
}
return H1;
}
struct Left_Heap *merger(struct Left_Heap *H1,struct Left_Heap *H2)
{
if(NULL == H1)
return H2;
if(NULL == H2)
return H1;
if(H1->data < H2->data)
return merger1(H1,H2);
else
return merger1(H2,H1);
}
struct Left_Heap *insert(int data,struct Left_Heap *H)
{
struct Left_Heap *temp;
//注意:在這裏不用再判斷 H 是否爲NULL,因爲merger()函數中已做過 H 爲NULL的處理
//創建一個單節點左式堆,然後進行合併
temp = malloc(sizeof(struct Left_Heap));
if(NULL == temp)
{
printf("Error: out of memory!!\n");
return NULL;
}
temp->data = data;
temp->lchild = temp->rchild = NULL;
temp->npl = 0;
return merger(temp,H);
}
struct Left_Heap *delete_min(struct Left_Heap *H)
{
struct Left_Heap *left_heap,*right_heap;
if(NULL == H)
{
printf("Failed: the current heap is a already empty leftist heap!!\n");
return H;
}
left_heap = H->lchild;
right_heap = H->rchild;
free(H);
//將左右兩個子左式堆進行合併
return merger(left_heap,right_heap);
}
void print_preorder(struct Left_Heap *H)
{
if(NULL == H)
return;
printf("%d ",H->data);
print_preorder(H->lchild);
print_preorder(H->rchild);
}
void print_midorder(struct Left_Heap *H)
{
if(NULL == H)
return;
print_midorder(H->lchild);
printf("%d ",H->data);
print_midorder(H->rchild);
}
void print_postorder(struct Left_Heap *H)
{
if(NULL == H)
return;
print_postorder(H->lchild);
print_postorder(H->rchild);
printf("%d ",H->data);
}
void print_allorder(struct Left_Heap *H)
{
printf("當前左式堆的前序遍歷爲:");
print_preorder(H);
printf("\n");
printf("當前左式堆的中序遍歷爲:");
print_midorder(H);
printf("\n");
printf("當前左式堆的後序遍歷爲:");
print_postorder(H);
printf("\n");
}
int main(void)
{
struct Left_Heap *g_H = NULL;
int c;
scanf("%d",&c);
while(c != 0)
{
g_H = insert(c,g_H);
scanf("%d",&c);
}
print_allorder(g_H);
printf("--------before delete----------\n");
g_H = delete_min(g_H);
printf("--------after delete----------\n");
print_allorder(g_H);
return 0;
}
程序運行結果如下: