1. 程式人生 > >用大根堆實現大值優先佇列

用大根堆實現大值優先佇列

        今天學了資料結構中的堆,堆分為大根堆和小根堆。大根堆是什麼呢?大根堆是指一顆即

是完全二叉樹又是大根樹的樹。那什麼是大根樹,和完全二叉樹呢?去百度google一下就知道了。

小根堆是一個與大根堆類似的概念,聯想一下吧。

大根堆和小根堆有何用呢?用處當然是有的,有人說可以用來實現大值優先佇列和小值優

先佇列。所以下面就大根堆來實現一個大值優先佇列heap。這個佇列提供兩個操作函式,一個是

push,一個是pop。push是把一個節點入列,pop是把節點出列,也就是刪除一個節點。

下面是程式碼實現

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

#define MAX_ELEMENTS 200
#define HEAP_FULL(n) (n == MAX_ELEMENTS - 1)
#define HEAP_EMPTY(n) (!n)

typedef struct
{
	int key;
	char c;
	/* add other fields */
} element;

element heap[MAX_ELEMENTS];

void push(element item, int *n)
{
	int i = 0;

	if(HEAP_FULL(*n))
	{
		fprintf(stderr, "The heap is full.\n");
		exit(0);
	}
	i = ++(*n);
	while(i != 1 && item.key > heap[i / 2].key)
	{
		heap[i] = heap[i / 2];
		i /= 2;
	}
	heap[i] = item;
}

// delete element with the highest key from the heap
element pop(int *n)
{
	int parent = 0, child = 0;
	element item, temp;

	if(HEAP_EMPTY(*n))
	{
		fprintf(stderr, "the heap is empty.\n");
		exit(0);
	}
	// save value of the element with the highest key
	item = heap[1];
	// use last element in heap to adjust heap parent
	temp = heap[(*n)--];
	parent = 1;
	child = 2;
	while(child <= *n)
	{
		// find the larger child of the current parent
		if(child < *n && heap[child].key < heap[child + 1].key)
			child++;
		if(temp.key >= heap[child].key)
			break;

		// move to the next lower level
		heap[parent] = heap[child];
		parent = child;
		child *= 2;
	}
	heap[parent] = temp;

	return item;
}

int main()
{
	int n = 0; // node counts
	int num[] = {2, 5, 18, 7, 9, 4, 3};
	element item;

	// push all node into queue
	for(int i = 0; i < sizeof(num) / sizeof(int); i++)
	{
		item.key = num[i];
		item.c = 'a';
		push(item, &n);
	}

	// pop all node out of queue
	while(n > 0)
	{
		item = pop(&n);
		printf("item.key = %d, ch = %c\n", item.key, item.c);
	}
	getchar();
	return 0;
}
大家可以把程式碼拷貝除錯看看,會發現在記憶體heap中不是按key值從大到小排列的,但pop列印的數值是從大到小,很神奇吧。