队列学习-优先队列

队列学习-优先队列

1.优先队列定义

#define MAXSIZE 11			//队列的最大容量

typedef int DataType;		//int的别名(队列中的元素类型)

//单链表(结点结构)
typedef struct _QNode {
	//每个节点的优先级,0最低优先级(自定义,可更改),9最高优先级(自定义,可更改),优先级相同,取第一个节点
	int priority;			
	DataType data;			//数据域(相当于 int data)
	struct _QNode *next;	//指针域
}QNode;

typedef QNode *QueuePtr;	//QNode的指针变量(QNode * 的别名)

//队列
typedef struct Queue {
	int length;				//队列的长度
	QueuePtr front;			//队头指针(相当于  QNode *front)
	QueuePtr rear;			//队尾指针(相当于  QNode *rear)
}LinkQueue;

2.优先队列初始化

//队列初始化,将队列初始化为空队列
void InitQueue(LinkQueue *LQ) {
	if (!LQ) return;

	LQ->length = 0;
	LQ->front = LQ->rear = NULL;	//打队头和队尾指针同时置零
}

3.判断优先队列为空

//判断队列为空
int IsEmpty(LinkQueue *LQ) {
	if (!LQ) return 0;

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

4.判断优先队列是否为满

//判断队列是否为满
int IsFull(LinkQueue *LQ) {
	if (!LQ) return 0;

	if (LQ->length == MAXSIZE) {
		return 1;
	}
	return 0;
}

5.入队

//入队,将元素data插入到队列LQ中
int EnterQueue(LinkQueue *LQ, DataType data, int priority) {
	if (!LQ) return 0;

	if (IsFull(LQ)) {
		cout << "无法插入元素" << data << ",队列已满!" << endl;
		return 0;
	}

	QNode *qNode = new QNode;
	qNode->data = data;
	qNode->priority = priority;		//优先级
	qNode->next = NULL;

	if (IsEmpty(LQ)) {	//空队列
		LQ->front = LQ->rear = qNode;
	}
	else {
		LQ->rear->next = qNode;			//在队尾插入节点qNode
		LQ->rear = qNode;				//队尾指向新插入的节点
	}
	LQ->length++;
	return 1;
}

6.出队

//出队, 遍历队列,找到队列中优先级最高的元素data出队
int DeleteQueue(LinkQueue *LQ, DataType *data) {
	QNode **prev = NULL, *prev_node = NULL;//保存当前已选举的最高优先级节点上一个节点的指针地址
	QNode *tmp = NULL, *last = NULL;

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

	if (!data) return 0;

	//prev 指向队头front 指针的地址
	prev = &(LQ->front);
	printf_s("prve:0x%p LQ->front: 0x%p\n", &(*prev), &(LQ->front));
	printf_s("第一个节点的优先级: %d\n", (*prev)->priority);
	last = LQ->front;		//last 指向第一个节点
	tmp = last->next;		//tmp 指向 last的下一个节点
	while (tmp) {
		if (tmp->priority > (*prev)->priority) {
			printf_s("抓到个更大优先级的节点[priority: %d]\n", tmp->priority);
			prev = &(last->next);
			prev_node = last;	//将last赋值给prev_node(用来给删除尾结点的情况使用)
		}
		last = tmp;			//将tmp 的指向节点赋值给last
		tmp = tmp->next;	//tmp赋值为下一个tmp节点
	}

	*data = (*prev)->data;	//将优先级最高的出列
	tmp = *prev;			//将需要出列的空间赋值给 tmp 释放资源
	*prev = (*prev)->next;	//将prev 下一个节点指向的节点赋值给当前节点prev
	delete tmp;				//将出列后的空间释放

	LQ->length--;			//队列长度减一

	//接下来存在2种情况需要分别对待
	//1. 删除的是首节点,而且队列长度为零
	if (LQ->length == 0) {
		LQ->rear = NULL;
	}

	//2. 如果删除的是尾部节点
	if (prev_node && prev_node->next == NULL) {
		LQ->rear = prev_node;	//将 rear 赋值成 prev_node(保存的删除结点的上一个节点)
	}

	return 1;

}

7.打印队列中的各元素

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

	if (!LQ) return;

	if (LQ->front == NULL) {
		cout << "队列为空!\n";
		return;
	}

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

8.获取队首元素,不出队

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

	if (!data) return 0;

	*data = LQ->front->data;
	return 1;
}

9.清空队列

//清空队列
void ClearQueue(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;
}

10.优先队列定义

//获取队列中元素的个数
int getLength(LinkQueue *LQ) {
	if (!LQ) return 0;

	return LQ->length;
}

11.测试代码

int main(void) {
	LinkQueue *LQ = new LinkQueue;
	DataType data = -1;

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

	//入队
	for (int i = 0; i < MAXSIZE; i++) {
		EnterQueue(LQ, i+10, i);
	}

	//打印队列中的元素
	cout << "队列中的元素(总共" << getLength(LQ) << "个): " << endl;
	PrintQueue(LQ);
	cout << endl;

	//出队
	for (int i = 0; i < MAXSIZE; i++) {
		if (DeleteQueue(LQ, &data)) {
			cout << "出队的元素是: " << data << endl;
		}
		else {
			cout << "出队失败!" << endl;
		}
	}

	//打印队列中的剩下元素
	cout << "出队一个元素后, 队列中的剩下的元素[" << getLength(LQ) << "]: " << endl;
	PrintQueue(LQ);
	cout << endl;

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

	//清理资源
	delete LQ;

	system("pause");
	return 0;
}

