数据结构之优先权队列

一、什么是优先权队列

(一)定义

优先权队列 (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 后7174
插入 2 后27471
插入 72 后2727174
插入54 后254717472
插入 93 后25471747293
插入 52 后2545274729371
插入 28 后228525472937174
执行两次 Remove()525472937174

四、全部代码

#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;
}


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

亦是远方

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值