数据结构——顺序队列与链式队列的实现

news2024/11/18 19:57:48

目录

一、概念

1、队列的定义

2、队首

3、队尾

二、接口

1、可写接口

1)数据入队

2)数据出队

3)清空队列

2、只读接口

1)获取队首数据

2)获取队列元素个数

3)队列的判空

三、队列的顺序表实现

1、数据结构定义

2、初始化创造队列

3、判断队列是否满

4、判断队列是否空

5、入队

6、出队

7、打印队列

8、队列的顺序表实现源码

四、队列的链表实现

1、数据结构定义

2、初始化创造队列

3、判断队列是否空

4、入队

5、出队

6、打印队列

7、队列的链表实现源码


一、概念

1、队列的定义

  队列 是仅限在 一端 进行 插入另一端 进行 删除 的 线性表
  队列 又被称为 先进先出 (First In First Out) 的线性表,简称 FIFO 。

2、队首

  允许进行元素删除的一端称为 队首。如下图所示:

3、队尾

  允许进行元素插入的一端称为 队尾。如下图所示:

二、接口

1、可写接口

1)数据入队

  队列的插入操作,叫做 入队。它是将 数据元素 从 队尾 进行插入的过程,如图所示,表示的是 插入 两个数据(绿色 和 蓝色)的过程:

2)数据出队

  队列的删除操作,叫做 出队。它是将 队首 元素进行删除的过程,如图所示,表示的是 依次 删除 两个数据(红色 和 橙色)的过程:

3)清空队列

  队列的清空操作,就是一直 出队,直到队列为空的过程,当 队首 和 队尾 重合时,就代表队尾为空了,如图所示:

2、只读接口

1)获取队首数据

  对于一个队列来说只能获取 队首 数据,一般不支持获取 其它数据。

2)获取队列元素个数

  队列元素个数一般用一个额外变量存储,入队 时加一,出队 时减一。这样获取队列元素的时候就不需要遍历整个队列。通过 O(1) 的时间复杂度获取队列元素个数。

3)队列的判空

  当队列元素个数为零时,就是一个 空队空队 不允许 出队 操作。

三、队列的顺序表实现

1、数据结构定义

对于顺序表,在 C语言 中表现为 数组,在进行 队列的定义 之前,我们需要考虑以下几个点:
  1)队列数据的存储方式,以及队列数据的数据类型;
  2)队列的大小;
  3)队首指针;
  4)队尾指针;

我们可以定义一个 队列 的 结构体,C语言实现如下所示:

#define MAXSIZE 10
typedef int datatype;

typedef struct seqqueue{
	datatype data[MAXSIZE];
	int front,rear;
}seq_queue,*seq_pqueue;

2、初始化创造队列

第一种无形参,C语言实现如下所示:

seq_pqueue init1_seqqueue(void)
{
	seq_pqueue q;
	q=(seq_pqueue)malloc(sizeof(seq_queue));
	if(q==NULL)
	{
		perror("malloc");
		exit(-1);
	}
	q->front=q->rear=MAXSIZE-1;

	return q;
}

第二种有形参,C语言实现如下所示:

void init_seqqueue(seq_pqueue *Q)
{
	*Q=(seq_pqueue)malloc(sizeof(seq_queue));
	if((*Q)==NULL)
	{
		perror("malloc");
		exit(-1);
	}
	(*Q)->front=(*Q)->rear=MAXSIZE-1;
	
	return;
}

3、判断队列是否满

C语言实现如下所示:

bool is_full_seqqueue(seq_pqueue q)
{
	if((q->rear+1)%MAXSIZE == q->front)
		return true;
	else
		return false;
}

4、判断队列是否空

C语言实现如下所示:

bool is_empty_seqqueue(seq_pqueue q)
{
	if(q->rear == q->front)
		return true;
	else
		return false;
}

5、入队

C语言实现如下所示:

bool in_seqqueue(datatype data,seq_pqueue q)
{
	//判断队列是否满
	if(is_full_seqqueue(q)){
		printf("队列已满!\n");
		return false;
	}

	//入队
	q->rear=(q->rear+1)%MAXSIZE;
	q->data[q->rear]=data;
	return true;
}

