【数据结构NO.00002】C++构建简单的队列:ADT抽象数据类型概念浅析 by arttnba3

本文介绍了如何使用C++构建队列数据结构,重点讨论了ADT(抽象数据类型)的概念,包括ADT的定义、实现策略以及接口设计。通过接口实现队列功能,如初始化、入队、出队等操作,增强了数据类型的泛用性。
摘要由CSDN通过智能技术生成

绪论

队列(Queue)本质上其实是一种比较特殊的链表,基本上在我们学会写链表之后只要稍加修订便能将一个链表变成一条队列,那么为什么今天要专门开一篇文章来讲队列呢

其实今天要讲的核心概念并非是什么是队列这种数据结构,而是抽象数据类型(Abstract Data Type 简称ADT)及其接口(Connector)的构建

相信大家对上一篇的链表还有一点印象吧…对,写的很水很直白,并且没写ADT接口,因此不好维护,也不好放在更大的系统当中运作…所以今天通过队列补上相关的ADT的内容
PS:本篇将要用到二级指针,说实话半夜敲代码的时候我看着也很费劲(甚至因为看不懂自己写的代码而发了条动态)
PS2:这是一篇修订过的博文

基本概念:数据结构:队列(Queue)

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。
(百度百科:队列)

简单来说,队列(Queue)就是只能从头删除数据、从尾加入数据的一种特殊的链表,在上一篇博文当中我们讲解了双向链表,因此我相信在阅读上一篇博文之后队列并非一种难以理解的数据结构

队列也可以理解成底部开口的特殊栈(当然此时已经不属于所谓的栈了)

在这里插入图片描述
队列的基本模型

基本概念:抽象数据类型(Abstract Data Type,ADT)

什么是ADT?

抽象数据类型(Abstract Data Type,ADT)是计算机科学中具有类似行为的特定类别的数据结构的数学模型;或者具有类似语义的一种或多种程序设计语言的数据类型。
(百度百科:ADT)

在了解抽象数据类型之前,我们得先来了解:什么是类型(Type)?

在计算机当中,类型特指一个包含有两类信息的实体操作(Operation)和属性(Attribute)

例如int类型:
属性:一个整数值
操作:同类型值间的四则运算、同类型值之间的求模、改变符号(针对有符号整型)

抽象数据类型(ADT)本质而言是一种我们假想的数学模型,并非原有定义好的一种数据类型(如int、char…),而是需要我们使用代码自行去定义的带有一定层次结构的新的模型,是一种间接模型

如何实现ADT?

计算机科学领域开发出了实现ADT的三步走战略:

一、提供ADT的属性和相关操作的抽象描述(纯理论定义),这种正式的描述便是ADT
二、开发一个用以实现ADT的编程接口,需要使用新类型时便可以直接通过接口进行编程
三、编写使用接口的代码,在使用新类型时程序员便无需知道其具体的实现细节(类似黑盒)

基本概念:接口(Connector)

接口(软件类接口)是指对协定进行定义的引用类型。其他类型实现接口,以保证它们支持某些操作。接口指定必须由类提供的成员或实现它的其他接口。与类相似,接口可以包含方法、属性、索引器和事件作为成员。
(百度百科:接口)

接口(Connector)其实就是不同的应用层之间用以通信的相同的规则,即一套通用的通信规范

当通信双方都使用同一接口时(即使用相同的通信规范),才可以实现相互间的通信

当一个程序较大、开发人员较多的时候,我们往往需要接口来进行规范化通信

本篇博文当中,我们使用一套通用接口实现队列ADT,增加其泛用性

利用ADT接口实现队列数据类型

一、建立抽象

上文提到过一个类型包含有两个基本要素:属性与操作,那么在抽象化队列这种数据类型时,他的属性与操作又分别是什么呢?

依照前面写链表的经历,我们不难得出以下关于队列数据类型的信息:

属性:
一个能储存多个项,每个项包含自己的名字与数据的,只能从首项进行数据删除、末项进行数据增添的线性表
操作:
1、初始化一个非空队列
2、确定队列当中的项数
3、在队尾使一个新项入队
4、在队头使一个项出队
5、检查队列是否为空队列
6、删除一整条队列
7、检索队列的一个项(不改变队列)

二、建立接口

在C/C++当中,我们通常习惯使用结构体搭配指针来搭建一个接口

为了使这个接口能够被更多开发者使用,我们将其单独放置在一个全新的头文件queue.h当中:

//Code in queue.h, written by arttnba3
typedef struct queue{
   
	
	struct queue * PreQueue;
	string QueueName;
	int QueueData;
	struct queue * NextQueue;
}Queue;

typedef Queue QueuePtr;

三、实现队列功能

同样的,我们选择在外部文件queue.h当中定义一些通用接口函数


QueuePtr* MakeQueue(string qName,int qData);//Make a new Queue
int CheckQueue(QueuePtr * pQueue);//Check how many terms are there in this Queue
int CheckQueuePre(QueuePtr * pQueue);
int CheckQueueNext(QueuePtr * pQueue);
int GetInQueue(QueuePtr ** pQueue,int qData,string qName);//To get a new term into a Queue
int GetOutQueue(QueuePtr ** pQueue);//To get the very first term of the Queue OUT
bool QueueEmpty(QueuePtr * pQueue);//To check whether this Queue is EMPTY
int QueueDelete(QueuePtr ** pQueue);//To delete a Queue
void QueueDeletePre(QueuePtr * pQueue);
void QueueDeleteNext(QueuePtr * pQueue);
int QueueDataNum(QueuePtr * pQueue,int qNum);//To read the NO.qNum term in the Queue
string QueueDataName(QueuePtr * pQueue,int qNum);//To read the name of NO.qNum term in the Queue

1、初始化一个非空队列

创建一个新的队列很简单,只需要分配好内存,设定好初始值,并返回指向该内存的指针即可,由于该数据类型我们使用结构体来实现,因此函数返回值设为结构体指针

和创建双向链表时相同,我们选择使用new来分配内存,这里便不再过多阐释

QueuePtr* MakeQueue(string qName,int qData)
{
   
	QueuePtr *pQueue=new Queue;
	if(pQueue==NULL)
		return NULL;
	pQueue->PreQueue=NULL;
	pQueue->NextQueue=NULL;
	pQueue->QueueName=qName;
	pQueue->QueueData=qData;
	return pQueue;
}

2、确定队列当中的项数

因为是通用接口函数,我们无法保证外部使用者所传进来的数据一定符合我们的预期,因此我们这个函数需要考虑到如何让外部使用者传进来的指针指向的并非是队列头/尾的情况下、传进来的是空队列的情况下、以及其他特殊情况下也能够正确的得出这一条队列当中真实的项数

队列是一个线性表,我们可以假定我们需要从队列中间的一项进行搜寻,那么此时我们便同时需要向前与向后搜寻

我们可以选择在接口函数内再套入两个函数分别向前与向后搜寻队列中的项,使用递归可以很好的完成这个功能:

int CheckQueue(QueuePtr * pQueue)//主接口函数</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值