C++11 数据结构7 队列的链式存储,实现,测试

news2024/7/6 18:42:34

前期考虑

队列是两边都有开口,那么在链式情况下,线性表的链式那一边作为对头好呢?

从线性表的核心的插入和删除算法来看,如果在线性表链表的头部插入,每次循环都不会走,但是删除的时候,要删除线性表的尾部,要遍历整个 线性表。

都差不多。

我们考虑到在插入的时候,可能是批量插入,删除只是在某些条件成立的情况下才会删除,因此会将 线性表的头部做为 队列的头部,将线性表的尾部做为队列的尾部

 插入算法 核心代码

	//正式插入数据,
	int i = 0;
	LinkListNode *curSeqListNode = &(tempseqlist->head);//让curSeqListNode 指向 链表的头部
	for (int i = 0; i < pos; ++i) {
		curSeqListNode = curSeqListNode->next;
	}
	node->next = curSeqListNode->next;
	curSeqListNode->next = node;
	tempseqlist->length++;
	return ret;

删除算法 核心代码

	//辅助指针变量curSeqListNode,指向的位置是链表的头部
	LinkListNode *curSeqListNode = &(tempseqlist->head);//让curSeqListNode 指向 链表的头部
	
    int i = 0;
	for (i = 0; i < pos; ++i) {
		curSeqListNode = curSeqListNode->next;
	}
	retSeqListNode = curSeqListNode->next;	//先将要删除的节点缓存出来
	curSeqListNode->next = retSeqListNode->next;// 删除的节点的next中保存着 “要删除元素的下一个元素”,让curseqlistnode->next 指向
	tempseqlist->length--;
	return retSeqListNode;

代码实现

#ifndef __007LINKQUEUE_H__
#define __007LINKQUEUE_H__


//这两个是要给 所有人公开的
typedef void LinkQueue;

typedef struct LinkQueueNode {  //链表节点
	struct LinkQueueNode *next;
}LinkQueueNode;

//对外提供的方法

//初始化队列,要动态的创建LinkQueue
//创建失败返回NULL
LinkQueue* createLinkQueue();

//入队列 ,给队列的头部插入一个元素,插入点是在数组的尾部
//参数queue 表示要插入的栈
//参数 seqQueueNode 表示要插入的 节点
//成功 返回 1
//失败 返回<0
int push_LinkQueue(LinkQueue* queue, LinkQueueNode * seqQueueNode);

//出队列 将队列的头部的第一个元素删除,删除点是在数组的头部
//参数stack 表示要删除第一个元素的栈
//成功 返回 1
//失败 返回<0
//说明,最开始的时候,让删除栈顶元素,返回int,但是这个设计是不合理的。
//因为假设上层是Teacher,这个Teacher里的元素有 char *,char**,且这两个空间也是malloc的,那么上层需要释放这两个malloc出来的元素。
//这意味着我们需要将 pop_SeqStack中的元素返回上去,上层才有机会释放,底层怎么知道上层搞的是个啥存的?因此一定要给上层,让上层去释放。

//出队列 将队列的头部的第一个元素删除,删除点是在数组的头部
//参数linkqueue 表示要删除第一个元素的队列
//成功 返回 删除的第一个元素
//失败 返回 NULL
LinkQueueNode* pop_LinkQueue(LinkQueue* linkqueue);

//返回队列元素,将队列头部的第一个元素返回
//失败返回NULL
//成功返回节点
LinkQueueNode* top_LinkQueue(LinkQueue* linkqueue);

//返回队列大小
//成功 返回 队列的大小
//失败 返回<0
int size_LinkQueue(LinkQueue* linkqueue);


//判断队列是否为空
//成功 返回1 表示队列为空 
//成功 返回0 表示队列不为空
//失败 返回-1 表示该函数执行的时候有问题
int isEmpty_LinkQueue(LinkQueue* linkqueue);

//销毁队列
//成功 返回1 表示成功销毁队列 
//失败 返回-1 表示该函数执行的时候有问题
int Destory_LinkQueue(LinkQueue* linkqueue);

