一種左式堆實現

左式堆,是一種二叉樹,但它是趨於左邊極不平衡的二叉樹。

結構性質:趨於左邊極不平衡的二叉樹

堆序性質:最小值在根節點上

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;
}

程序運行結果如下:


發佈了36 篇原創文章 · 獲贊 11 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章