使用ADT(抽象数据类型)对队列进行操作

2023-10-09 16:40

本文主要是介绍使用ADT(抽象数据类型)对队列进行操作,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这里写目录标题

  • 一 、什么叫ADT
  • 二 、创建新的数据类型和函数接口
  • 三 、 实现函数接口
  • 四 、编写主函数
  • 五、运行结果
        • 1. 添加数据
        • 2. 删除数据
        • 3. 查找和显示数据

一 、什么叫ADT

在这里用ADT(抽象数据类型)来对队列进行操作,那么什么叫抽象数据类型呢,简单的说就是设计一种新的数据类型,然后再对新类型构造一系列操控数据的方法,详细步骤如下(来自C primer PLUS)

  1. 提供类型属性和相关操作的抽象描述。这些描述既不能依赖特定的实 现,也不能依赖特定的编程语言。这种正式的抽象描述被称为抽象数据类型 (ADT)。

  2. 开发一个实现 ADT 的编程接口。也就是说,指明如何储存数据和执 行所需操作的函数。例如在 C中,可以提供结构定义和操控该结构的函数原 型。这些作用于用户定义类型的函数相当于作用于 C基本类型的内置运算 符。需要使用该新类型的程序员可以使用这个接口进行编程。

  3. 编写代码实现接口。这一步至关重要,但是使用该新类型的程序员无 需了解具体的实现细节。

二 、创建新的数据类型和函数接口

在了解了什么抽象数据类型之后,这里还是以最简单的整型队列为例,话不多说,让我们来coding吧,首先定义queue.h文件

#ifndef _QUEUE_H_
#define _QUEUE_H_
#include <stdbool.h>
#define MAXITEMS 10// 定义队列
typedef int Item;typedef struct node
{Item item;struct node *next;
}Node;
typedef struct queue
{Node *head;Node *rear;int counts; // counts 为队列当中的项数
}Queue;// 定义操作队列的一系列方法
// 初始化队列
void InitialQueue(Queue *pq);//判断队列是否为空
bool QueueIsEmpty(const Queue *pq);//判断队列是否已满
bool QueueIsFull(const Queue *pq);//获取队列的项数
unsigned int CountInQueue(const Queue *pq);//在队列当中添加一个节点
bool AddNode(Item *pi,Queue *pq);//在队列当中删除节点
bool DeleteNode(Item *pi,Queue *pq);//查找队列当中的节点
bool FindNode(Item *pi,const Queue *pq);//清空队列节点
void EmptyQueue(Queue *pq);#endif

三 、 实现函数接口

在定义好数据类型和操作数据的接口函数之后,现在让我们来实现函数接口

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include "queue.h" void InitialQueue(Queue *pq){pq->head=pq->rear=NULL; //将头指针和尾指针都赋为NULLpq->counts=0; // 把队列的项数初始化为0
}bool QueueIsEmpty(const Queue *pq){return pq->counts==0; 
}bool QueueIsFull(const Queue *pq){return pq->counts==MAXITEMS ;
}unsigned int CountInQueue(const Queue *pq){return pq->counts;
}bool AddNode(Item *pi,Queue *pq){Node *pnew;if(QueueIsFull(pq))// 如果队列已满,返回falsereturn false;pnew=(Node *)malloc(sizeof(Node));//给new分配内存空间if(pnew==NULL)//如果未分配到内存,提前返回falsereturn false;CopyToNode(pi,pnew);pnew->next=NULL; //将新添加的数据的next赋为NULLif(QueueIsEmpty(pq))// 如果队列为空,直接在队首插入新的元素pq->head=pnew;elsepq->rear->next=pnew; //把尾结点的next与新节点连接起来pq->rear=pnew;//把新节点赋值给尾结点pq->counts++;// 项数加1return true;
}static void CopyToNode(Item *pi,Node *pnew){pnew->item=*pi; // 添加结点的数据部分
}bool DeleteNode(Item *pi,Queue *pq){Node *temp;if(QueueIsEmpty(pq))return false;CopyToItem(pi,pq->head);temp=pq->head; // 用temp存储被删除的节点pq->head=pq->head-next; // 把头节点重置为头节点的next指针free(temp);pq->counts--;if(pq->couns==0) // 删除最后一项时,把尾指针赋为NULL,头指针已经重新赋值为头指针的next,已经为NULLpq->rear=NULL; return true;
}static void CopyToItem(Item *pi,Node *temp){*pi=temp->item; // 将被删除的节点数据部分保存到*pi
}
bool FindNode(Item *pi,const Queue *pq){Node *temp;if(QueueIsEmpty(pq))return false;temp=pq->head // 把头节点赋值给temp;while(temp!=NULL){if(temp->item==*pi)return true;temp=temp->next;// 节点后移}return false;
}
void EmptyQueue(Queue *pq){Item del;while(!QueueIsEmpty(pq)){DeleteNode(&del,pq);}
}