#endif

#include "007linkqueue.h"
#include "stdlib.h"
#include "stdio.h"
#include "string.h"

typedef struct LinkQueue {
	LinkQueueNode head;
	int length;// 该链表的大小
}TLinkQueue;

//初始化队列,要动态的创建LinkQueue
//创建失败返回NULL
LinkQueue* createLinkQueue() {
	TLinkQueue * tq = malloc(sizeof(TLinkQueue));
	if (tq == NULL) {
		printf("createLinkQueue error because malloc error\n");
		return NULL;
	}
	memset(tq,0,sizeof(TLinkQueue));
	tq->head.next = NULL;
	tq->length = 0;
	return tq;
}

//入队列 ,给队列的尾部插入一个元素,插入点也是在线性表的头部
//参数queue 表示要插入的栈
//参数 seqQueueNode 表示要插入的 节点
//成功 返回 1
//失败 返回<0
int push_LinkQueue(LinkQueue* queue, LinkQueueNode * seqQueueNode) {
	int ret = 1;
	if (queue == NULL) {
		ret = -1;
		printf("push_LinkQueue error because queue == NULL \n");
		return ret;
	}
	if (seqQueueNode == NULL) {
		ret = -2;
		printf("push_LinkQueue error because seqQueueNode == NULL \n");
		return ret;
	}
	TLinkQueue *tq = (TLinkQueue *)queue;
	LinkQueueNode* current = &(tq->head);//辅助指针变量,指向线性表的头结点
	seqQueueNode->next = current->next;
	current->next = seqQueueNode;
	tq->length++;
	return ret;
	
}

//出队列 将队列的头部的第一个元素删除,删除点是在线性表链接的最后一个元素
//参数linkqueue 表示要删除第一个元素的队列
//成功 返回 1
//失败 返回<0
//说明,最开始的时候,让删除栈顶元素,返回int,但是这个设计是不合理的。
//因为假设上层是Teacher,这个Teacher里的元素有 char *,char**,且这两个空间也是malloc的,那么上层需要释放这两个malloc出来的元素。
//这意味着我们需要将 pop_SeqStack中的元素返回上去,上层才有机会释放,底层怎么知道上层搞的是个啥存的?因此一定要给上层,让上层去释放。

//出队列 将队列的头部的第一个元素删除,删除点是在数组的尾部,
//参数linkqueue 表示要删除第一个元素的队列
//成功 返回 删除的第一个元素
//失败 返回 NULL
LinkQueueNode* pop_LinkQueue(LinkQueue* linkqueue) {
	LinkQueueNode* ret = NULL;
	if (linkqueue == NULL) {
		ret = NULL;
		printf("pop_LinkQueue error because queue == NULL \n");
		return ret;
	}
	TLinkQueue *tq = (TLinkQueue *)linkqueue;
	if (tq->length==0) {
		ret = NULL;
		printf("pop_LinkQueue error because tq->length==0 \n");
		return ret;
	}
	LinkQueueNode* current = &(tq->head);//辅助指针变量,指向线性表的头结点
	int pos = tq->length -1;
	for (int i = 0; i < pos; i++)
	{
		current = current->next;
	}
	LinkQueueNode* delnode = current->next;
	current->next = delnode->next;
	tq->length--;
	return delnode;

}

//返回队列元素,将队列头部的第一个元素返回
//失败返回NULL
//成功返回节点
LinkQueueNode* top_LinkQueue(LinkQueue* linkqueue) {
	LinkQueueNode* ret = NULL;
	if (linkqueue == NULL) {
		ret = NULL;
		printf("top_LinkQueue error because queue == NULL \n");
		return ret;
	}
	TLinkQueue *tq = (TLinkQueue *)linkqueue;
	if (tq->length == 0) {
		ret = NULL;
		printf("top_LinkQueue error because tq->length==0 \n");
		return ret;
	}
	LinkQueueNode* current = &(tq->head);//辅助指针变量,指向线性表的头结点
	int pos = tq->length -1;
	for (int i = 0; i < pos; i++)
	{
		current = current->next;
	}
	LinkQueueNode* getnode = current->next;
	return getnode;
}