6、出队

C语言实现如下所示:

bool out_seqqueue(seq_pqueue q,datatype *D)
{
	//判断队列是否空
	if(is_empty_seqqueue(q)){
		printf("队列已空!\n");
		return false;
	}

	//出队
	q->front=(q->front+1)%MAXSIZE;
	*D=q->data[q->front];

	return true;
}

7、打印队列

C语言实现如下所示:

void show_seqqueue(seq_pqueue q)
{
	int i;
	if(is_empty_seqqueue(q))
		return;
	//非空时,从对头打印到队尾
	for(i=(q->front+1)%MAXSIZE;i!=(q->rear+1)%MAXSIZE;i=(i+1)%MAXSIZE)
	{
		printf("%d\t",q->data[i]);
	}
	printf("\n");
}

8、队列的顺序表实现源码

seqqueue.h

#ifndef __SEQQUEUE_H__
#define __SEQQUEUE_H__

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define MAXSIZE 10
typedef int datatype;

typedef struct seqqueue{
	datatype data[MAXSIZE];
	int front,rear;
}seq_queue,*seq_pqueue;

extern seq_pqueue init1_seqqueue(void);
extern void init_seqqueue(seq_pqueue *Q);
extern bool is_full_seqqueue(seq_pqueue q);
extern bool is_empty_seqqueue(seq_pqueue q);
extern bool in_seqqueue(datatype data,seq_pqueue q);
extern bool out_seqqueue(seq_pqueue q,datatype *D);
extern void show_seqqueue(seq_pqueue q);

#endif

seqqueue.c

#include "seqqueue.h"

seq_pqueue init1_seqqueue(void)
{
	seq_pqueue q;
	q=(seq_pqueue)malloc(sizeof(seq_queue));
	if(q==NULL)
	{
		perror("malloc");
		exit(-1);
	}
	q->front=q->rear=MAXSIZE-1;

	return q;
}

void init_seqqueue(seq_pqueue *Q)
{
	*Q=(seq_pqueue)malloc(sizeof(seq_queue));
	if((*Q)==NULL)
	{
		perror("malloc");
		exit(-1);
	}
	(*Q)->front=(*Q)->rear=MAXSIZE-1;
	
	return;
}

//判断队列是否满
bool is_full_seqqueue(seq_pqueue q)
{
	if((q->rear+1)%MAXSIZE == q->front)
		return true;
	else
		return false;
}

//入队
bool in_seqqueue(datatype data,seq_pqueue q)
{
	//判断队列是否满
	if(is_full_seqqueue(q)){
		printf("队列已满!\n");
		return false;
	}

	//入队
	q->rear=(q->rear+1)%MAXSIZE;
	q->data[q->rear]=data;
	return true;
}

//判断队列是否空
bool is_empty_seqqueue(seq_pqueue q)
{
	if(q->rear == q->front)
		return true;
	else
		return false;
}

//出队
bool out_seqqueue(seq_pqueue q,datatype *D)
{
	//判断队列是否空
	if(is_empty_seqqueue(q)){
		printf("队列已空!\n");
		return false;
	}

	//出队
	q->front=(q->front+1)%MAXSIZE;
	*D=q->data[q->front];

	return true;
}

void show_seqqueue(seq_pqueue q)
{
	int i;
	if(is_empty_seqqueue(q))
		return;
	//非空时,从对头打印到队尾
	for(i=(q->front+1)%MAXSIZE;i!=(q->rear+1)%MAXSIZE;i=(i+1)%MAXSIZE)
	{
		printf("%d\t",q->data[i]);
	}
	printf("\n");
}

test.c

#include "seqqueue.h"
/* 用循环队列实现如下功能:
 * 用户从键盘输入整数,程序将其入队;
 * 用户从键盘输入字母,程序将队头元素出队;
 * 并在每一次出队和入队之后打印队列元素。
 */
