C++11 数据结构5 队列的概念,队列的顺序存储,实现,测试

一,队列的概念

队列是一种特殊的受限制的线性表。  

队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。

队列是一种先进先出的t(First In First Out)的线性表,简称FIFO。允许插入的一端为队尾,允许删除的一端为队头。队列不允许在中间部位进行操作!假设队列是q=(a1,a2,……,an),那么a1就是队头元素,而an是队尾元素。这样我们就可以删除时,总是从a1开始,而插入时,总是在队列最后。这也比较符合我们通常生活中的习惯,排在第一个的优先出列,最后来的当然排在队伍最后。如下图:

二,队列的顺序存储

那么如果用数组来模拟队列,情况说明如下,我们这里采用 尾部插入,头部删除的case进行处理

三,  队列顺序存储的代码实现

#ifndef __005SEQQUEUE_H__

#define __005SEQQUEUE_H__


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

//对外提供的方法

//初始化队列,要动态的创建SeqQueue,根据user设定的大小创建
//int stacksize ,表示user 要创建队列的大小
//创建失败返回NULL
SeqQueue* createSeqQueue(int queuesize);

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

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

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

//返回队列元素,将队列头部的第一个元素返回
//失败返回NULL
//成功返回节点
SeqQueueNode* top_SeqQueue(SeqQueue* seqqueue);

//返回队列大小
//成功 返回 队列的大小
//失败 返回<0
int size_SeqQueue(SeqQueue* seqqueue);

//返回user对队列分配的大小
//成功 返回 队列的大小
//失败 返回<0 
int capacity_SeqQueue(SeqQueue* seqqueue);


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

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


#endif

#include "005seqqueue.h"
#include "stdlib.h"
#include "stdio.h"
#include "string.h"

//栈的内部结构,不用写在.h文件中,一会要移动位置
typedef struct SeqQueue {

	//队列中的数组,存储的是数据的指针,假设我们的数据是Teacher,那么arr[0] 中的数据就应该是&Tea1,
	//也就是说,这是一个数组,数组的每一个成员里面都存放的是指针。
	//本质上是一个  void * arr[], 也可以看成是 int * arr[],因为实际上放的就是 Teacher的指针 

	SeqQueueNode **data;

	int m_QueueSize;//队列的实际大小

	int m_QueueCapacity;//队列的总大小,也就是user给定的大小
}TSeqQueue;


//对外提供的方法

//初始化队列,要动态的创建SeqQueue,根据user设定的大小创建
//int stacksize ,表示user 要创建队列的大小
//创建失败返回NULL
SeqQueue* createSeqQueue(int queuesize) {
	TSeqQueue* ss = NULL;
	ss = (TSeqQueue*)malloc(sizeof(TSeqQueue));
	if (ss == NULL) {
		printf("createSeqQueue func error\n");
		return ss;
	}
	memset(ss, 0, sizeof(TSeqQueue));
	ss->m_QueueSize = 0;
	ss->m_QueueCapacity = queuesize;
	ss->data = (SeqQueueNode**)malloc(sizeof(SeqQueueNode *) * queuesize);
	if (ss->data == NULL) {
		printf("createSeqQueue func error ss->data == NULL \n");
		return NULL;
	}
	memset(ss->data, 0, sizeof(ss->data));
	return ss;
}

//入队列 ,给队列的头部插入一个元素,插入点是在数组的尾部
//参数queue 表示要插入的栈
//参数 seqQueueNode 表示要插入的 节点
//成功 返回 1
//失败 返回<0
int push_SeqQueue(SeqQueue* queue, SeqQueueNode * seqQueueNode) {
	int ret = 1;
	if (queue == NULL) {
		ret = -1;
		printf("push_SeqQueue func error because stack==NULL ret=-1 and return\n");
		return ret;
	}
	if (seqQueueNode == NULL) {
		ret = -2;
		printf("push_SeqQueue func error because seqQueueNode==NULL ret=-2 and return\n");
		return ret;
	}
	TSeqQueue* st = (TSeqQueue*)queue;
	if (st->m_QueueCapacity == st->m_QueueSize) {
		ret = -3;
		printf("push_SeqQueue func error because st->m_StackCapccity == st->m_StackSize ret = -3 and return st->m_StackSize = %d, st->m_StackCapccity = %d\n",
			st->m_QueueSize,st->m_QueueCapacity);
		return ret;
	}
	//前面检查都完毕了,到这里就真的可以插入了,实行的是尾插法
	st->data[st->m_QueueSize] = seqQueueNode;
	st->m_QueueSize++;
	return ret;
}

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

