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

前期考虑

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

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

都差不多。

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

 插入算法 核心代码

	//正式插入数据,
	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号元素

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

回归与聚类——K-Means(六)

什么是无监督学习 一家广告平台需要根据相似的人口学特征和购买习惯将美国人口分成不同的小 组&#xff0c;以便广告客户可以通过有关联的广告接触到他们的目标客户。Airbnb 需要将自己的房屋清单分组成不同的社区&#xff0c;以便用户能更轻松地查阅这些清单。一个数据科学团队…

Python爱心代码

爱心效果图&#xff1a; 完整代码&#xff1a; import random from math import sin, cos, pi, log from tkinter import *# 定义画布尺寸和颜色 CANVAS_WIDTH 640 CANVAS_HEIGHT 480 CANVAS_CENTER_X CANVAS_WIDTH / 2 CANVAS_CENTER_Y CANVAS_HEIGHT / 2 IMAGE_ENLARG…

C#实现TFTP客户端

1、文件结构 2、TftpConfig.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace TftpTest {public class TftpConfig{}/// <summary>/// 模式/// </summary>public enum Modes{…

大模型都在用的:旋转位置编码

写在前面 这篇文章提到了绝对位置编码和相对位置编码&#xff0c;但是他们都有局限性&#xff0c;比如绝对位置编码不能直接表征token的相对位置关系&#xff1b;相对位置编码过于复杂&#xff0c;影响效率。于是诞生了一种用绝对位置编码的方式实现相对位置编码的编码方式——…

LS2K1000LA基础教程

基于LS2K1000LA的基础教程 by 南京工业大学 孙冬梅 于 2024.4.25 文章目录 基于LS2K1000LA的基础教程一、目的二、平台1.硬件平台2.软件平台 三、测试0.开发板开机及编译器配置0.1 开发板控制台0.2 虚拟机编译器配置 1. 简单应用编程1.helloworld.c2. fileio 文件操作3.proce…

Scrapy 爬虫教程:从原理到实战

Scrapy 爬虫教程&#xff1a;从原理到实战 一、Scrapy框架简介 Scrapy是一个由Python开发的高效网络爬虫框架&#xff0c;用于从网站上抓取数据并提取结构化信息。它采用异步IO处理请求&#xff0c;能够同时发送多个请求&#xff0c;极大地提高了爬虫效率。 二、Scrapy运行原…

入坑 Java

原文&#xff1a;https://blog.iyatt.com/?p11305 前言 今天&#xff08;2023.8.31&#xff09;有个学长问我接不接一个单子&#xff0c;奈何没学过 Java&#xff0c;本来不打算接的。只是报酬感觉还不错&#xff0c;就接了。 要求的完成时间是在10月初&#xff0c;总共有一…

Spring Boost + Elasticsearch 实现检索查询

需求&#xff1a;对“昵称”进行“全文检索查询”&#xff0c;对“账号”进行“精确查询”。 认识 Elasticsearch 1. ES 的倒排索引 正向索引 对 id 进行检索速度很快。对其他字段即使加了索引&#xff0c;只能满足精确查询。模糊查询时&#xff0c;逐条数据扫描&#xff0c…

编译原理实验课

本人没咋学编译原理&#xff0c;能力有限&#xff0c;写的不好轻点喷&#xff0c;大佬路过的话&#xff0c;那你就路过就好 东大编译原理实验课原题&#xff0c;22年 1. 基本题&#xff1a;简单的扫描器设计 【问题描述】 熟悉并实现一个简单的扫描器&#xff0c;设计扫描器…

C++ | Leetcode C++题解之第49题字母异位词分组

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<vector<string>> groupAnagrams(vector<string>& strs) {// 自定义对 array<int, 26> 类型的哈希函数auto arrayHash [fn hash<int>{}] (const array<int, 26>&…

黑马点评(十二) -- UV统计

一 . UV统计-HyperLogLog 首先我们搞懂两个概念&#xff1a; UV&#xff1a;全称Unique Visitor&#xff0c;也叫独立访客量&#xff0c;是指通过互联网访问、浏览这个网页的自然人。1天内同一个用户多次访问该网站&#xff0c;只记录1次。 PV&#xff1a;全称Page View&…

linux权限维持(四)

6.inetd服务后门 inetd 是一个监听外部网络请求 ( 就是一个 socket) 的系统守护进程&#xff0c;默认情况下为 13 端口。当 inetd 接收到 一个外部请求后&#xff0c;它会根据这个请求到自己的配置文件中去找到实际处理它的程序&#xff0c;然后再把接收到的 这个socket 交给那…

机器学习 -- 分类问题

场景 探讨了一个回归任务——预测住房价格&#xff0c;用到了线性回归、决策树以及随机森林等各种算法。本次中我们将把注意力转向分类系统。我们曾经对MNIST进行了分类任务&#xff0c;这次我们重新回到这里&#xff0c;细致的再来一次。 开始 获取数据 Scikit-Learn提供了…

力扣爆刷第127天之动态规划五连刷(整数拆分、一和零、背包)

力扣爆刷第127天之动态规划五连刷&#xff08;整数拆分、一和零、背包&#xff09; 文章目录 力扣爆刷第127天之动态规划五连刷&#xff08;整数拆分、一和零、背包&#xff09;关于0 1 背包问题的总结01背包遍历顺序&#xff1a;完全背包遍历顺序&#xff1a; 一、343. 整数拆…

Lock-It for Mac(应用程序加密工具)

OSXBytes Lock-It for Mac是一款功能强大的应用程序加密工具&#xff0c;专为Mac用户设计。该软件具有多种功能&#xff0c;旨在保护用户的隐私和数据安全。 Lock-It for Mac v1.3.0激活版下载 首先&#xff0c;Lock-It for Mac能够完全隐藏应用程序&#xff0c;使其不易被他人…

【Pytorch】(十四)C++ 加载TorchScript 模型

文章目录 &#xff08;十四&#xff09;C 加载TorchScript 模型Step 1: 将PyTorch模型转换为TorchScriptStep 2: 将TorchScript序列化为文件Step 3: C程序中加载TorchScript模型Step 4: C程序中运行TorchScript模型 【Pytorch】&#xff08;十三&#xff09;PyTorch模型部署: T…

平衡二叉树、红黑树、B树、B+树

Tree 1、前言2、平衡二叉树和红黑树3、B树和B树3.1、B树的构建3.2、B树和B树的区别3.3、数据的存储方式 1、前言 本文侧重在理论方面对平衡二叉树、红黑树、B树和B树的各方面性能进行比较。不涉及编程方面的实现。而关于于平衡二叉树在C中的实现&#xff0c;我的上一篇文章平衡…

Nginx基本使用 反向代理与负载均衡

什么是Nginx Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器。 其特点是占有内存少&#xff0c;并发能力强&#xff0c;nginx的并发能力在同类型的网页服务器中表现较好&#xff0c;而且几乎可以做到7*24不间断运行&#xff0c;即使运行数个月也不需要重新启动。 …

操作系统安全:Linux安全审计,Linux日志详解

「作者简介」&#xff1a;2022年北京冬奥会网络安全中国代表队&#xff0c;CSDN Top100&#xff0c;就职奇安信多年&#xff0c;以实战工作为基础对安全知识体系进行总结与归纳&#xff0c;著作适用于快速入门的 《网络安全自学教程》&#xff0c;内容涵盖系统安全、信息收集等…

【树莓派】yolov5 Lite,目标检测,树莓派4B,推理v5lite-e_end2end.onnx,摄像头实时目标检测

文章目录 YOLOv5 Lite: 在树莓派上轻松运行目标检测1. 环境配置2. 克隆项目3. 安装依赖项4. 下载模型权重5. 理解end2end的含义6. 示例推理7. 文件介绍8. 把文件弄到树莓派4B执行9. 进一步尝试fp16的onnx&#xff08;行不通&#xff09;10. 视频流检测 这里有大概的环境配置&am…