优先队列 – 数据结构 (二叉堆)
最后更新于:2022-04-01 20:06:08
优先队列包括二叉堆、d-堆、左式堆、斜堆、二项队列等
1、二叉堆
堆是一棵被完全填满的二叉树,有可能例外的是在底层,底层上的元素从左到右填入。这样的树称为完全二叉树。
堆序的性质:在一个堆中,对于每一个节点X,X的父亲的关键字小于(或等于)X中的关键字,根节点除外(它没有父节点)。完全二叉树可以用数组实现。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-17_57b42920c5068.jpg)
//关于二叉堆的头文件定义
如果要插入的元素是新的最小值,那么它将一直被推向堆顶。这样在某一个时刻,i将是1,我们就需要另Insert函数令程序跳出while循环,这个值必须保证小于或者至少等
于堆中的任何值,我们称之为标记。
~~~
#ifndef BITHEAP_H_INCLUDED
#define BITHEAP_H_INCLUDED
#include
#include
typedef int ElementType;
struct HeapStruct;
typedef struct HeapStruct *PriorityQueue;
PriorityQueue BitHeap_Init(int max_elements);
void BitHeap_Insert(ElementType x, PriorityQueue H);
ElementType BitHeap_Delete(PriorityQueue H);
void BitHeap_Show(PriorityQueue H);
int BitHeap_Free(PriorityQueue H);
#endif // BITHEAP_H_INCLUDED
~~~
//二叉堆中的功能函数的定义
~~~
#include "bitheap.h"
struct HeapStruct
{
int Capacity;
int Size;
ElementType *Elements;
};
static void print_err(char *str);
static int IsFull(PriorityQueue H);
static int IsEmpty(PriorityQueue H);
PriorityQueue BitHeap_Init(int max_elements)
{
PriorityQueue H;
H = (PriorityQueue)malloc(sizeof(struct HeapStruct));
if(H == NULL)
print_err("no space for H in BitHeap");
H->Elements = (ElementType *)malloc((max_elements+1) * sizeof(ElementType));
H->Elements[0] = (1<<31);
if(H->Elements == NULL)
print_err("no space for H->Elements in BitHeap");
H->Capacity = max_elements;
H->Size = 0;
return H;
}
void BitHeap_Insert(ElementType x, PriorityQueue H)
{
int i;
if(IsFull(H))
{
printf("the heap is full\n");
return;
}
for(i = ++H->Size; H->Elements[i/2] > x; i /= 2)
H->Elements[i] = H->Elements[i/2];
H->Elements[i] = x;
}
ElementType BitHeap_Delete(PriorityQueue H)
{
ElementType min_val, last_val;
int i, child;
if(IsEmpty(H))
{
printf("the bitheap is empty\n");
return (1<<31);
}
min_val = H->Elements[1];
last_val = H->Elements[H->Size--];
for(i = 1; 2*i < H->Size; i = child)
{
child = 2 * i;
if(child != H->Size && (H->Elements[child+1] < H->Elements[child]))
child++;
if(last_val > H->Elements[child])
H->Elements[i] = H->Elements[child];
else
break;
}
H->Elements[i] = last_val;
return min_val;
}
void BitHeap_Show(PriorityQueue H)
{
int i;
if(H != NULL)
{
for(i = 1; i <= H->Size; i++)
printf("%d ", H->Elements[i]);
}
printf("\n");
}
int BitHeap_Free(PriorityQueue H)
{
if(H != NULL)
{
free(H->Elements);
free(H);
}
return 1;
}
/*
* flowing function is used by function in bitheap.c
*/
static int IsFull(PriorityQueue H)
{
return (H->Size == H->Capacity);
}
static int IsEmpty(PriorityQueue H)
{
return (H->Size == 0);
}
static void print_err(char *str)
{
perror(str);
exit(-1);
}
~~~
//关于二叉堆的测试函数 main.c
~~~
#include
#include
#include "bitheap.h"
int main()
{
PriorityQueue H;
H = BitHeap_Init(15);
BitHeap_Insert(4, H);
BitHeap_Insert(2, H);
BitHeap_Insert(7, H);
BitHeap_Insert(3, H);
BitHeap_Insert(12, H);
BitHeap_Insert(8, H);
BitHeap_Show(H);
BitHeap_Delete(H);
BitHeap_Show(H);
if(BitHeap_Free(H))
printf("\nfree the bitheap is ok.\n");
return 0;
}
~~~
2、d-堆是二叉堆的简单推广,它恰像一个二叉堆,只是所有的节点都有d个儿子(可以说二叉堆是2-堆)
3、优先队列还包括了左式堆、斜堆、二项队列等。
可以参考《数据结构与算法分析-C语言描述》第6章 - 优先队列(堆)
';