12.运行结果

在这里插入图片描述
在这里插入图片描述

12.完整代码

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

using namespace std;

#define MAXSIZE 11			//队列的最大容量

typedef int DataType;		//int的别名(队列中的元素类型)

//单链表(结点结构)
typedef struct _QNode {
	//每个节点的优先级,0最低优先级(自定义,可更改),9最高优先级(自定义,可更改),优先级相同,取第一个节点
	int priority;			
	DataType data;			//数据域(相当于 int data)
	struct _QNode *next;	//指针域
}QNode;

typedef QNode *QueuePtr;	//QNode的指针变量(QNode * 的别名)

//队列
typedef struct Queue {
	int length;				//队列的长度
	QueuePtr front;			//队头指针(相当于  QNode *front)
	QueuePtr rear;			//队尾指针(相当于  QNode *rear)
}LinkQueue;

//队列初始化,将队列初始化为空队列
void InitQueue(LinkQueue *LQ) {
	if (!LQ) return;

	LQ->length = 0;
	LQ->front = LQ->rear = NULL;	//打队头和队尾指针同时置零
}

//判断队列为空
int IsEmpty(LinkQueue *LQ) {
	if (!LQ) return 0;

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

//判断队列是否为满
int IsFull(LinkQueue *LQ) {
	if (!LQ) return 0;

	if (LQ->length == MAXSIZE) {
		return 1;
	}
	return 0;
}


//入队,将元素data插入到队列LQ中
int EnterQueue(LinkQueue *LQ, DataType data, int priority) {
	if (!LQ) return 0;

	if (IsFull(LQ)) {
		cout << "无法插入元素" << data << ",队列已满!" << endl;
		return 0;
	}

	QNode *qNode = new QNode;
	qNode->data = data;
	qNode->priority = priority;		//优先级
	qNode->next = NULL;

	if (IsEmpty(LQ)) {	//空队列
		LQ->front = LQ->rear = qNode;
	}
	else {
		LQ->rear->next = qNode;			//在队尾插入节点qNode
		LQ->rear = qNode;				//队尾指向新插入的节点
	}
	LQ->length++;
	return 1;
}

//出队, 遍历队列,找到队列中优先级最高的元素data出队
int DeleteQueue(LinkQueue *LQ, DataType *data) {
	QNode **prev = NULL, *prev_node = NULL;//保存当前已选举的最高优先级节点上一个节点的指针地址
	QNode *tmp = NULL, *last = NULL;

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

	if (!data) return 0;

	//prev 指向队头front 指针的地址
	prev = &(LQ->front);
	printf_s("prve:0x%p LQ->front: 0x%p\n", &(*prev), &(LQ->front));
	printf_s("第一个节点的优先级: %d\n", (*prev)->priority);
	last = LQ->front;		//last 指向第一个节点
	tmp = last->next;		//tmp 指向 last的下一个节点
	while (tmp) {
		if (tmp->priority > (*prev)->priority) {
			printf_s("抓到个更大优先级的节点[priority: %d]\n", tmp->priority);
			prev = &(last->next);
			prev_node = last;	//将last赋值给prev_node(用来给删除尾结点的情况使用)
		}
		last = tmp;			//将tmp 的指向节点赋值给last
		tmp = tmp->next;	//tmp赋值为下一个tmp节点
	}

	*data = (*prev)->data;	//将优先级最高的出列
	tmp = *prev;			//将需要出列的空间赋值给 tmp 释放资源
	*prev = (*prev)->next;	//将prev 下一个节点指向的节点赋值给当前节点prev
	delete tmp;				//将出列后的空间释放

	LQ->length--;			//队列长度减一

	//接下来存在2种情况需要分别对待
	//1. 删除的是首节点,而且队列长度为零
	if (LQ->length == 0) {
		LQ->rear = NULL;
	}

	//2. 如果删除的是尾部节点
	if (prev_node && prev_node->next == NULL) {
		LQ->rear = prev_node;	//将 rear 赋值成 prev_node(保存的删除结点的上一个节点)
	}

	return 1;

}

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

	if (!LQ) return;

	if (LQ->front == NULL) {
		cout << "队列为空!\n";
		return;
	}

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

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

	if (!data) return 0;

	*data = LQ->front->data;
	return 1;
}

//清空队列
void ClearQueue(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 getLength(LinkQueue *LQ) {
	if (!LQ) return 0;

	return LQ->length;
}


int main(void) {
	LinkQueue *LQ = new LinkQueue;
	DataType data = -1;

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

	//入队
	for (int i = 0; i < MAXSIZE; i++) {
		EnterQueue(LQ, i+10, i);
	}

	//打印队列中的元素
	cout << "队列中的元素(总共" << getLength(LQ) << "个): " << endl;
	PrintQueue(LQ);
	cout << endl;

	//出队
	for (int i = 0; i < MAXSIZE; i++) {
		if (DeleteQueue(LQ, &data)) {
			cout << "出队的元素是: " << data << endl;
		}
		else {
			cout << "出队失败!" << endl;
		}
	}

	//打印队列中的剩下元素
	cout << "出队一个元素后, 队列中的剩下的元素[" << getLength(LQ) << "]: " << endl;
	PrintQueue(LQ);
	cout << endl;

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

	//清理资源
	delete LQ;

	system("pause");
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值