int main(int argc, const char *argv[])
{
	seq_pqueue q;
	datatype data,t,ret;
	
	init_seqqueue(&q);

	while(1)
	{
		printf("请输入一个整数或字符:");
		ret=scanf("%d",&data);
		
		//输入整数时,入队
		if(ret == 1)
		{
			if(in_seqqueue(data,q))
				show_seqqueue(q);
		}
		else
		{
			//输入为字符时
			if(out_seqqueue(q,&t))
			{
				printf("out:%d\n",t);
				show_seqqueue(q);
			}
			//清空输入缓冲区
			while(getchar()!='\n');
		}
	}
	return 0;
}

Makefile

CC = gcc
CFLAGS = -o0 -g -Wall

SRC=seqqueue.c test.c
OBJS=test

$(OBJS):$(SRC)
	$(CC) $(CFLAGS) -o $@ $^

.PHONY:clean
clean:
	rm -rf $(OBJS) *.o
  • "-o0"表示优化级别为0,即关闭优化。这将导致生成的可执行文件较大,但是可以方便地进行调试。
  • "-g"表示生成调试信息,以便在调试程序时可以查看变量的值、函数的调用栈等信息。
  • "-Wall"表示启用所有警告,编译器将会显示所有可能的警告信息,帮助开发人员发现潜在的问题。

编译结果测试:

四、队列的链表实现

1、数据结构定义

对于链表,在进行 队列的定义 之前,我们需要考虑以下几个点:
  1)队列数据的存储方式,以及队列数据的数据类型;
  2)队列的大小;
  3)队首指针;
  4)队尾指针;

我们可以定义一个 队列 的 结构体,C语言实现如下所示:

typedef int datatype;

typedef struct linkqueuenode{ 
	datatype data;                    /* 数据域 */
	struct linkqueuenode *next;       /* 指针域 */
}linkqueue_node,*linkqueue_pnode;

typedef struct linkqueue{
	linkqueue_pnode front,rear;       /* 链队列指针 */
}link_queue,*link_pqueue;

2、初始化创造队列

C语言实现如下所示:

void init_linkqueue(link_pqueue *Q)
{
	//申请front和rear的空间
	*Q=(link_pqueue)malloc(sizeof(link_queue));
	if((*Q)==NULL)
	{
		perror("malloc");
		exit(-1);
	}
	//申请头结点空间
	(*Q)->front=(linkqueue_pnode)malloc(sizeof(linkqueue_node));
	if((*Q)->front==NULL)
	{
		perror("malloc");
		exit(-1) ;
	}

	(*Q)->front->next=NULL;
	(*Q)->rear=(*Q)->front;

	return;
}

3、判断队列是否空

C语言实现如下所示:

bool is_empty_linkqueue(link_pqueue q)
{
	if(q->rear == q->front)
		return true;
	else
		return false;
}

4、入队

C语言实现如下所示:

bool in_linkqueue(datatype data,link_pqueue q)
{
	linkqueue_pnode  new;

	//申请数据结点空间
	new=(linkqueue_pnode)malloc(sizeof(linkqueue_node));
	if(new==NULL)
	{
		puts("入队失败!");
		return false;
	}
	//将数据存储在申请的空间
	new->data=data;
	
	//将new指向的结点插入到链式队列中
	new->next=q->rear->next;
	q->rear->next=new;
	
	//让rear指针指向新的队尾结点
	q->rear=q->rear->next;

	return true;
}

5、出队

C语言实现如下所示:

bool out_linkqueue(link_pqueue q,datatype *D)
{
	linkqueue_pnode t;
	//判断队列是否空
	if(is_empty_linkqueue(q)){
		printf("队列已空!\n");
		return false;
	}

	//出队
	t=q->front;
	q->front =q->front->next;
	*D=q->front->data;
	free(t);

	return true;
}

6、打印队列

C语言实现如下所示:

void show_linkqueue(link_pqueue q)
{
	linkqueue_pnode p;
	if(is_empty_linkqueue(q))
		return;
	//非空时,从对头打印到队尾
	for(p=q->front->next;p!=NULL;p=p->next)
	{
		printf("%d\t",p->data);
	}
	printf("\n");
}

7、队列的链表实现源码

linkqueue.h

#ifndef __LINKQUEUE_H__
#define __LINKQUEUE_H__

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef int datatype;

