006——队列

news2024/9/23 5:26:25

队列:

一种受限的线性表(线性逻辑结构),只允许在一段进行添加操作,在另一端只允许进行删除操作,中间位置不可操作,入队的一端被称为队尾,出队的一端被称为队头,在而我们会用两个指针分别用于标记队首和队尾,分别叫做队首指针和队尾指针

 单端队列:

存储结构:

顺序队列

顺序存储,基于数组来存储

两种思路

思路1:r指针指向尾元素的下一个位置

Ⅰ)初始空的队列:f=0,r=0

typedef struct {
	int* data;//数组
	int f, r;//front队首指针  rear队尾指针 
}Squeue;

Squeue InitQueue()
{
	Squeue q;
	q.data = (int*)malloc(sizeof(int) * maxsize);
	if (q.data == NULL)
	{
		printf("空间分配失败\n");
	}
	else {
		q.f = q.r = 0;
	}
	return q;
}

Ⅱ)入队:a[r]=k;r++;//a[r++]=k;

void Enqueue(Squeue* q, int k)
{
	q->data[q->r] = k;
	r++;
}

Ⅲ)出队:f++;

void Dequeue(Squeue* q)
{
	q->f++;
}

Ⅳ)判满:r==maxsize(假溢出)

Ⅴ)判空:f==r

思路2:r指针指向真正的尾元素

Ⅰ)初始空的队列:f=0,r=-1

Squeue InitQueue()
{
	Squeue q;
	q.data = (int*)malloc(sizeof(int) * maxsize);
	if (q.data == NULL)
	{
		printf("空间分配失败\n");
	}
	else {
		q.f = 0;
        q.r = 1;
	}
	return q;
}

Ⅱ)入队:r++;a[r]=k;//a[++r]=k;

void Enqueue(Squeue* q, int k)
{
	r++;
    q->data[q->r] = k;
	
}

Ⅲ)出队:f++;

void Dequeue(Squeue* q)
{
	q->f++;
}

Ⅳ)判满:r==maxsize-1(假溢出)

Ⅴ)判空:f==r+1

如何解决假溢出的问题?

形成循环队列-->取余(思路1相对来说更加方便取余)

Ⅰ)初始空的队列:f=0,r=0

Ⅱ)入队:a[r]=k;r=(r+1)%maxsize;

Ⅲ)出队:f=(f+1)%maxsize;

Ⅳ)判满:

        方法①:牺牲一个存储空间(r+1)%maxsize==f;

        方法②:队满之前的操作一定是入队flag==0操作

                       队空之前的操作一定是出队flag==1操作

        则用一个变量flag来记录此时是入队操作还是出队操作

                        f==r&&flag==0

Ⅴ)判空:f==r

#include<stdio.h>
#include<stdlib.h>
#define maxsize 10
//循环队列
typedef struct {
	int* data;//数组
	int f, r;//front队首指针  rear队尾指针 
}Squeue;
Squeue InitQueue()
{
	Squeue q;
	q.data = (int*)malloc(sizeof(int) * maxsize);
	if (q.data == NULL)
	{
		printf("空间分配失败\n");
	}
	else {
		q.f = q.r = 0;
	}
	return q;
}
void Enqueue(Squeue* q, int k)
{
	if ((q->r + 1) % maxsize == q->f)
	{
		printf("队满,不能入队\n");
		return;
	}
	q->data[q->r] = k;
	q->r = (q->r + 1) % maxsize;

}
void Dequeue(Squeue* q)
{
	if (q->f == q->r)
	{
		printf("队空,不能出队\n");
		return;
	}
	printf("队首%d出队\n", q->data[q->f]);
	q->f = (q->f + 1) % maxsize;
}
int main()
{
	
	return 0;
}

链式队列

#include<stdio.h>
#include<stdlib.h>
#define maxsize 10
//链式队列
typedef struct Qnode {
	int data;
	struct Qnode* next;
}QNode;
typedef struct Queue {
	QNode* f;
	QNode* r;
}LinkQ;