//返回队列大小
//成功 返回 队列的大小
//失败 返回<0
int size_LinkQueue(LinkQueue* linkqueue) {
	int ret = 0;
	if (linkqueue == NULL) {
		ret = -1;
		printf("size_LinkQueue error because queue == NULL \n");
		return ret;
	}
	TLinkQueue *tq = (TLinkQueue *)linkqueue;
	return tq->length;
}


//判断队列是否为空
//成功 返回1 表示队列为空 
//成功 返回0 表示队列不为空
//失败 返回-1 表示该函数执行的时候有问题
int isEmpty_LinkQueue(LinkQueue* linkqueue) {
	int ret = 0;
	if (linkqueue == NULL) {
		ret = -1;
		printf("isEmpty_LinkQueue error because queue == NULL \n");
		return ret;
	}
	TLinkQueue *tq = (TLinkQueue *)linkqueue;
	int length =  tq->length;
	if (length==0) {
		ret = 1;
		return ret;
	}else{
		ret = 0;
		return ret;
	}
}

//销毁队列
//成功 返回1 表示成功销毁队列 
//失败 返回-1 表示该函数执行的时候有问题
int Destory_LinkQueue(LinkQueue* linkqueue) {
	int ret = 1;
	if (linkqueue == NULL) {
		ret = -1;
		printf("Destory_LinkQueue error because queue == NULL \n");
		return ret;
	}
	free(linkqueue);
	linkqueue = NULL;
	return ret;
}

#define _CRT_SECURE_NO_WARNINGS
#define _CRTDBG_MAP_ALLOC
#include "iostream"
#include <stdio.h>
#include <stdlib.h>

extern "C" {
#include "007linkqueue.h"
}

typedef struct Teacher {
	LinkQueueNode  linkqueuenode;
	int age;
	char name[128];
	char *othername;
	char **stuname; //一个老师下面有5个学生
}Teacher;

int main() {
	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);//程序退出时检测内存泄漏并显示到“输出”窗口

	int ret = 0;

	//初始化队列,要动态的创建LinkQueue
