文章目录
一、什么是优先权队列
(一)定义
优先权队列 (priority queue) 是 0 个或多个元素的集合,每个元素都有一个优先权或值。
普通队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。
在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。通常采用 堆 数据结构来实现优先权队列。
在实际应用中,如 果 值越小, 优先 级 越 高,则 使用最 小 堆即可,否则使用最大堆。
根据最小堆的定义, 堆顶元素是堆中具有最小值的元素,在 最 小 堆的顺序存储结构中, 堆顶
元素处于顺序表的第一个元素位置。因此,从优先权队列中删除最高优先级的元素(即堆顶元素)的操作是容易实现的 ,只需取出和删除堆顶元素即可 。但删除堆顶元素后,必须将堆中剩余元素重新调整成堆。同样,当有新元素插入队列时 ,也必须 重新调整,使之成 为最小堆。
(二)优先权队列结构体
typedef struct priorityQueue
{
ElemType* elements;
int n;
int maxSize;
}PriorityQueue;
(三)优先权队列存储结构

(四)向上调整运算详解
在 Insert() 运笋中,新元素 x 加入优先权队列时, 该元素首先被存储干堆底元素(堆中的最后一个元素)的下一个单元。由于在原先符合最小堆的序列尾部添加了 一个元素,很 可能使得新的序列不再满足最小堆要求,因此需要对新增加的尾部元素执行向上调整运算 AdjustUp。
v o i d A d j u s t U p ( E l e m t y p e h e a p [ ] , i n t c u r r e n t ) void \ AdjustUp(Elemtype \ heap[], \ int \ current) void AdjustUp(Elemtype heap[], int current)
(五)向上调整算法实例