LinkQ InitLinkQ()
{
	LinkQ q;
	q.f = (QNode*)malloc(sizeof(QNode));
	if (q.f == NULL)
	{
		printf("空间分配失败\n");
	}
	else {
		q.f->next = NULL;
		q.r = q.f;
	}
	return q;
}
LinkQ Enqueue(LinkQ q, int k)
{
	QNode* s = (QNode*)malloc(sizeof(QNode));
	if (s == NULL)
	{
		printf("空间分配失败,不能入队\n");
	}
	else {
		s->data = k;
		s->next = NULL;
		q.r->next = s;
		q.r = s;
	}
	return q;

}
LinkQ Dequeue(LinkQ q)
{
	if (q.r == q.f)
	{
		printf("空间分配失败,不能出队\n");
		return q;
	}
	QNode* p = q.f->next;
	q.f->next = p->next;
	if (q.r == p)
	{
		q.r = q.f;
	}
	printf("队首%d出队\n", p->data);
	free(p);
	p = NULL;
}
int main()
{
	return 0;
}

双端队列

双端队列,可以简单理解成将两个队列合在一起,而双端队列的两端分为前端和后端,而在着两端均可以进行出入队操作

存储方式:

顺式存储

前面可以了解到,顺序存储我们是用数组来实现,那这里就会存在一个问题:前端的位置和后端的位置是不固定的,-因为我们不知道前端的位置具体插入多少元素,后端的位置插入多少元素,所以我们采用循环数组来实现存储

这里还有一个需要考虑的问题:到底是先动指针还是先放数据?

①前后端先动指针后放数据

这个时候我们会发现中间会存放一个空数据,所以是不行的

①前后端先放数据后动指针

这个时候我们会发现有的元素数据会被覆盖掉

所以我们需要一端是先移动指针,一段是先放入数据

不过这样的话,其中一个指针指向的是该元素,另一个指针指向的是该元素的下一个位置

代码案例:

#include<stdio.h>
#include<stdlib.h>
#define maxsize 10
int* q=NULL;//指针模拟开数组
int l, r;//左端 右端
int size;//记录双端队列中实际的元素个数


void InitQueue() {
	q = (int*)malloc(sizeof(int) * maxsize);
	if (q == NULL) {
		printf("空间访问失败\n");
		return;
	}
	size = 0;
	l = r = 0;
}

//左端入队
void insert_left(int k) {
	if (size == maxsize) {
		printf("队满,不能入队\n");
		return;
	}
	q[l] = k;
	l = (l - 1 + maxsize) % maxsize;
	size++;
}

//左端出队
void delete_left() {
	if (size == 0) {
		printf("队空,不能出队\n");
		return;
	}
	printf("出队元素为%d", q[(l + 1) % maxsize]);
	l = (l + 1) % maxsize;
	size--;
}

//右端入队
void insert_right(int k) {
	if (size == maxsize) {
		printf("队满,不能入队\n");
		return;
	}
	
	r = (r + 1 ) % maxsize;
	q[r] = k;
	size++;
}

//右端出队
void delete_right() {
	if (size == 0) {
		printf("队空,不能出队\n");
		return;
	}
	printf("出队元素为%d", q[(r - 1 + maxsize) % maxsize]);
	r = (r - 1 + maxsize) % maxsize;
	size--;
}

//打印
void show() {
	int i = (l + 1)%maxsize;
	while (i != r) {
		printf("%d\t", q[i]);
		i = (i + 1) % maxsize;
	}
	printf("%d\n", q[r]);

}

int main() {
	InitQueue();
	insert_left(10);
	insert_left(5);
	insert_right(13);
	insert_right(56);
	show();
}

链式存储

因为双端队列需要往两端去延长,所以如果用链表来实现的话,我们需要用双向链表来去实现。

代码示例

#include<stdio.h>
#include<stdlib.h>
#define maxsize 10 
typedef struct linkQ{
	int data;
	struct linkQ* pre;
	struct linkQ* next;
}Node; 
Node* l=NULL;
Node* r=NULL; 
void initqueue()
{
	l=(Node*)malloc(sizeof(Node));
	if(l==NULL)
	{
		printf("空间分配失败\n");
		return;
	}
	l->next=NULL;
	l->pre=NULL;
	r=l;
}
//左边
void insert_left(int k)
{
	Node* s=(Node*)malloc(sizeof(Node));
	if(s==NULL)
	{
		printf("空间分配失败,不能入队\n");
		return;
	}
	l->data=k;
	s->pre=l->pre;
	l->pre=s;
	s->next=l;
	l=s; 
 } 