//创建失败返回NULL
	LinkQueue* linkqueue = createLinkQueue();
	if (linkqueue==NULL) {
		ret = -1;
		printf("func createLinkQueue error because linkqueue=NULL");
		return ret;
	}

	ret = isEmpty_LinkQueue(linkqueue);
	printf("isEmpty_LinkQueue = ret %d\n", ret);

	ret = size_LinkQueue(linkqueue);
	printf("size_LinkQueue = ret %d\n", ret);

	Teacher tea1;
	tea1.age = 20;
	strcpy(tea1.name, (const char*)"tea1");

	tea1.othername = (char *)malloc(sizeof(char) * 128);
	memset(tea1.othername, 0, sizeof(char) * 128);
	strcpy(tea1.othername, (const char*)"tea1othername");

	tea1.stuname = (char **)malloc(sizeof(char *) * 5);
	memset(tea1.stuname, 0, sizeof(char *) * 5);
	for (size_t i = 0; i < 5; i++)
	{
		tea1.stuname[i] = (char *)malloc(sizeof(char) * 128);//每个学生名字也有128个字符
		memset(tea1.stuname[i], 0, sizeof(char) * 128);
		sprintf(tea1.stuname[i], "tea1stuname%d", i + 1);
	}



	Teacher tea2;
	tea2.age = 22;

	strcpy(tea2.name, (const char*)"tea2");

	tea2.othername = (char *)malloc(sizeof(char) * 128);
	memset(tea2.othername, 0, sizeof(char) * 128);
	strcpy(tea2.othername, (const char*)"tea2othername");

	tea2.stuname = (char **)malloc(sizeof(char *) * 5);
	memset(tea2.stuname, 0, sizeof(char *) * 5);
	for (size_t i = 0; i < 5; i++)
	{
		tea2.stuname[i] = (char *)malloc(sizeof(char) * 128);//每个学生名字也有128个字符
		memset(tea2.stuname[i], 0, sizeof(char) * 128);
		sprintf(tea2.stuname[i], "tea2stuname%d", i + 1);
	}



	Teacher tea3;
	tea3.age = 33;
	strcpy(tea3.name, (const char*)"tea3");

	tea3.othername = (char *)malloc(sizeof(char) * 128);
	memset(tea3.othername, 0, sizeof(char) * 128);
	strcpy(tea3.othername, (const char*)"tea3othername");

	tea3.stuname = (char **)malloc(sizeof(char *) * 5);
	memset(tea3.stuname, 0, sizeof(char *) * 5);
	for (size_t i = 0; i < 5; i++)
	{
		tea3.stuname[i] = (char *)malloc(sizeof(char) * 128);//每个学生名字也有128个字符
		memset(tea3.stuname[i], 0, sizeof(char) * 128);
		sprintf(tea3.stuname[i], "tea3stuname%d", i + 1);
	}

	ret = push_LinkQueue(linkqueue, (LinkQueueNode *)&tea1);
	if (ret < 0) {
		printf("push_LinkQueue(linkqueue, (LinkQueueNode * )&tea1) func error ret =%d \n", ret);
		return ret;
	}

	ret = push_LinkQueue(linkqueue, (LinkQueueNode *)&tea2);
	if (ret < 0) {
		printf("push_LinkQueue(linkqueue, (LinkQueueNode * )&tea2) func error ret =%d \n", ret);
		return ret;
	}

	ret = push_LinkQueue(linkqueue, (LinkQueueNode *)&tea3);
	if (ret < 0) {
		printf("push_LinkQueue(linkqueue, (LinkQueueNode * )&tea3) func error ret =%d \n", ret);
		return ret;
	}

	printf("-after-\n");
	ret = isEmpty_LinkQueue(linkqueue);
	printf("isEmpty_LinkQueue = ret %d\n", ret);

	ret = size_LinkQueue(linkqueue);
	printf("size_LinkQueue = ret %d\n", ret);



	while (size_LinkQueue(linkqueue) > 0) {
		Teacher * temptea = (Teacher *)top_LinkQueue(linkqueue);
		if (temptea == NULL) {
			printf("can not get find teacher\n");
		}
		printf("temptea->age = %d,temptea->name = %s,temptea->othername=%s\n",
			temptea->age,
			temptea->name,
			temptea->othername);
		for (size_t j = 0; j < 5; j++)
		{
			printf("temptea->stuname[%d] = %s,  ",
				j, temptea->stuname[j]);
		}
		Teacher * deltea = (Teacher *)pop_LinkQueue(linkqueue);
		if (deltea == NULL) {
			printf("pop_LinkQueue seqstack error\n");
		}
		if (deltea->othername != NULL) {
			free(deltea->othername);

		}
		if (deltea->stuname != NULL) {
			for (size_t i = 0; i < 5; i++)
			{
				if (deltea->stuname[i] != NULL) {
					free(deltea->stuname[i]);
				}
			}
			free(deltea->stuname);
			deltea->stuname = NULL;
		}

		printf("\n");
	}
	printf("sss\n");

	//销毁栈
	//成功 返回1 表示成功销毁栈 
	//失败 返回-1 表示该函数执行的时候有问题
	ret = Destory_LinkQueue(linkqueue);

	return 0;

}

注意的点:

在代码中,我们从队尾删除元素的时候,或者从队尾拿到元素的时候,注意pos的值是length-1的,这是因为:我们在设计的时候,头部元素并不算真正的元素,真正的元素是从有值的第一个元素开始算的,且认为是0号元素

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

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

相关文章

IDEA中配置使用maven和配置maven的中央仓库

1 以汉化后的IDEA为例配置maven 打开idea选择文件 选择 设置 点击>构建.执行.部署 点击>构建工具 点击>Maven 其中Maven主路径 就是我们maven下载解压后的路径 可以通过边上的三个点选择你解压后的绝对路径&#xff0c;也可以直接把解压后的绝对路劲复制过来 以下…