到这里对应的函数接口内容就全部完成了,接下来就是编写主函数了

四 、编写主函数

int main(void){Item temp;Queue line;char ch;InitialQueue(&pq);printf("Please input your select .a is add ,q is quit ,d is del,q is quit, f is findnode:\n");while((ch=getchar())!='q'){if(ch!='a'&&ch!='d'&&ch!='f')continue;if(ch=='a'){printf("Please input a number\n");scanf("%d",&temp);if(QueueIsFull(&line))printf("The Queue is FULL!!\n");else{AddNode(&temp,&line);printf("puttings %d into queue\n",temp);}}else if(ch=='d'){if(QueueIsEmpty(&line))printf("The Queue is Empty\n");else{DelNodeInQueue(&temp,&line);printf("Removing %d in the queue\n",temp);}}else{if(QueueIsEmpty(&line))printf("The Queue is Empty\n");else{printf("Please input you wish to find number\n");scanf("%d",&temp);if (FindNode(&temp,&line))printf("%d is in line\n",temp);elseprintf("%d is not in line\n",temp);}}printf("%d items in queue \n",CountInQueue(&line));  puts("Type a to add, d to delete, q to quit ,f is find:\n");}printf("Here is queue:\n");showqueue(&line);return 0;
}void showqueue(Queue *pq){if(QueueIsEmpty(pq))printf("The Queue is empty\n");while(pq->head!=NULL){printf("%d",pq->head->item);DeleteNode(&(pq->head->item),pq);}
}

五、运行结果

1. 添加数据

在这里插入图片描述

2. 删除数据

在这里插入图片描述

3. 查找和显示数据

在这里插入图片描述

这篇关于使用ADT(抽象数据类型)对队列进行操作的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/174157

相关文章

SpringBoot集成redisson实现延时队列教程

《SpringBoot集成redisson实现延时队列教程》文章介绍了使用Redisson实现延迟队列的完整步骤,包括依赖导入、Redis配置、工具类封装、业务枚举定义、执行器实现、Bean创建、消费... 目录1、先给项目导入Redisson依赖2、配置redis3、创建 RedissonConfig 配

Python正则表达式匹配和替换的操作指南

《Python正则表达式匹配和替换的操作指南》正则表达式是处理文本的强大工具,Python通过re模块提供了完整的正则表达式功能,本文将通过代码示例详细介绍Python中的正则匹配和替换操作,需要的朋... 目录基础语法导入re模块基本元字符常用匹配方法1. re.match() - 从字符串开头匹配2.

Python使用FastAPI实现大文件分片上传与断点续传功能

《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

Spring Security简介、使用与最佳实践

《SpringSecurity简介、使用与最佳实践》SpringSecurity是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架,本文给大家介绍SpringSec... 目录一、如何理解 Spring Security?—— 核心思想二、如何在 Java 项目中使用?——

springboot中使用okhttp3的小结

《springboot中使用okhttp3的小结》OkHttp3是一个JavaHTTP客户端,可以处理各种请求类型,比如GET、POST、PUT等,并且支持高效的HTTP连接池、请求和响应缓存、以及异... 在 Spring Boot 项目中使用 OkHttp3 进行 HTTP 请求是一个高效且流行的方式。

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结

Java使用jar命令配置服务器端口的完整指南

《Java使用jar命令配置服务器端口的完整指南》本文将详细介绍如何使用java-jar命令启动应用,并重点讲解如何配置服务器端口,同时提供一个实用的Web工具来简化这一过程,希望对大家有所帮助... 目录1. Java Jar文件简介1.1 什么是Jar文件1.2 创建可执行Jar文件2. 使用java

C#使用Spire.Doc for .NET实现HTML转Word的高效方案

《C#使用Spire.Docfor.NET实现HTML转Word的高效方案》在Web开发中,HTML内容的生成与处理是高频需求,然而,当用户需要将HTML页面或动态生成的HTML字符串转换为Wor... 目录引言一、html转Word的典型场景与挑战二、用 Spire.Doc 实现 HTML 转 Word1

Java实现在Word文档中添加文本水印和图片水印的操作指南

《Java实现在Word文档中添加文本水印和图片水印的操作指南》在当今数字时代,文档的自动化处理与安全防护变得尤为重要,无论是为了保护版权、推广品牌,还是为了在文档中加入特定的标识,为Word文档添加... 目录引言Spire.Doc for Java:高效Word文档处理的利器代码实战:使用Java为Wo