void delet_left()
{
	if(l==r)
	{
	printf("队空,不能出队\n");
		return; 	
	}
	int x=l->next->data;
	printf("%d出队\n",x); 
	Node* p=l;
	l=p->next;
	l->pre=p->pre;
	free(p);
	p=NULL;
}
//右边
void insert_right(int k)
{
	Node* s=(Node*)malloc(sizeof(Node));
	if(s==NULL)
	{
		printf("空间分配失败,不能入队\n");
		return;
	}
	s->data=k;
	s->next=r->next;
	s->pre=r;
	r->next=s;
	r=s;
 } 
 void delet_right()
 {
 	if(l==r)
	{
	printf("队空,不能出队\n");
		return; 	
	}
	int x=r->data;
	printf("%d出队\n",x); 
	Node* p=r;
	r=p->pre;
	r->next=p->next;
	free(p);
	p=NULL;
}
void show()
{
	Node* p=l->next;
	while(p!=NULL)
	{
		printf("%d ",p->data);
		p=p->next;
	}
	printf("\n");
}
int main()
{
	initqueue();
	insert_left(1);
	insert_left(2);
	insert_left(3);
    insert_right(4);
    insert_right(8);
    printff();
    delet_left();
	delet_right(); 
	delet_right();
	delet_right();
	 show();
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2156678.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

作业报告┭┮﹏┭┮(Android反调试)

一&#xff1a;Android反调试 主要是用来防止IDA进行附加的&#xff0c;主要的方法思路就是&#xff0c;判断自身是否有父进程&#xff0c;判断是否端口被监听&#xff0c;然后通过调用so文件中的线程进行监视&#xff0c;这个线程开启一般JNI_OnLoad中进行开启的。但是这个是…

Java语言程序设计基础篇_编程练习题**18.31 (替换单词)

目录 题目&#xff1a;**18.31 (替换单词) 习题思路 代码示例 运行结果 替换前 替换后 题目&#xff1a;**18.31 (替换单词) 编写一个程序&#xff0c;递归地用一个新单词替换某个目录下的所有文件中出现的某个单词。从命令行如下传递参数&#xff1a; java Exercise18…

C++标准库双向链表 list 中的insert函数实现。

CPrimer中文版&#xff08;第五版&#xff09;&#xff1a; //运行时错误&#xff1a;迭代器表示要拷贝的范围&#xff0c;不能指向与目的位置相同的容器 slist.insert(slist.begin(),slist.begin(),slist.end()); 如果我们传递给insert一对迭代器&#xff0c;它们不能…

【有啥问啥】深度剖析:大模型AI时代下的推理路径创新应用方法论

深度剖析&#xff1a;大模型AI时代下的推理路径创新应用方法论 随着大规模预训练模型&#xff08;Large Pretrained Models, LPMs&#xff09;和生成式人工智能的迅速发展&#xff0c;AI 在多领域的推理能力大幅提升&#xff0c;尤其是在自然语言处理、计算机视觉和自动决策领…

【C++11】异常处理

目录 一、异常的引入 二、C异常的关键字 三、异常的抛出与处理规则 四、异常缺陷的处理 五、自定义异常体系 六、异常规范 七、异常安全 八、异常的优缺点 1.优点 2.缺点 一、异常的引入 传统的C语言处理异常的方式有两种&#xff1a; 1.终止程序&#xff1a;使用as…

[WMCTF2020]Make PHP Great Again 2.01

又是php代码审计,开始吧. 这不用审吧&#xff0c;啊喂. 意思就是我们要利用require_once()函数和传入的file的value去读取flag的内容.&#xff0c;貌似呢require_once()已经被用过一次了&#xff0c;直接读取还不行&#xff0c;看一下下面的知识点. require_once() require…

Qt 注册表操作

一.操作环境 二.注册表查看 1. 搜索注册表打开 2. 注册表查看 例如我想操作 计算机\HKEY_CURRENT_USER\SOFTWARE\winzq\qwert下的内容 三.代码 1. H文件 #ifndef __REGISTER_H__ #define __REGISTER_H__#include <QString> #include <QSettings> #include <Q…

Web 安全(Web Security)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…

信息安全工程师(11)网络信息安全科技信息获取

一、信息获取的重要性 在网络安全领域&#xff0c;及时、准确地获取科技信息对于防范和应对网络威胁至关重要。这些信息可以帮助安全团队了解最新的攻击手段、漏洞信息、防护技术等&#xff0c;从而制定有效的安全策略和应对措施。 二、信息获取的来源 网络信息安全科技信息的获…

s3c2440各部分应用

一、按位运算 按位与&&#xff1a;清零&#xff0c;清零位&0&#xff1b; 如&#xff1a;0xFFFF &&#xff08; ~&#xff08;1 << 7&#xff09;&#xff09;, 将第7位清零。 按位或 | &#xff1a;置1&#xff0c;置1位 | 1&#xff1b; 如&…

MySQL(七)——事务

文章目录 事务事务的概念事务的ACID特性事务的语法查看存储引擎查看自动提交参数和设置手动事务操作保存点 隔离级别与并发事务问题隔离级别并发事务问题 事务 事务的概念 事务&#xff08;Transaction&#xff09;是数据库管理系统中执行过程中的一个逻辑单位&#xff0c;由…

Rx Strategist:智能体实现处方验证的方方面面,如适应症、剂量、药物相互作用

Rx Strategist&#xff1a;智能体实现处方验证的方方面面&#xff0c;如适应症、剂量、药物相互作用 秒懂大纲提出背景&#xff1a;拆解解法分析全流程分析创意 秒懂大纲 ├── 处方验证系统【主题】 │ ├── 背景和问题【问题描述】 │ │ ├── 现代药物复杂性对严…

Java基础面试题——异常

目录 关系图 1. Throwable和Exception之间的关系 2.异常分为哪两大类 3.常见的 RuntimeException 4. 常见的 Error 5.什么是已检查异常和未检查异常&#xff1f;它们的区别是什么&#xff1f; 6.Java 中如何自定义异常&#xff1f; 7.throw 和 throws 的区别是什么&…

ML 系列:机器学习和深度学习的深层次总结(07)数据预处理—解决缺失值、异常值和错误数据

文章目录 一、说明二、数据预处理三、缺失值四、数据集中可能会出现多种类型的缺失值&#xff1a;五、处理缺失值的方法六、结论 一、说明 在AI数据挖掘中&#xff0c;对原始数据的预处理是必须的技术手段&#xff0c;本篇将对数据预处理的一系列注意事项进行展示。 二、数据…

JavaEE: 深入探索TCP网络编程的奇妙世界(五)

文章目录 TCP核心机制TCP核心机制六: 拥塞控制为什么要有拥塞控制?动态调整的拥塞控制拥塞控制中,窗口大小具体的变化过程 TCP核心机制七: 延时应答TCP核心机制八: 捎带应答 TCP核心机制 前一篇文章 JavaEE: 深入探索TCP网络编程的奇妙世界(四) 书接上文~ TCP核心机制六: 拥…

数据结构:二叉树OJ题(基础版)

前言 更完两期二叉树的知识之后&#xff0c;来做几道oj题巩固一下基础 一、翻转二叉树 链接&#xff1a;leetcode链接 还是分治思想&#xff0c;将问题分解成左子树和右子树交换&#xff0c;遇到空树停止 采用递归算法做题 TreeNode* invertTree(TreeNode* root) {if(root …

2D目标检测常用loss

在2D目标检测任务中&#xff0c;常用的损失函数&#xff08;Loss&#xff09;主要用于优化以下三个关键方面&#xff1a; 类别分类&#xff08;Classification&#xff09;&#xff1a;用于区分检测到的对象属于哪一类。边界框回归&#xff08;Bounding Box Regression&#x…

Spring Boot蜗牛兼职网:全栈开发

第4章 系统设计 4.1 系统体系结构 蜗牛兼职网的结构图4-1所示&#xff1a; 图4-1 系统结构 登录系统结构图&#xff0c;如图4-2所示&#xff1a; 图4-2 登录结构图 蜗牛兼职网结构图&#xff0c;如图4-3所示。 图4-3 蜗牛兼职网结构图 4.2开发流程设计 系统流程的分析是通…

在Web开发中使用和风天气接口

介绍 和风天气是一个提供全球天气预报和气象数据的服务平台&#xff0c;支持多种语言&#xff0c;提供实时天气、未来天气预报、空气质量指数、生活建议等多种气象数据&#xff0c;可以广泛用于网页开发、移动应用和物联网设备等场景。 开发文档&#xff1a;文档 | 和风天气开…

intellij idea 控制台运行java出现中文乱码的解决方法

原因&#xff1a; 字符编码不一致&#xff1a; 当你在intellij idea使用了UTF-8编码&#xff0c;而在控制台使用了其他编码&#xff08;比如gbk&#xff09;&#xff0c;就可能导致乱码。 文件读写编码问题&#xff1a; 如果读取文件时使用的编码与文件实际编码不一致&#xf…