//出队列 将队列的头部的第一个元素删除,删除点是在数组的头部
//参数seqqueue 表示要删除第一个元素的队列
//成功 返回 删除的第一个元素
//失败 返回 NULL
SeqQueueNode* pop_SeqQueue(SeqQueue* seqqueue) {
	SeqQueueNode* ret = NULL;
	if (seqqueue == NULL) {
		ret = NULL;
		printf("pop_SeqQueue func error because stack==NULL and return\n");
		return ret;
	}
	TSeqQueue * tq = (TSeqQueue *)seqqueue;
	if (tq->m_QueueSize == 0) {
		ret = NULL;
		printf("pop_SeqQueue func error because tq->m_QueueSize == 0 and return\n");
		return ret;
	}
	//执行到这里,说明可以删除

	ret = tq->data[0];

	//这里有移动的操作。因为删除的是 数组的第一个元素

	for (int i = 0; i < tq->m_QueueSize; ++i) {
		tq->data[i] = tq->data[i + 1];
	}
	tq->m_QueueSize--;
	
	return ret;
}

//返回队列元素,将队列头部的第一个元素返回
//失败返回NULL
//成功返回节点
SeqQueueNode* top_SeqQueue(SeqQueue* seqqueue) {
	SeqQueueNode* ret = NULL;
	if (seqqueue == NULL) {
		ret = NULL;
		printf("top_SeqQueue func error because stack==NULL and return\n");
		return ret;
	}
	TSeqQueue * tq = (TSeqQueue *)seqqueue;
	if (tq->m_QueueSize == 0) {
		ret = NULL;
		printf("top_SeqQueue func error because tq->m_QueueSize == 0 and return\n");
		return ret;
	}
	//执行到这里,说明队列是有元素的

	ret = tq->data[0];
	return ret;
}

//返回队列大小
//成功 返回 队列的大小
//失败 返回<0
int size_SeqQueue(SeqQueue* seqqueue){

	int ret = 0;
	if (seqqueue == NULL) {
		ret = -1;
		printf("size_SeqQueue func error because stack==NULL and return\n");
		return ret;
	}
	TSeqQueue * tq = (TSeqQueue *)seqqueue;
	return tq->m_QueueSize;

}

//返回user对队列分配的大小
//成功 返回 队列的大小
//失败 返回<0 
int capacity_SeqQueue(SeqQueue* seqqueue) {
	int ret = 0;
	if (seqqueue == NULL) {
		ret = -1;
		printf("capacity_SeqQueue func error because stack==NULL and return\n");
		return ret;
	}
	TSeqQueue * tq = (TSeqQueue *)seqqueue;
	return tq->m_QueueCapacity;
}


//判断队列是否为空
//成功 返回1 表示队列为空 
//成功 返回0 表示队列不为空
//失败 返回-1 表示该函数执行的时候有问题
int isEmpty_SeqQueue(SeqQueue* seqqueue) {
	int ret = 0;
	if (seqqueue == NULL) {
		ret = -1;
		printf("isEmpty_SeqQueue func error because stack==NULL and return\n");
		return ret;
	}
	TSeqQueue * tq = (TSeqQueue *)seqqueue;
	if (tq->m_QueueSize ==0) {
		ret = 1;
	}
	else {
		ret = 0;
	}
	return ret;
}

//销毁队列
//成功 返回1 表示成功销毁队列 
//失败 返回-1 表示该函数执行的时候有问题
int Destory_SeqQueue(SeqQueue* seqqueue) {
	int ret = 1;
	if (seqqueue == NULL) {
		ret = -1;
		printf("isEmpty_SeqQueue func error because stack==NULL and return\n");
		return ret;
	}
	TSeqQueue * tq = (TSeqQueue *)seqqueue;
	if (tq->data!=NULL) {
		free(tq->data);
	}
	tq->data = NULL;
	free(tq);
	seqqueue = NULL;
	return ret;

}

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

extern "C" {
#include "005seqqueue.h"
}

