二叉堆在结构上类似完全二叉树,除最低层外,是被完全填满的,低层的元素从左向右填入。
依据上面的性质,一颗高度为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;
}
本文介绍二叉堆的结构与性质,探讨其在数据结构中的应用,特别是作为优先级队列的基础。文中详细解释了二叉堆的常见操作,如插入、删除最小元素等,并提供了C语言实现示例。
1392

被折叠的 条评论
为什么被折叠?



