数据结构学习之队列

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


数据结构之队列

课程链接:【【强烈推荐】深入浅出数据结构 - 顶尖程序员图文讲解 - UP主翻译校对 (已完结)】 https://www.bilibili.com/video/BV1Fv4y1f7T1/?p=17&share_source=copy_web&vd_source=a380547882bee6e5ecb87e70ac629227
————————————————


一、队列

在这里插入图片描述
队列先进先出,栈先进后出。
栈的插入和弹出都必须从一端进行,称为栈顶。
列表元素的插入必须从队尾进行,元素删除必须从另外一段,即队头进行。

  • 应用场景:多个程序请求同一资源,该资源一次只能服务一个请求

二、实验代码

1.使用数组实现队列

循环数组的概念

使用数组实现列表,会首先一定大小的数组内存,但在执行一系列的入队列出队列操作后,尾部来到了数组的一端,不能再执行插入操作,出现内存浪费。
在这里插入图片描述
考虑采用循环数组,循环数组的索引需要依靠取模求余数运算。
在这里插入图片描述

  • 代码实现
#include<iostream>
using namespace std;

#define N 5
int A[N];
int front = -1;//初始化队头
int rear = -1;//初始化队尾

bool IsEmpty();
bool IsFull();
int Front();//获取队头元素
void InQueue(int x);//插入队列元素
void DeQueue();//删除队列元素
void Print_Queue();

int main()
{
	InQueue(1);
	InQueue(2);
	InQueue(3);
	InQueue(4);
	InQueue(5);
	InQueue(6);//满了
	Print_Queue();//12345
	cout << Front() << endl;//1
	DeQueue();
	DeQueue();
	Print_Queue();//345
	DeQueue();
	DeQueue();
	DeQueue();
	DeQueue();//空队列去删,显示队列为空
	cout << Front() << endl;//显示队列为空,返回NULL
}

bool IsEmpty()
{
	if (front == -1 && rear == -1)
	{
		return true;
	}
	else
	{
		return false;
	}
}
bool IsFull()
{
	if ((rear + 1) % N == front)
	{
		return true;
	}
	else
	{
		return false;
	}
}
int Front()
{
	if (IsEmpty())
	{
		cout << "列表为空,无法读取!!!" << endl;
		return 0;
	}
	return A[front];
}

void InQueue(int x)
{
	if (IsFull())
	{
		cout<<"列表已满,无法加入!!!" << endl;
		return;
	}
	else if (IsEmpty())
	{
		front = 0;
		rear = 0;
	}
	else
	{
		rear = (rear + 1) % N;
	}
	A[rear] = x;
}
void DeQueue()
{
	if (IsEmpty())
	{
		cout<<"列表为空,无法删除!!!" << endl;
		return;
	}
	else if (front == rear)//删除列表元素,此时只剩最后一个,头尾指向的一样
	{
		front = -1;
		rear = -1;
	}
	else
	{
		front = (front + 1) % N;
	}
}
void Print_Queue()
{
	for (int i = front; i != rear; i = (i + 1) % N)
	{
		cout << A[i] << ' ';
	}
	cout << A[rear];
	cout << endl;
}

在这里插入图片描述

2.使用链表实现队列

在这里插入图片描述

  • 需要定义一个front始终指向队头和rear始终指向队尾,删除从队头删除,插入从队尾插入,时间复杂度都是O(1)。如果只有队头或者队尾,在完成删除或者插入的操作时,有一个需要遍历整个队列,那么时间复杂度将是O(n)
  • 相比数组实现,数组实现大小固定,需要扩展时需复制整个数组,或者有未使用的内存造成浪费;而链表实现,除了需要额外的内存来存放下一个节点的地址,但内存利用率更高

代码如下(示例):

#include<iostream>
using namespace std;

struct Node {
	int data;
	struct Node* next;
};

//初始化 全局变量
struct Node* front = NULL;
struct Node* rear = NULL;

void enqueue(int x);
void dequeue();
bool IsEmpty();
int Front();
void print();

int main()
{
	enqueue(1);
	enqueue(2);
	enqueue(3);
	print();//1 2 3
	cout << "队头元素为:" << Front() << endl;
	dequeue();
	dequeue();
	print();//3
	dequeue();
	print();//
	dequeue();//不能删除
}
bool IsEmpty()
{
	if (front == NULL && rear == NULL)
	{
		return true;
	}
	else
	{
		return false;
	}
}
void enqueue(int x)
{
	//创建一个temp指针(在栈区),指向新创建的节点(节点创建在堆区)
	struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
	temp->data = x;
	temp->next = NULL;
	if (IsEmpty())//队列为空
	{
		front = rear = temp;
		return;
	}
	else
	{
		rear->next = temp;
		rear = temp;
	}
}
void dequeue()
{
	//创建一个temp指针(在栈区),指向front指向的节点(节点存储在堆区)
	struct Node* temp = front;
	if (IsEmpty())
	{
		cout << "已经空了  不能删除" << endl; 
		return;
	}
	else if (front == rear)
	{
		front = rear = NULL;
	}
	else
	{
		front = front->next;
	}
	free(temp);//释放被删除的节点
}

int Front()
{
	if (IsEmpty())
	{
		cout << "空队列!!" << endl;
		return NULL;
	}
	else
	{
		return front->data;
	}
}

void print() {
	cout << "队列为:";
	struct Node* temp = front;
	while (temp != NULL) {
		cout << temp->data << ' ';
		temp = temp->next;
	}
	cout << endl;
}

在这里插入图片描述


总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值