优先队列之二叉堆
在操作系统中,调度程序必须决定在什么时候运行哪个进程。一般来说,短的作业是需要尽可能快地完成,也就是说,短的作业应该拥有优先权。这种特殊的应用将由一种特殊的队列来完成,这种数据结构叫做优先队列,属于计算机科学中最讲究的一种。
一、最基本的两种操作
优先队列具备的最基本的两种操作,是插入和删除最小者。插入操作相当于入列,而删除操作相当于出队。只是这里有一些地方是不同的,不像之前出队和入队操作那么简单。
二、二叉堆
一般来说,管二叉堆叫堆,它的应用非常普遍。而堆就是一棵完全二叉树。这种数据结构有一个特点,就是存储它的元素可以用数组来存储,不必动用指针。对于数组中任意一个位置i上面的元素,它的左儿子在位置2i上,右儿子在(2i + 1)上;父节点则在位置(i/2)上。
堆序的另外一个特性,就是每一个节点X,X的父亲中关键字小于或者等于X,根节点例外,因为根节点并没有父节点。
下面是《DSAAC》中对这种数据结构的实现,插入和删除的操作可谓经典:
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
#ifndef _BinHeap_H
#define _BinHeap_H
typedef int ElementType;
struct HeapStruct;
typedef struct HeapStruct *PriorityQueue;
PriorityQueue Initizlize(int MaxElement);
void Destroy(PriorityQueue h);
void Insert(ElementType x, PriorityQueue h);
ElementType DeleteMin(PriorityQueue h);
int IsEmpty(PriorityQueue h);
int IsFull(PriorityQueue h);
#endif
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "binheap.h"
#define MINDATA -1
#define MIN_ELEMENT_SIZE 10
struct HeapStruct
{
int capacity;
int size;
ElementType *element;
};
int IsEmpty(PriorityQueue h)
{
return h->size == 0;
}
int IsFull(PriorityQueue h)
{
return h->size == h->capacity;
}
PriorityQueue Initizlize(int MaxElement)
{
PriorityQueue h;
if (MaxElement < MIN_ELEMENT_SIZE)
{
fprintf(stdout, "the size is too small.\n");
return NULL;
}
h = malloc(sizeof(struct HeapStruct));
if (h == NULL)
{
fprintf(stdout, "failed to create a heap struct.\n");
return NULL;
}
h->element = malloc(sizeof(ElementType) * (MaxElement + 1));
if (h->element == NULL)
{
fprintf(stdout, "failed to create a heap struct.\n");
return NULL;
}
h->capacity = MaxElement;
h->size = 0;
h->element[0] = MINDATA;
return h;
}
void Insert(ElementType x, PriorityQueue h)
{
int i;
if (IsFull(h))
{
fprintf(stdout, "heap is full.\n");
return;
}
for (i = ++h->size; h->element[i] > x; i /= 2)
{
h->element[i] = h->element[i / 2];
}
h->element[i] = x;
}
ElementType DeleteMin(PriorityQueue h)
{
int i, child;
ElementType MinElement, LastElement;
if (IsEmpty(h))
{
fprintf(stdout, "the queue is empty.\n");
return h->element[0];
}
MinElement = h->element[1];
LastElement = h->element[h->size--];
for (i = 1; i * 2 <= h->size; i = child)
{
child = i * 2;
if (child != h->size && (h->element[child+1] < h->element[child]) )
{
child++;
}
if (LastElement > h->element[child])
{
h->element[i] = h->element[child];
}
else
{
break;
}
}
h->element[i] = LastElement;
return MinElement;
}
#define SAFE_FREE(h) {if(h) {free(h); h = NULL;} }
void Destroy(PriorityQueue h)
{
if (h == NULL)
{
fprintf(stdout, "[Destroy]the pointer is NULL.\n");
return;
}
SAFE_FREE(h->element);
SAFE_FREE(h);
}