typedef struct Teacher {
	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;
	//初始化队列,要动态的创建SeqStack,根据user设定的大小创建
//int stacksize ,表示user 要创建栈的大小
//创建失败返回NULL
	SeqQueue* seqqueue = createSeqQueue(1024);
	if (seqqueue == NULL) {
		ret = -1;
		printf("func createSeqQueue error because seqstack = NULL return ret =-1\n");
		return ret;
	}
	ret = isEmpty_SeqQueue(seqqueue);
	printf("isEmpty_SeqQueue = ret %d\n", ret);

	ret = size_SeqQueue(seqqueue);
	printf("size_SeqQueue = ret %d\n", ret);

	ret = capacity_SeqQueue(seqqueue);
	printf("capacity_SeqQueue = 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_SeqQueue(seqqueue, &tea1);
	if (ret < 0) {
		printf("push_SeqQueue(seqqueue, (SeqStackNode * )&tea1) func error ret =%d \n", ret);
		return ret;
	}

	push_SeqQueue(seqqueue, &tea2);
	if (ret < 0) {
		printf("push_SeqQueue(seqqueue, (SeqStackNode * )&tea2) func error ret =%d \n", ret);
		return ret;
	}

	push_SeqQueue(seqqueue, &tea3);
	if (ret < 0) {
		printf("push_SeqQueue(seqqueue, (SeqStackNode * )&tea3) func error ret =%d \n", ret);
		return ret;
	}

	printf("-after-\n");
	ret = isEmpty_SeqQueue(seqqueue);
	printf("isEmpty_SeqQueue = ret %d\n", ret);

	ret = size_SeqQueue(seqqueue);
	printf("size_SeqQueue = ret %d\n", ret);

	ret = capacity_SeqQueue(seqqueue);
	printf("capacity_SeqQueue = ret %d\n", ret);


	while (size_SeqQueue(seqqueue) > 0) {
		Teacher * temptea = (Teacher *)top_SeqQueue(seqqueue);
		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_SeqQueue(seqqueue);
		if (deltea == NULL) {
			printf("pop_SeqStack 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_SeqQueue(seqqueue);


	return 0;





}

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

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

相关文章

Day16-Java进阶-线程通信线程生命周期线程池单例设计模式

1. 线程通信 1.1 线程通信介绍 1.2 两条线程通信 package com.itheima.correspondence;public class CorrespondenceDemo1 {/*两条线程通信*/public static void main(String[] args) {Printer1 p new Printer1();new Thread(new Runnable() {Overridepublic void run() {syn…

机器学习运用-民宿价格

项目简介 随着旅游业的蓬勃发展&#xff0c;民宿市场迎来了前所未有的增长机遇。正好最近在参加拓尔思数据挖掘公益实习活动&#xff0c;我的项目将应用机器学习技术开发一个价格预测模型。可以达到更好地理解和预测民宿价格的目的&#xff0c;该模型综合考虑了从容纳人数、便…

【Java】文件操作(一)

文章目录 ✍一、文件的基本认识1.文件是什么&#xff1f;2.文本文件和二进制文件3.文件权限4.相对路径和绝对路径1.1绝对路径1.2相对路径 ✍二、文件的基本操作1.FIle的属性2.File的构造方法3.File类的方法3.1File类的获取操作3.2File类的判断操作3.3文件创建和删除3.4其他的常…

this指向

调用方式示例 函数中this的指向通过new调用new method()新对象直接调用method()全局对象通过对象调用obj.method()前面的对象call、apply、bindmethod.call(ctx)第一个参数 我们说的this指向是一个函数里边的this指向&#xff0c;如果这个this不在函数里边&#xff0c;那th…

C. Inhabitant of the Deep Sea

本题链接&#xff1a;Problem - C - Codeforces 题目&#xff1a; 样例&#xff1a; 输入 6 4 5 1 2 4 3 4 6 1 2 4 3 5 20 2 7 1 8 2 2 2 3 2 2 15 1 5 2 7 5 2输出 2 3 5 0 2 2 思路&#xff1a; 数学模拟。 根据题意&#xff0c;一前一后的攻击&#xff0c;攻击k次后&…

PotPlayer详细安装教程

安装步骤 进入官网&#xff1a; https://potplayer.tv/ 根据自己电脑的windows系统选择对应的版本安装 选择合适的字体 下载完成 优化设置 刚下好的potplayer仅限于能用&#xff0c;所有设置均为默认状态&#xff0c;我们需要进行优化 首先打开potplayer 右击选择选项 在…

三、CPU基础-缓存

计算机中缓存一般分为两个部分 1.内存 2.CPU Cache 一、CPU Cache分级 CPU Cache 通常分为大小不等的三级缓存&#xff0c;分别是 L1 Cache、L2 Cache 和 L3 Cache。 L1 Cache 和 L2 Cache 都是每个 CPU 核心独有的&#xff08;通常会分为「数据缓存」和「指令缓存」&#…

Git--原理与使用

目录 一、课程目标二、初始Git三、安装Git3.1 Linux-centos 四、Git的基本操作4.1 创建Git本地仓库 五、配置Git六、认识工作区、暂存区、版本库七、添加文件八、查看.git九、修改文件十、版本回退十一、撤销修改11.1 情况一&#xff1a;对于工作区的代码&#xff0c;还有add11…

海康NVR接入视频监控平台部分视频浏览失败,显示503错误的解决办法

目录 一、问题概述 二、问题排查 &#xff08;一&#xff09;排查思路介绍 &#xff08;二&#xff09;平台排查 1、确定排查的思路 2、信令控制模块的排查 3、媒体转发模块的排查 &#xff08;三&#xff09;客户设备排查 1.观察正常视频的设置 2. 调查问题原因 三…

B端设计实战:基于角色属性的权限设计

编辑导读:“权限控制”是中后台的基础能力,用于管控操作人员在平台内可做的事项内容。即通过权限控制,可以决定哪些人在平台内可以做哪些事。本文作者围绕角色&属性的权限设计展开分析,希望对你有帮助。 Hello,我是一名交互设计师。 随着3月暖春的即将到来,苏州的疫…

足球场体育馆三维可视化:颠覆传统观赛体验,开启视觉新纪元

在数字化浪潮席卷全球的今天&#xff0c;三维可视化技术正以其独特的魅力引领着体育场馆建设的革新潮流。这一技术的出现&#xff0c;不仅为观众带来了前所未有的视觉享受&#xff0c;更在体育产业的发展中&#xff0c;开启了一扇通往未来的大门。 足球场体育馆三维可视化&…

YOLOV1学习笔记

1. 前置知识简介 1.1 方向梯度直方图&#xff08;HOG, Histogram of Oriented Gradient&#xff09; 在计算机视觉以及数字图像处理中方向梯度直方图是一种能对物体进行检测的基于形状边缘特征的描述算子&#xff08;用于量化图像局部特征的算法工具&#xff0c;它将图像中的…

string 类以及模拟实现

&#x1d649;&#x1d65e;&#x1d658;&#x1d65a;!!&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦ &#x1f44f;&#x1f3fb;‧✧̣̥̇:Solitary_walk ⸝⋆ ━━━┓ - 个性标签 - &#xff1a;来于“云”的“羽球人”。…

Flutter 中优雅切换应用主题的组件

Flutter 中优雅切换应用主题的组件 视频 https://youtu.be/L–XLpc452I https://www.bilibili.com/video/BV1wD421n75p/ 前言 原文 https://ducafecat.com/blog/flutter-app-theme-switch Adaptive Theme 这个组件通过包裹 MaterialApp 的方式整体管理 theme 主题&#xff0…

Java冲突

本身 父类 接口(多) 如果出现同样名字的方法,就会出现冲突 * 情况描述1: * 当一个类,继承了父类,实现了某接口,父类中的成员方法和接口中的方法重名 * 解决方法: * 子类就近选择父类成员方法 亲爹优先原则 * *使用格式: * 父类:super.方法名 * 父接口:父接口名.super.方…

QT——其他方式实现HelloWrold

QT——其他方式实现HelloWrold 使用输入框实现使用代码实现 通过按钮实现信号槽代码方式实现 我们之前对QT实现HelloWorld有了一些基本的了解&#xff0c;用了一些简单的方法实现了HelloWorld&#xff0c;如果对QT还不怎么了解的&#xff0c;可以点击这里&#xff1a; https://…

算法提高 第一期 KMP扩展算法

1## 具体思路&#xff1a; 和KMP算法的是想类似&#xff0c;充分利用已经比较字符性质来减少冗余的字符比较次数。KMP的思想是充分的利用模式串中所有前缀字串&#xff08;以模式串为开头的字串&#xff09;的真前缀和真后缀&#xff08;指子串的开始字符与子串的最后字符相等的…

【C 数据结构】二叉树

文章目录 【 1. 基本原理 】1.1 二叉树的性质1.2 满二叉树1.3 完全二叉树 【 2. 二叉树的顺序存储结构 】2.1 完全二叉树的顺序存储2.2 普通二叉树的顺序存储2.3 完全二叉树的还原 【 3. 二叉树的链式存储结构 】【 4. 二叉树的先序遍历 】4.1 递归实现4.2 非递归实现 【 5. 二…

MongoDB磁盘空间占满,导致数据库被锁定,如何清理数据和磁盘空间

一、问题 1、我在实际项目中&#xff0c;遇到一个问题&#xff0c;随着数据每天的不断增加&#xff0c;导致mongodb的磁盘空间站满了&#xff0c;数据库被锁了&#xff0c;无法使用。 2、故障表现 部署的应用程序突然无法将数据写入数据库&#xff0c;但是可以正常读取数据。…

栈和队列详解

目录 栈栈的概念及结构栈的实现数组栈的实现数组栈功能的实现栈的初始化void STInit(ST* pst)初始化情况一初始化情况二 代码栈的插入void STPush(ST* pst, STDataType x)代码 栈的删除void STPop(ST* pst)代码 栈获取数据STDataType STTop(ST* pst)代码 判断栈是否为空bool ST…