数据结构3:队列

134 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第9天,点击查看活动详情

基础知识

  • 队列
    • 定义:队列(Queue)是限定仅在表头进行删除操作、在表尾进行插入操作的线性表(先进先出)。进行插入操作的端称为队尾,进行删除操作的端称为队头。
    • 存储结构:顺序存储结构(数组实现)和链式存储结构(链表实现)
    • 应用:在计算机组成中,队列应用于CPU的作业调度等;在数据处理中,队列应用于数据遍历等。
    • 存储形式:顺序存储、链式存储
    • 常见的操作:入队、出队、计算节点数量、...

在这里插入图片描述

  • 链队
    • 链队是采用链式存储结构实现的“队列“,它是一种数据存储结构,可以通过单链表的方式来实现

使用链式栈的优点在于它能够克服用数组实现的顺序队列空间利用率不高的特点,但是需要为每个队列元素分配额外的指针空间用来存放指针域。

在这里插入图片描述

题目

队列的链式存储结构

队列的链式存储结构的实现

(1)用随机函数生成10个3位整数(100~999),把这些整数应用入队操作存于队列中;

(2)应用遍历操作输出队列的内容;

(3)把队列的内容翻转,应用出队操作输出队列的内容。

思路

① 通过定义一个class类 QueueNode,表示链表的结点;

② 通过定义一个class类 LinkQueue,表示各种链表,封装了对链表的各种操作:

③ 具体实现操作在main()函数中调用执行

代码

#include <iostream>
#include <ctime>
using namespace std;

class QueueNode
{
public:
	QueueNode() :data(-1), next(NULL) {}
	QueueNode(int m_data, QueueNode *m_next = NULL) :data(m_data), next(m_next) {}
	~QueueNode() { next = NULL; }
public:
	int data;
	QueueNode *next;
};

class LinkQueue
{
public:
	LinkQueue()
	{
		len = 0;
		font = rear = new QueueNode();  //队头队尾结点指向新的头结点,头结点的指针域置空
	}
	~LinkQueue()
	{
		QueueEmpty();
		//delete font;
		//delete rear;
	}
	void QueueEmpty();  //队列清空
	void EnQueue(int m_data);  //入队
	int DeQueue();  //出队  //注意盘对队列是否为空,且判断出队元素是否最后一个元素(若是,队尾指针重新赋值,指向头结点)
	void QueueTraverse();  //遍历
	void rollback();  //翻转
public:
	QueueNode* font;
	QueueNode* rear;
	int len;
};

void LinkQueue::QueueEmpty()
{
	if (font == rear)
	{
		delete font;
	}
	else
	{
		while (font->next != NULL)
		{
			QueueNode* tmp = font->next;
			delete font;
			font = tmp;
		}
		//delete font;
	}
}

void LinkQueue::EnQueue(int m_data)   //入队 
{
	QueueNode* p_new = new QueueNode(m_data);
	p_new->next = NULL;
	rear->next = p_new;  //队尾元素的next指向新结点
	rear = p_new;  //队尾指针指向新结点
	len++;
	cout << "整数" << m_data << "入队成功!" << endl;

	QueueTraverse();
}

int LinkQueue::DeQueue()   //出队
{
	if (font == rear) {  //队空
		cout << "链队为空,无法执行出队操作!" << endl;
		return -1;
	}
	else
	{
		QueueNode* tmp = font->next;
		int e = tmp->data;
		font->next = tmp->next;  //修改头指针的next
		if (rear == tmp) {
			rear = font;  //当队列只剩一个元素时,如果直接出栈,会导致队尾指针丢失,应将队尾指针赋值为队头指针
		}
		delete tmp;
		len--;
		cout << "整数" << e << "出队成功!" << endl;
		if (len > 0) QueueTraverse();
		return e;
	}
}

void LinkQueue::QueueTraverse()
{
	QueueNode* p = font;
	if (p->next != NULL)
	{
		cout << "链队元素:Start->";
		while (p->next != NULL)
		{
			p = p->next;
			cout << p->data << "->";
		}
		cout << "End" << endl;
	}
	else cout << "链队为空!" << endl;
}

void LinkQueue::rollback()
{
	QueueNode* pos1 = font->next;  //pos1指向第一个元素
	int i = 1;
	while (i <= len - i)
	{
		QueueNode* pos2 = pos1;
		int t = i;
		while (t <= len - i && pos2 != NULL)  //指针移动到对应位置
		{
			pos2 = pos2->next;
			t++;
		}
		int tmp = pos2->data;
		pos2->data = pos1->data;
		pos1->data = tmp;
		i++;
		pos1 = pos1->next;
	}
	cout << "队链翻转成功!" << endl;
	QueueTraverse();
}

int main()
{
	time_t t;  //随机种子由时间确定
	srand((unsigned)time(&t));
	LinkQueue Slist;  //定义一个单链表
	for (int i = 1; i <= 10; i++)  //生成10个随机整数存入链表
	{
		Slist.EnQueue(rand() % 900 + 100);  //插入到位置i100-999随机整数
	}
	cout <<'\n'<< "是否执行出队操作(不执行(0):执行(1)):";
	int flag;
	cin >> flag;

	if (flag != 0)
	{
		cout << "请输入要出队的个数:";
		int popNum;
		cin >> popNum;

		if (popNum > Slist.len)
		{
			cout << "数量超出队列的长度,全部元素出队!" << endl;
		}
		else
		{
			for (int i = 0; i < popNum; ++i)
			{
				Slist.DeQueue();
			}
		}
	}
	else cout << "不执行出队操作!" << endl;
	cout << endl;
	cout << "链队遍历..." << endl;
	Slist.QueueTraverse();
	cout << endl;
	cout << "队链翻转..."<<endl;
	Slist.rollback();
}

结果

在这里插入图片描述