C++之通俗易懂学模版

目录 一、了解什么是泛性编程 二、模版 1.函数模版 1.1 函数模板概念 1.2 函数模板格式 1.3 函数模板的原理 1.4 函数模板的实例化 1.5 模板参数的匹配原则 2.类模板 2.1 类模板的定义格式 2.2 类模板的实例化 3. 非类型模板参数 4. 模板的特化 4.1 概念 4.2 …

半导体晶圆厂内外网数据单向导出,什么样的方案才安全又便捷?

半导体晶圆厂企业为了隔绝外部⽹络有害攻击、保护⽹络和数据安全&#xff0c;通常采⽤物理隔离的⽅式&#xff0c;将企业内⽹与互联⽹隔离。⽹络隔离后&#xff0c;基于业务开展需求&#xff0c;部分重要数据仍需由内⽹导⼊及导出⾄外部⽹络区域。为保障数据的安全合规性&#…

【Qt常用控件】—— 多元素控件

目录 1.1 List Widget 1.2 Table Widget 1.3 Tree Widget 1.4 小结 Qt 中提供的多元素控件有: QListWidget QListView QTableWidget QTableView QTreeWidget QTreeView xxWidget 和 xxView 之间的区别 以 QTableWidget 和 QTableView 为例&#xff1a; QTableView 是基于…

Java:优先级队列(堆)

一、初识【堆】 1、什么是【优先级队列】&#xff1f; 前面的文章我们介绍过队列&#xff0c;队列是一种先进先出的数据结构&#xff0c;但是&#xff0c;在某些情况下&#xff0c;操作的数据可能需要有一个优先级来获取数据&#xff0c;例如优先获取队列中最大的元素&#xf…

这个合租室友真的没有一点公德心,还好他搬走了

这个合租室友真的没有一点公德心&#xff0c;还好他搬走了 这个出租屋有四个房间。 有三个卧室&#xff0c;和一个隔断。 我住三个卧室中的一个。下图中右边那个就是我住的。 2023年下半年&#xff0c;左边那个屋子来了一个新租户小白。 在住的过程中&#xff0c;隔断间的租…

致力于为企业提升媒体宣传的一种新策略-软文发稿和投放

随着新媒体时代的快速发展&#xff0c;媒体宣发的方式也在不断迭代&#xff0c;其中&#xff0c;“软文发稿”成为了许多企业非常看重的一种媒体宣发方式。那么&#xff0c;什么是“软文发稿”呢&#xff1f;这是一种通过撰写有新闻属性的广告文章&#xff0c;将企业的品牌、产…

武汉星起航:凭借专业优势,助力卖家孵化,推动跨境电商发展

在全球经济一体化的大背景下&#xff0c;跨境电商行业以其独特的优势&#xff0c;成为了推动国际贸易发展的重要力量。作为这一领域的佼佼者&#xff0c;武汉星起航电子商务有限公司积极践行“走出去”战略&#xff0c;凭借自营店铺运营经验和跨境电商资源的积累&#xff0c;利…

嵌入式学习59-ARM7(自动设备号和混杂设备)

知识零碎&#xff1a; 头文件查找&#xff1a; /arm/路径下的头文件 linux驱动程序的编写&#xff0c;编译&#xff0c;运行过程 -------------------------------------------------------------------------------------------------------------------------------- 1.…

photoshop如何使用PS中的吸管工具吸取软件外部的颜色?

第一步&#xff0c;打开PS&#xff0c;随意新建一个画布&#xff0c;或打开一个图片。 第二步&#xff0c;将PS窗口缩小&#xff0c;和外部窗口叠加放置&#xff0c;以露出后面的其它页面。 第三步&#xff0c;选中吸管工具&#xff0c;在PS窗口内单击一点吸取颜色&#xff0c;…

个人信息 | Q1违规通报分析出炉,通报量环比提升180%,工信部重点方向明晰!