typedef struct linkqueuenode{
	datatype data;
	struct linkqueuenode *next;
}linkqueue_node,*linkqueue_pnode;

typedef struct linkqueue{
	linkqueue_pnode front,rear;
}link_queue,*link_pqueue;

extern void init_linkqueue(link_pqueue *Q);
extern bool is_empty_linkqueue(link_pqueue q);
extern bool in_linkqueue(datatype data,link_pqueue q);
extern bool out_linkqueue(link_pqueue q,datatype *D);
extern void show_linkqueue(link_pqueue q);

#endif

linkqueue.c      

#include "linkqueue.h"

void init_linkqueue(link_pqueue *Q)
{
	//申请front和rear的空间
	*Q=(link_pqueue)malloc(sizeof(link_queue));
	if((*Q)==NULL)
	{
		perror("malloc");
		exit(-1);
	}
	//申请头结点空间
	(*Q)->front=(linkqueue_pnode)malloc(sizeof(linkqueue_node));
	if((*Q)->front==NULL)
	{
		perror("malloc");
		exit(-1) ;
	}

	(*Q)->front->next=NULL;
	(*Q)->rear=(*Q)->front;

	return;
}

//入队
bool in_linkqueue(datatype data,link_pqueue q)
{
	linkqueue_pnode  new;

	//申请数据结点空间
	new=(linkqueue_pnode)malloc(sizeof(linkqueue_node));
	if(new==NULL)
	{
		puts("入队失败!");
		return false;
	}
	//将数据存储在申请的空间
	new->data=data;
	
	//将new指向的结点插入到链式队列中
	new->next=q->rear->next;
	q->rear->next=new;
	
	//让rear指针指向新的队尾结点
	q->rear=q->rear->next;

	return true;
}

bool is_empty_linkqueue(link_pqueue q)
{
	if(q->rear == q->front)
		return true;
	else
		return false;
}

//出队
bool out_linkqueue(link_pqueue q,datatype *D)
{
	linkqueue_pnode t;
	//判断队列是否空
	if(is_empty_linkqueue(q)){
		printf("队列已空!\n");
		return false;
	}

	//出队
	t=q->front;
	q->front =q->front->next;
	*D=q->front->data;
	free(t);

	return true;
}

void show_linkqueue(link_pqueue q)
{
	linkqueue_pnode p;
	if(is_empty_linkqueue(q))
		return;
	//非空时,从对头打印到队尾
	for(p=q->front->next;p!=NULL;p=p->next)
	{
		printf("%d\t",p->data);
	}
	printf("\n");
}

test.c

#include "linkqueue.h"
/* 用链式队列实现如下功能:
 * 用户从键盘输入整数,程序将其入对;
 * 用户从键盘输入字母,程序将队头元素出队;
 * 并在每一次出队和入队之后打印队列元素。
 */
int main(int argc, const char *argv[])
{
	link_pqueue q;
	datatype data,t,ret;
	
	init_linkqueue(&q);

	while(1)
	{
		printf("请输入一个整数或字符:");
		ret=scanf("%d",&data);
		
		//输入整数时,入对
		if(ret == 1)
		{
			if(in_linkqueue(data,q))
				show_linkqueue(q);
		}
		else
		{
			//输入为字符时
			if(out_linkqueue(q,&t))
			{
				printf("out:%d\n",t);
				show_linkqueue(q);
			}
			//清空输入缓冲区
			while(getchar()!='\n');
		}
	}
	return 0;
}

Makefile 

CC = gcc
CFLAGS = -o0 -g -Wall

SRC=linkqueue.c test.c
OBJS=test

$(OBJS):$(SRC)
	$(CC) $(CFLAGS) -o $@ $^

.PHONY:clean
clean:
	rm -rf $(OBJS) *.o
  • "-o0"表示优化级别为0,即关闭优化。这将导致生成的可执行文件较大,但是可以方便地进行调试。
  • "-g"表示生成调试信息,以便在调试程序时可以查看变量的值、函数的调用栈等信息。
  • "-Wall"表示启用所有警告,编译器将会显示所有可能的警告信息,帮助开发人员发现潜在的问题。