二、优先权队列的实现
(一)创建优先权队列
// 创建最大存储容量为 maxSize 空的优先权队列结构体
void CreatePQ(PriorityQueue* pqueue, int maxSize)
{
pqueue->elements = (ElemType*)malloc(sizeof(ElemType) * maxSize);
if (!pqueue->elements)
return Error;
pqueue->maxSize = maxSize;
pqueue->n = 0;
}
(二)销毁优先权队列
// 销毁优先权队列
void DestoryPQ(PriorityQueue* pqueue)
{
free(pqueue->elements);
pqueue->n = 0;
pqueue->maxSize = 0;
}
(三)判断队列是否为空
// 判断是否为空
int IsEmpty(PriorityQueue* pqueue)
{
return pqueue->n == 0 ? True : False;
}
(四)判断队列是否为满
// 判断是否为满
int IsFull(PriorityQueue* pqueue)
{
return pqueue->n == pqueue->maxSize ? True : False;
}
(五) 返回队列的元素个数
// 返回队列的元素个数
int Size(PriorityQueue* pqueue)
{
return pqueue->n;
}
(六)向优先权队列中插入元素
// 向优先权队列中插入元素
void Insert(PriorityQueue* pqueue, ElemType x)
{
if (IsFull(pqueue))
return Error;
pqueue->elements[pqueue->n] = x;
pqueue->n++;
AdjustUp(pqueue->elements, pqueue->n - 1);
}
(七)取出优先权最高的元素
// 取出优先权队列中优先权最高的元素,以 x 返回,并且在队列中删除它
void Remove(PriorityQueue* pqueue, ElemType* x)
{
if (IsEmpty(pqueue) || IsFull(pqueue))
return Error;
*x = pqueue->elements[0];
pqueue->n--;
pqueue->elements[0] = pqueue->elements[pqueue->n];
AdjustDown(pqueue->elements, 0, pqueue->n - 1);
}
(八)向上调整算法
// 向上调整算法
void AdjustUp(ElemType heap[], int current)
{
int p = current;
ElemType temp;
while (p > 0)
{
if (heap[p] < heap[(p - 1) / 2])
{
temp = heap[p];
heap[p] = heap[(p - 1) / 2];
heap[(p - 1) / 2] = temp;
p = (p - 1) / 2;
}
else
{
break;
}
}
}
(九)向下调整算法
void AdjustDown(ElemType heap[], int current, int border)
{
int p = current;
int minChild;
ElemType temp;
// p 不是叶子结点 说明 p 结点 有左孩子 或者 有左孩子且有右孩子
while (2 * p + 1 <= border)
{
// 如果右孩子存在 且 左孩子大于右孩子
if ((2 * p + 2 <= border) && heap[2 * p + 1] > heap[2 * p + 2])
{
minChild = 2 * p + 2;
}
else // 不存在右孩子 或 左孩子小于右孩子
{
minChild = 2 * p + 1;
}
if (heap[p] <= heap[minChild])
break;
else
{
// 交换变量的值
temp = heap[p];
heap[p] = heap[minChild];
heap[minChild] = temp;
p = minChild;
}
}
}
(十)打印队列
void PrintPQ(PriorityQueue* pqueue)
{
for (int i = 0; i < pqueue->n; i++)
{
printf("%d ", pqueue->elements[i]);
}
printf("\n");
}
三、创建优先权队列实例
创建一个空的优先权队列,依次插入以下元素
{
71
,
74
,
2
,
72
,
54
,
93
,
52
,
28
}
\{71, 74, 2, 72, 54, 93, 52, 28 \}
{71,74,2,72,54,93,52,28}
有:
| 步骤 | 优先权队列的状态 | |||||||
| 插入 71 后 | 71 | |||||||
| 插入 74 后 | 71 | 74 | ||||||
| 插入 2 后 | 2 | 74 | 71 | |||||
| 插入 72 后 | 2 | 72 | 71 | 74 | ||||
| 插入54 后 | 2 | 54 | 71 | 74 | 72 | |||
| 插入 93 后 | 2 | 54 | 71 | 74 | 72 | 93 | ||
| 插入 52 后 | 2 | 54 | 52 | 74 | 72 | 93 | 71 | |
| 插入 28 后 | 2 | 28 | 52 | 54 | 72 | 93 | 71 | 74 |
| 执行两次 Remove() | 52 | 54 | 72 | 93 | 71 | 74 | ||
四、全部代码
#include <stdio.h>
#define ElemType int
#define Error -1
#define True 1
#define False 0
#define MaxSize 10
typedef struct priorityQueue
{
ElemType* elements;
int n;
int maxSize;
}PriorityQueue;
void CreatePQ(PriorityQueue* pqueue, int maxSize); // 创建最大存储容量为 maxSize 空的优先权队列结构体
void DestoryPQ(PriorityQueue* pqueue); // 销毁优先权队列
int IsEmpty(PriorityQueue* pqueue); // 判断是否为空
int IsFull(PriorityQueue* pqueue); // 判断是否为满
void Insert(PriorityQueue* pqueue, ElemType x); // 向优先权队列中插入元素
void Remove(PriorityQueue* pqueue, ElemType* x); // 取出优先权队列中优先权最高的元素,以 x 返回,并且在队列中删除它
void AdjustUp(ElemType heap[], int current); // 向上调整算法
void AdjustDown(ElemType heap[], int current, int border); // 向下调整算法
// 创建最大存储容量为 maxSize 空的优先权队列结构体
void CreatePQ(PriorityQueue* pqueue, int maxSize)
{
pqueue->elements = (ElemType*)malloc(sizeof(ElemType) * maxSize);
if (!pqueue->elements)
return Error;
pqueue->maxSize = maxSize;
pqueue->n = 0;
}
// 销毁优先权队列
void DestoryPQ(PriorityQueue* pqueue)
{
free(pqueue->elements);
pqueue->n = 0;
pqueue->maxSize = 0;
}
// 判断是否为空
int IsEmpty(PriorityQueue* pqueue)
{
return pqueue->n == 0 ? True : False;
}
// 判断是否为满
int IsFull(PriorityQueue* pqueue)
{
return pqueue->n == pqueue->maxSize ? True : False;
}
// 返回队列的元素个数
int Size(PriorityQueue* pqueue)
{
return pqueue->n;
}
// 向优先权队列中插入元素
void Insert(PriorityQueue* pqueue, ElemType x)
{
if (IsFull(pqueue))
return Error;
pqueue->elements[pqueue->n] = x;
pqueue->n++;
AdjustUp(pqueue->elements, pqueue->n - 1);
}
// 取出优先权队列中优先权最高的元素,以 x 返回,并且在队列中删除它
void Remove(PriorityQueue* pqueue, ElemType* x)
{
if (IsEmpty(pqueue) || IsFull(pqueue))
return Error;
*x = pqueue->elements[0];
pqueue->n--;
pqueue->elements[0] = pqueue->elements[pqueue->n];
AdjustDown(pqueue->elements, 0, pqueue->n - 1);
}
// 向上调整算法
void AdjustUp(ElemType heap[], int current)
{
int p = current;
ElemType temp;
while (p > 0)
{
if (heap[p] < heap[(p - 1) / 2])
{
temp = heap[p];
heap[p] = heap[(p - 1) / 2];
heap[(p - 1) / 2] = temp;
p = (p - 1) / 2;
}
else
{
break;
}
}
}
void AdjustDown(ElemType heap[], int current, int border)
{
int p = current;
int minChild;
ElemType temp;
// p 不是叶子结点 说明 p 结点 有左孩子 或者 有左孩子且有右孩子
while (2 * p + 1 <= border)
{
// 如果右孩子存在 且 左孩子大于右孩子
if ((2 * p + 2 <= border) && heap[2 * p + 1] > heap[2 * p + 2])
{
minChild = 2 * p + 2;
}
else // 不存在右孩子 或 左孩子小于右孩子
{
minChild = 2 * p + 1;
}
if (heap[p] <= heap[minChild])
break;
else
{
// 交换变量的值
temp = heap[p];
heap[p] = heap[minChild];
heap[minChild] = temp;
p = minChild;
}
}
}
void PrintPQ(PriorityQueue* pqueue)
{
for (int i = 0; i < pqueue->n; i++)
{
printf("%d ", pqueue->elements[i]);
}
printf("\n");
}
int main()
{
PriorityQueue* pqueue = malloc(sizeof(PriorityQueue));
CreatePQ(pqueue, MaxSize);
Insert(pqueue, 71);
PrintPQ(pqueue);
Insert(pqueue, 74);
PrintPQ(pqueue);
Insert(pqueue, 2);
PrintPQ(pqueue);
Insert(pqueue, 72);
PrintPQ(pqueue);
return 0;
}
141

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