为协助企业了解监管部门动向&#xff0c;爱加密基于移动应用安全大数据平台长期收集个人信息违规通报信息&#xff0c;并定期抽查新上架及有更新应用的个人信息合规情况&#xff0c;未来将定期公布部分分析结果&#xff0c;以便各企业了解监管侧及市场侧情况。 根据爱加密统计…

一文带你看懂多线程编程

title: 深入理解多线程编程 date: 2024/4/25 17:32:02 updated: 2024/4/25 17:32:02 categories: 后端开发 tags: 线程同步互斥锁死锁避免竞态条件线程池异步编程性能优化 第一章&#xff1a;多线程基础 1.1 线程概念与原理 线程&#xff1a;在操作系统中&#xff0c;一个…

探索SSH:常见功能与使用技巧

文章目录 远程登录密钥认证文件传输端口转发执行远程命令会话保持总结 SSH&#xff08;Secure Shell&#xff09;是一种安全网络协议&#xff0c;用于通过加密的方式在网络上安全地进行远程登录和执行命令。它是管理远程服务器和网络设备的重要工具之一。在本文中&#xff0c;我…

【TDengine】mac m1解决no taos in java.library.path

前言 使用macos搭建springbootmybatisplus&#xff0c;通过mqtt将数据更新到tdenigne 3.2.3&#xff0c;数据源使用远程服务器的tdengine。 问题 启动时报错&#xff1a; Caused by: java.lang.UnsatisfiedLinkError: no taos in java.library.path 以下是官方文档 打开本…

【电路笔记】-Colpitts振荡器

Colpitts振荡器 文章目录 Colpitts振荡器1、概述2、基本Colpitts 振荡器电路3、示例14、使用运算放大器的Colpitts振荡器5、总结Colpitts 振荡器设计使用两个中心抽头电容器与并联电感器串联,形成产生正弦振荡的谐振储能电路。 1、概述 在许多方面,Colpitts 振荡器与我们在上…

(开源版)企业AI名片S2B2C商城系统商业计划书

团队使命 擎动人工智能跃迁&#xff0c;融技术与商业之行 项目背景 话说2022年12月7日那天&#xff0c;国务院大大发布了个重磅消息&#xff0c;宣布咱们国家的三年抗疫大战终于告一段落&#xff0c;全面放开啦&#xff01;这意味着咱们的市场经济要重新焕发生机啦&#xff…

LeetCode //C - 38. Count and Say Medium Topics Companies

38. Count and Say The count-and-say sequence is a sequence of digit strings defined by the recursive formula: countAndSay(1) “1”countAndSay(n) is the way you would “say” the digit string from countAndSay(n-1), which is then converted into a differen…

【C语言】万字详讲操作符

目录 前言 一、操作符分类 二、算数操作符 三、移位操作符 四、位操作符 五、赋值操作符 六、单目操作符 6.1 逻辑反操作 6.2 负值与正值 6.3 取地址 6.4 sizeof 6.5 取反操作符 6.6 --和操作符 6.7 间接访问操作符&#xff08;解引用操作符&#xff09; 6.8 强…

比较好的平民衣服品牌有哪些?平价质量好短袖品牌推荐

随着气候变暖&#xff0c;夏天的持续时间似乎越来越长&#xff0c;短袖作为夏季的必备服装&#xff0c;受到了广大男士的青睐。然而&#xff0c;面对市场上众多的短袖品牌和不同的质量&#xff0c;大家都觉得选短袖的时候实在难以找到质量好且合适自己的。 选择合适的短袖确实…

中级信息系统管理工程师-必会题锦集

文章目录 中级信息系统管理工程师-必会题锦集题目一CPU[解析]试题二 CPU[解析] 中级信息系统管理工程师-必会题锦集 题目一CPU CPU中&#xff08;1&#xff09;不仅要保证指令的正确执行&#xff0c;还要能够处理异常事件。 A. 运算器 B. 控制器 C. 寄存器组 D. 内部总线 [解…