编译结果测试:

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

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

相关文章

com.gexin.platform 依赖下载问题

打包时报错显示&#xff1a; com.gexin.platform:gexin-rp-sdk-http:pom:4.1.1.4 failed to transfer from http://0.0.0.0/ 解决办法&#xff1a; 1、在idea中找到maven中的设置的settings.xml 2、根据路径找到settings.xml文件&#xff0c;添加以下内容 <mirror><…

基于孔雀优化算法的航线规划

MATLAB2020a下正常运行 上传明细-CSDN创作中心

一元函数微分学——刷题(14

目录 1.题目&#xff1a;2.解题思路和步骤&#xff1a;3.总结&#xff1a;小结&#xff1a; 1.题目&#xff1a; 2.解题思路和步骤&#xff1a; 只要知道反函数求导等于原函数的导数的倒数&#xff0c;那就很好求解了&#xff0c;这不过要先处理好x和y的对应关系&#xff0c;知…

WPF容器的背景对鼠标事件的影响

背景&#xff1a;在实现鼠标拖动窗口的过程中发现对父容器设置了鼠标拖动窗口的事件MouseLeftButtonDown private void DragWindow(object sender, MouseButtonEventArgs e) {if (e.LeftButton MouseButtonState.Pressed)DragMove(); } 问题&#xff1a;非常困惑的是&#x…

【MySQL】常用存储引擎,数据库管理,数据表管理,数据库账户管理

目录 一 常用的数据引擎(4) 1.1 InnoDB存储引擎 1.2 MyISAM存储引擎 1.3 Memory存储引擎 1.4 ARCHIVE存储引擎 二 数据库管理 2.1 元数据库概念与分类 2.2 相关操作命令 三 数据表的管理 3.1 三大范式 3.2 数据类型 四 数据库账户管理 五 思维导图 一 常用的数据…

Mac环境下Parallels Desktop 19的安装和使用

为了后续构建漏洞靶场和渗透测试环境&#xff0c;我们需要提前准备好几套与宿主机隔离的工作环境&#xff08;Windows、Linux等&#xff09;&#xff0c;在Mac上最常用的就是Paralles Desktop&#xff08;PD&#xff09;工具了&#xff0c;当前最新版本为19。接下来介绍如何安装…

PDF控件Spire.PDF for .NET【安全】演示:获取并验证 PDF 中的数字签名

在 PDF 中创建数字签名广泛用于保护 PDF 文件。因此&#xff0c;当您查看一些带有数字签名的PDF文件时&#xff0c;需要获取并验证数字签名。本文向您展示了一种通过使用Spire.PDF和 C# 代码来获取和验证 PDF 中的数字签名的解决方案。 Spire.PDF for .NET 是一款独立 PDF 控件…

第二证券:停牌意味着什么?

股票停牌的原因&#xff1f; 一般来说&#xff0c;股票停牌的原因可以分为以下几类&#xff1a; 1、上市公司有严峻情况变化&#xff0c;如企业并购、重组等&#xff0c;为了确保生意顺利完成和信息宣布的及时、充分、准确&#xff0c;避免商场出现信息不对称的情况&#xff…

javascript 常见工具函数(五)

41.深度拷贝对象&#xff1a; static deepCopyObj$(obj) {var result Array.isArray(obj) ? [] : {};for (var key in obj) {if (obj.hasOwnProperty(key)) {if (typeof obj[key] object && obj[key] ! null) {result[key] Utils$.deepCopyObj$(obj[key]); //递归…

门店管理井然有序的秘诀,就在这1888字里

门店管理是一款帮助企业提高线下门店管理效率的应用&#xff0c;适用于所有拥有实体连锁门店的行业&#xff0c;如&#xff1a;连锁服饰、商超、数码产品、连锁餐饮等。 门店管理常见痛点 线下连锁门店的管理受位置、时间等因素影响&#xff0c;总部管理鞭长莫及&#xff1b; …

外贸自建站和独立站的区别?海洋建站方法?

外贸自建站和独立站的异同点&#xff1f;怎么建跨境电商网站&#xff1f; 越来越多的外贸企业开始关注和选择建立自己的网站来进行产品推广和销售。然而&#xff0c;在外贸建站领域中&#xff0c;存在两种常见的类型&#xff1a;外贸自建站和独立站。那么&#xff0c;这两者之…

Android Studio如何创建尺寸大小及API通用的模拟器

目录 前言 一、操作步骤 二、总结 三、更多资源 前言 在开发移动应用程序的过程中&#xff0c;使用模拟器进行测试是一种常见和方便的方式。Android Studio是一款功能强大的集成开发环境&#xff0c;它提供了创建和管理模拟器的功能。在本文中&#xff0c;我们将介绍如何创…

面向对象(类和对象,对象内存图,成员变量和局部变量,封装,构造方法)

1. 类和对象 1.1 类和对象的理解 客观存在的事物皆为对象 &#xff0c;所以我们也常常说万物皆对象。 类 类的理解 类是对现实生活中一类具有共同属性和行为的事物的抽象类是对象的数据类型&#xff0c;类是具有相同属性和行为的一组对象的集合简单理解&#xff1a;类就是对…

C++的基础语句

C前奏 1.变量的定义2.键入和输出3.运算符4.sizeof()函数5.判断6.goto语句7.总结 这个专题&#xff0c;我会用简单的语言介绍C的语法&#xff0c;并会适当的对比实现相同或相似功能的C与python代码写法上的不同。 1.变量的定义 对于python来说&#xff0c;我们可以跳过定义直接…

python统计分析——直方图(plt.hist)

使用matplotlib.pyplot.hist()函数绘制直方图 from matplotlib.pyplot as pltdata_setnp.array([2,3,3,4,4,4,4,5,5,6]) plt.hist(fish_data) 下面介绍plt.hist()函数中常用的几个重要参数&#xff08;参数等号后为默认设置&#xff09;&#xff1a; &#xff08;1&#xff0…

从C++习题中思考

目录 一.开始1.1 二.变量和基本类型 C Peimer习题集第5版练习。 一.开始 1.1 编写程序&#xff0c;提示用户输入2个整数&#xff0c;打印出这两个整数指定的范围内的所有整数。 方式1&#xff1a;使用while循环。 #include<iostream> using namespace std; int main() …

RA4000CE (RTC模块)适用于汽车,工作温度范围宽,稳定性高

RA4000CE是一个集成了32.768 kHz数字温度补偿晶体振荡器(DTCXO)的RTC模块&#xff0c;适用于汽车&#xff0c;工作温度范围宽&#xff0c;稳定性高。它包括各种功能&#xff0c;如具有闰年校正的秒到年时钟/日历&#xff0c;时间警报&#xff0c;唤醒计时器&#xff0c;时间更新…

深入了解隧道代理HTTP的协议与技术细节

隧道代理HTTP&#xff0c;作为一种网络通信的桥梁技术&#xff0c;其背后的协议与技术细节承载着网络世界的无尽奥秘。对于技术人员而言&#xff0c;深入了解这些细节&#xff0c;不仅有助于优化网络性能&#xff0c;还能为网络安全提供坚实的保障。 一、隧道代理HTTP的协议基…

QQ邮件发送(PHP的Laravel)

1. 开启 QQ 邮箱的 SMTP 支持 2.里面会一个类似于密码之类&#xff08;复制一下&#xff09; 3.然后再 .env文件里面配置一下 MAIL_DRIVERsmtp —— 使用支持 ESMTP 的 SMTP 服务器发送邮件&#xff1b; MAIL_HOSTsmtp.qq.com —— QQ 邮箱的 SMTP 服务器地址&#xff0c;必…

MySQL之四大引擎、账号管理以及建库认识

目录 一、数据库存储引擎&#xff08;发动机&#xff09; 1.1、认识引擎 1.2、查看存储引擎 1.3、引擎常识 1.4、support字段说明 1.5、四大引擎 二、数据库管理 2.1、元数据库介绍&#xff1a; 2.2、分类&#xff1a; 2.3、增删改查以及使用操作 2.4、权限 三、数…