关闭

左式堆合并的实现

975人阅读 评论(0) 收藏 举报
分类:

这是第一篇博客,相信是个不错的开始!
//define the leftist heap struct
typedef struct Leftist pLeftist;
struct Leftist{

	int element;
	pLeftist left, right;
	int npl;
};

//build the merged leftist heap and return it
pLeftist BuildHeap(LeftistQueue q){

	Leftist h1, h2;

	while(!IsEmpty(q)){
		h1 = Dequeue(q);
		if(IsEmpty(q))
			return h1;		//the leftist heap has been built
		h2 = Dequeue(q);

		Enqueue(q, Merge(h1, h2));	//enqueue the new merged leftist heap
	}

	return NULL;	//there is no leftist heap in queue
}

pLeftist Merge(Leftist h1, Leftist h2){

	if(!h1)
		return h2;
	if(!h2)
		return h1;	

	if(h1->element<h2->element)		//compare the element and choose the root
		return MergeHeap(h1, h2);
	else
		return MergeHeap(h2, h1);
}

pLeftist MergeHeap(Leftist h1, Leftist h2){

	if(!h1->left){
		h1->left = h2;		//single node
	}else{
		h1->right = Merge(h1->right, h2);
		if(h1->left->npl<h1->right->npl)	//make left child's npl >= right's
			SwapChl(h1);
		h1->npl = h1->right->npl+1;		//make the npl equalling its right child+1
	}

	return h1;	//return the root
}

左式堆而言,较于小根堆

1.合并速度快,O(n)

2.链表比数组带来更多的开销,并且多一个域(npl)

3.代码相对复杂,其实也不复杂


较于leftist heap,有个skew heap,每次合并都左右换一下,不需要(npl),如果数据是随机的,也是一个很不错的选择


有个同学说随机删除堆里的一个元素,这样的方法比较好:

将改点的值置为负无穷,然后冒泡到顶部,再删去顶部,将剩下的两个子树合并。


不过,堆似乎不是用来随机删除节点的。一般指删最小的,以前遇到过一个题目,在最小的三个元素中删除一个特定的,这样就可以在前三层找(应该是7个元素中),然后删,随机删除其中的任意节点得不偿失。

还有,删除任意节点,将其子树合并,合并获得的新树的根放回原来删除节点的位置,这样不是很合理吗,为何要冒泡到最顶部?



0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:20420次
    • 积分:446
    • 等级:
    • 排名:千里之外
    • 原创:27篇
    • 转载:7篇
    • 译文:0篇
    • 评论:3条
    最新评论