优先级队列

21 篇文章 0 订阅

优先级队列实现

#include <iostream>
#include <Windows.h>
#include <iomanip>

#define MAXSIZE 11

using namespace std;

typedef int DataType;	//队列中的元素类型

typedef struct _QNode {	//节点结构
	DataType data;
	int priority;		//每一个节点的优先级,9最高,0最低,优先级相同取第一个节点
	struct _QNode* next;
}QNode;

typedef QNode* QueuePtr;

typedef struct Queue {	//队列
	int length;		//队列的长度
	QueuePtr front;	//队头指针
	QueuePtr rear;	//队尾指针
}LinkQueue;

void InitQueue(LinkQueue*& LQ) {
	if (!LQ) { return; }

	LQ->length = NULL;				//把长度置为0
	LQ->front = LQ->rear = NULL;	//把对头和队尾指针,同时置为0
}

bool IsEmpty(LinkQueue*& LQ) { //判断队列是否为空
	if (!LQ) { return false; }

	if (LQ->front == NULL) { return true; }

	return false;
}

bool IsFull(LinkQueue*& LQ) { //判断队列是否为满
	if (!LQ) { return false; }

	if (LQ->length > MAXSIZE) { return true; }

	return false;
}

bool EnterQueue(LinkQueue* LQ, DataType data, int priority) { //入队,将元素 data 插入到队列 LQ 中
	if (!LQ) { return false; }
	if (IsFull(LQ)) { cout << "无法插入:" << data << "队列已满!" << endl; return false; }

	QNode* qNode = new QNode;
	qNode->data = data;
	qNode->priority = priority;		//入队的时候要新增一个优先级
	qNode->next = NULL;

	if (IsEmpty(LQ)) { //空列队
		LQ->front = LQ->rear = qNode;
	}
	else {
		//在队尾插入节点 qNode,把新入队的链接到队列中,LQ->reat代表原本的队列,->next,代表原来节点的指针域,指向新插入的队列
		LQ->rear->next = qNode;
		LQ->rear = qNode;		//队尾指向新插入的节点
	}
	LQ->length++;

	return true;
}

//出队,将队列中队头的元素出队,其后的第一个元素成为新的队首
bool DeleteQueue(LinkQueue* LQ, DataType& data) {
	//保存当前已选举的最高优先级节点上一个节点的指针地址
	QNode** prev = NULL, * prev_node = NULL;
	QNode* tmp = NULL, * last = NULL; //遍历队列用的

	if (IsEmpty(LQ)) { cout << "队列为空!!" << endl; return false; }

	prev = &(LQ->front);
	printf("第一个节点的优先级:[%d]\n", (*prev)->priority);
	last = LQ->front; //把第一个节点赋值给last
	tmp = last->next; //把last的下一个节点赋值给tmp

	while (tmp) {
		//第一次循环tmp是第二个节点,(*prev)是第二个节点,以此类推
		if (tmp->priority > (*prev)->priority) {
			printf("抓到一个更大的节点:[%d]\n", tmp->priority);
			prev = &(last->next); //把优先级最高节点的上一个节点赋值给prev
			prev_node = last;
		}
		//这两句是依次循环用的
		last = tmp;
		tmp = tmp->next;
	}
	if (!&data) { return false; }
	data = (*prev)->data;
	tmp = *prev;	//*prev就是需要出队的节点
	//这一句就是跳过被删掉的节点,把前后连接起来,*prev指向的是被删除节点的上一个
	//节点的next,把被删除节点的上一个节点的指针域赋值为,被删除节点的后一个节点
	//右值,只是提供一块修改的内存,不会访问具体的值,左值才会去访问具体的值
	*prev = (*prev)->next;
	delete tmp;

	LQ->length--;
	//还有两种情况需要分别对待
	//1.删除的是首节点,而且队列长度为零
	if (LQ->length == 0) {
		LQ->rear = NULL;
	}
	//2.删除的是尾部节点
	if (prev_node && prev_node->next == NULL) {
		LQ->rear = prev_node;
	}

	return true;
}

void PrintQueue(LinkQueue* LQ) { //打印队列中的元素
	QueuePtr tmp = NULL;

	if (!LQ) { return; }
	if (IsFull(LQ)) { cout << "队列为空!" << endl; return; }

	tmp = LQ->front;
	while (tmp) {
		cout << setw(4) << tmp->data;
		tmp = tmp->next;
	}
	cout << endl;

}

bool GetHead(LinkQueue* LQ, DataType& data) { //获取队首元素 
	if (!LQ || IsEmpty(LQ)) { cout << "队列为空!!" << endl; return false; }
	if (!data) { return false; }

	data = LQ->front->data;

	return true;
}

int getLength(LinkQueue* LQ) { //获取队列中元素的个数 
	if (!LQ || IsEmpty(LQ)) { cout << "队列为空!!" << endl; return 0; }

	return LQ->length;
}

void ClearQueue(LinkQueue* LQ) { //清空队列第一种方式
	if (!LQ) return;

	while (LQ->front) {
		QueuePtr tmp = LQ->front;
		LQ->front = tmp->next;
		cout << "删除:" << tmp->data << "元素成功!" << endl;

		delete tmp;
	}
	LQ->front = LQ->rear = NULL;
	LQ->length = NULL;
}

void ClearQueue1(LinkQueue* LQ) {  //清空队列第二种方式
	if (!LQ) return;
	while (LQ->front) {
		QueuePtr tmp = LQ->front->next;
		delete LQ->front;
		LQ->front = tmp;
	}
	LQ->front = LQ->rear = NULL;
	LQ->length = 0;
}
int main(void) {
	LinkQueue* LQ = new LinkQueue;
	DataType data = -1;

	//初始化队列 
	InitQueue(LQ);

	//入队 
	for (int i = 0; i < 5; i++) {
		EnterQueue(LQ, i + 10, i);
	}
	//打印队列中的元素 
	printf("队列中的元素(总共%d 个):", getLength(LQ)); PrintQueue(LQ); 
	cout<<endl; 
	//出队 
	for(int i=0; i<5; i++){ 
		if(DeleteQueue(LQ, data)){ 
			cout<<"出队的元素是:"<<data<<endl; 
		}else { 
			cout<<"出队失败!"<<endl;
		} 
	}
	//打印队列中的元素 
	printf("出队五个元素后,队列中剩下的元素[%d]:\n", getLength(LQ)); 
	PrintQueue(LQ); 
	cout<<endl; 

	ClearQueue(LQ); 
	cout<<"清空队列!\n"; 
	PrintQueue(LQ);

	//清理资源 
	delete LQ;

	system("pause");
	return NULL;
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值