在操作系统中,调度程序必须决定在什么时候运行哪个进程。一般来说,短的作业是需要尽可能快地完成,也就是说,短的作业应该拥有优先权。这种特殊的应用将由一种特殊的队列来完成,这种数据结构叫做优先队列,属于计算机科学中最讲究的一种。
一、最基本的两种操作
优先队列具备的最基本的两种操作,是插入和删除最小者。插入操作相当于入列,而删除操作相当于出队。只是这里有一些地方是不同的,不像之前出队和入队操作那么简单。
二、二叉堆
一般来说,管二叉堆叫堆,它的应用非常普遍。而堆就是一棵完全二叉树。这种数据结构有一个特点,就是存储它的元素可以用数组来存储,不必动用指针。对于数组中任意一个位置i上面的元素,它的左儿子在位置2i上,右儿子在(2i + 1)上;父节点则在位置(i/2)上。
堆序的另外一个特性,就是每一个节点X,X的父亲中关键字小于或者等于X,根节点例外,因为根节点并没有父节点。
下面是《DSAAC》中对这种数据结构的实现,插入和删除的操作可谓经典:
代码
#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
#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
代码
#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);
}
#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);
}