二叉堆&&优先级队列

本文介绍二叉堆的结构与性质,探讨其在数据结构中的应用,特别是作为优先级队列的基础。文中详细解释了二叉堆的常见操作,如插入、删除最小元素等,并提供了C语言实现示例。

二叉堆在结构上类似完全二叉树,除最低层外,是被完全填满的,低层的元素从左向右填入。

依据上面的性质,一颗高度为h的的二叉堆有2的h次方到2的h次方减一个节点。

二叉堆的堆序性质:在堆中,对于堆中的任意一个节点X,X的父亲的键值小(大于)于X的键值(根节点除外)。

故,依据堆序性质,最小(大)的键值总是在树根处,findMin/Max操作可以在常数时间内完成,二叉堆一般使用数组表示,第一个节点索引为1。


下面以最小堆(节点X的父亲的键值总是小于X的键值)对二叉堆的操作,最大堆一般反向操作。

1,构造堆,常用的堆排序算法的基础

2,插入一个键值

3,弹出最小元素

4,返回最小元素

5,减某个节点的键值


优先级队列(包括最大优先级队列和最小优先级队列)是基于堆实现的一种数据结构,因为基于堆来实现,所以同样提供以上五种操作。

下面是一份c语言实现的堆的基本操作:

/*
min_binary_heap.c
yejing@2014.11.3
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HEAP_SIZE 1024

typedef struct _min_heap{
	int heap_array[HEAP_SIZE];
	int heap_size;
}heap_t;

heap_t heap;

void array_show(int array[], int n){
	int i = 0;
	for(i = 1; i <= n; i++)
		printf(" %d", array[i]);
	printf("\n");
	return;
}

//采用上浮法建堆
void heap_insert(int value){
	if(heap.heap_size >= HEAP_SIZE - 1)//堆从索引为1的数组元素开始
		return;
		
	int tmp = ++heap.heap_size;
	heap.heap_array[tmp] = value;
	
	while(tmp > 1 && heap.heap_array[tmp] < heap.heap_array[tmp/2]){
		heap.heap_array[tmp] = heap.heap_array[tmp/2];
		tmp /= 2;
	}
	heap.heap_array[tmp] = value;
	return;
}
void swap(int* x, int* y){
	if(!x || !y)
		return;
	int tmp = *x;
	*x = *y;
	*y = tmp;
	return;
}

/*返回堆的最小元素*/
int get_root(void){	
	if(heap.heap_size < 1){
		printf("heap is empty !! \n");
		return -1;
	}
	printf("the smallest item of the heap is %d \n", heap.heap_array[1]);
	return heap.heap_array[1];
}

/*堆的最小化*/
void heap_min_heaprify(int pos){
	int lchild, rchild, minimam;
	lchild = 2*pos;
	rchild = 2*pos + 1;
	if(lchild <= heap.heap_size && heap.heap_array[lchild] < heap.heap_array[pos])
		minimam = lchild;
	else
		minimam = pos;
	if(rchild <= heap.heap_size && heap.heap_array[rchild] < heap.heap_array[minimam])
		minimam = rchild;
	if(minimam != pos){
		swap(&(heap.heap_array[minimam]), &(heap.heap_array[pos]));
		heap_min_heaprify(minimam);
	}
	return;
}

/*弹出最小元素*/
int heap_extract_min(){
	if(heap.heap_size < 1){
		printf("heap is empty! no item to extract\n");
		return -1;
	}
	int min = get_root();
	heap.heap_array[1] = heap.heap_array[heap.heap_size];
	heap.heap_size--;
	heap_min_heaprify(1);
	printf("the current heap after extract_min: ");
	array_show(heap.heap_array, heap.heap_size);
	return min;
}

/*建堆*/
void heap_build(int array[], int n){
	if(n > HEAP_SIZE - 1)
		return;
	int i;
#ifdef DIVE
	for(i = 0; i < n; ++i)
		heap_insert(array[i]);
#else
	memcpy(heap.heap_array + 1, array, n*sizeof(int));
	heap.heap_size = n;
	for(i = n/2; i > 0; i--){
		heap_min_heaprify(i);
	}
#endif
	printf("heap_build finished, data is:");
	array_show(heap.heap_array, heap.heap_size);
	return;
}

/*降低某个节点的key值*/
void heap_decrease_key(int i, int key){
	if(heap.heap_size < i || heap.heap_array[i] < key){
		printf("precondition is not correct \n");
		return;
	}
	
	heap.heap_array[i] = key;
	while(i > 1 && heap.heap_array[i/2] > heap.heap_array[i]){
		swap(&heap.heap_array[i/2], &heap.heap_array[i]);
		i /= 2;
	}
	
	printf("heap_decrease_key fininshed, now, data is: ");
	array_show(heap.heap_array, heap.heap_size);
	return;
}

/*向堆中插入一个元素*/
void heap_insert_key(int key){
	heap.heap_size++;
	heap.heap_array[heap.heap_size] = 0x7fffffff;
	heap_decrease_key(heap.heap_size, key);
	printf("heap_insert finished, now, data is: ");
	array_show(heap.heap_array, heap.heap_size);
	return;
}

/*堆排序,小堆从大往小,大堆从小往大*/
void heap_sort(int array[], int n){
	if(!array || n < 0 || n > HEAP_SIZE - 1){
		printf("input params are not appropriate \n");
		return;
	}
	int i = 0;
	heap_build(array, n);
	int tmp = heap.heap_size;
	for(i = n; i > 1; i--){
		swap(&heap.heap_array[1], &heap.heap_array[i]);
		--heap.heap_size;
		heap_min_heaprify(1);
	}
	heap.heap_size = tmp;
	printf("\033[1;31;40mheap_sort finished, data is:");
	array_show(heap.heap_array, heap.heap_size);
	printf("\033[0m\n");
	return;
}

int main(int argc, char* argv[]){
	memset((char*)&heap, 0, sizeof(heap));
	int array[] = {1,2,3,9,7,5,43,55,32,45,68,65,345,54,32,10,11,21,54,87,98,0};
	
	heap_sort(array, sizeof(array)/sizeof(int));
	
	memset((char*)&heap, 0, sizeof(heap));
	int array1[] = {1,2,3,9,7,5,43,55,32,45,68,65,345,54,32,10,11,21,54,87,98,0};
	
	heap_build(array, sizeof(array1)/sizeof(int));
	
	heap_extract_min();
	
	heap_decrease_key(4, -1);
	
	return 1;
}


执行结果如下:






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值