C语言数据结构-栈和队列

news2024/12/29 11:07:04

文章目录

  • 1 栈的表示与实践
    • 1.1 栈的概念及结构
    • 1.2 定义数据结构
    • 1.3 初始化与销毁
    • 1.4 入栈
    • 1.5 出栈
    • 1.6 栈顶的数据
    • 1.7 栈的个数
    • 1.8 栈是否是空
    • 1.9 打印栈
  • 2 队列的表示与实现
    • 2.1 队列的概念与结构
    • 2.2 队列的数据结构定义
    • 2.3 队列的初始化与销毁
    • 2.4 入队
    • 2.5 出队
    • 2.6 取队头数据
    • 2.7 取队尾数据
    • 2.8 队的个数
    • 2.9 判断队是否是空
    • 2.10 打印出队列
  • 3 栈和队列完整代码
    • 3.1 Stack.h
    • 3.2 Stack.c
    • 3.3 Queue.h
    • 3.4 Queue.c
    • 3.5 test.c


1 栈的表示与实践

1.1 栈的概念及结构

栈:一种特殊的线性表,其只允许在固定一段进行插入和删除元素操作。
进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。
栈中的数据元素遵循后进先出LIFO(Last in First out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶。
在这里插入图片描述

1.2 定义数据结构

//1 定义栈的数据结构类型
typedef int StackDataType;
//动态增长的栈
typedef struct Stack
{
	StackDataType* a;
	int top;
	int capacity;

}Stack;


//静态栈一般不用,我们常常使用动态增长的栈
//typedef struct Stack
//{
//	STDataType a[50];
//	int top;
//}Stack;

1.3 初始化与销毁

ps->top = 0; 和ps->top = -1;说实话我也说不清楚,要根据画图思考,根据调试得结果
在这里插入图片描述

void StackInit(Stack* ps)
{
	assert(ps);
	//刚刚开始给4个数据结构大小
	ps->a = (StackDataType*)malloc(sizeof(StackDataType) * 4);
	if (ps->a == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	ps->capacity = 4;
	ps->top = 0;	//top指向栈顶元素的后一个
	//ps->top = -1;   //top指向栈顶元素

}


void StackDestory(Stack* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->top = ps->capacity = 0;
}

1.4 入栈

接下来跟我们前面学的顺序表,链表十分类似,也比较容易理解

//检查扩容
void StackCheckCapacity(Stack* ps)
{
	assert(ps);
	if (ps->top == ps->capacity)
	{
		StackDataType* tmp = (StackDataType*)realloc(ps->a, ps->capacity * 2 * sizeof(StackDataType));
		if (tmp == NULL)
		{
			printf("realloc fail\n");
			return;
		}
		ps->a = tmp;
		ps->capacity *= 2;   //初始化函数中,capacity大小为4
	}
}

void StackPush(Stack* ps, StackDataType x)
{
	assert(ps);
	//检查扩容
	StackCheckCapacity(ps);

	//ps->a[ps->top] = x;
	//ps->top++;
	//上面两个代码简写成一下一行
	ps->a[ps->top++] = x;
}

1.5 出栈

void StackPop(Stack* ps)
{
	assert(ps);
	//当栈顶没有元素再删除就产生越界
	assert(ps->top > 0);

	ps->top--;
	//ps->a[ps->top - 1] = 0;
}

1.6 栈顶的数据

StackDataType StackTop(Stack* ps)
{
	assert(ps);
	assert(ps->top > 0);
	//取出栈顶元素
	return ps->a[ps->top - 1];
}

1.7 栈的个数

int StackSize(Stack* ps)
{
	assert(ps);
	//tope位于栈最后一个元素的下一个,同时是前面的数据个数
	return ps->top;
}

1.8 栈是否是空

布尔类型检查空间是否是空挺合适的

bool StackIfEmpty(Stack* ps)
{
	assert(ps);
	//如果是top是0,真,栈空
	return ps->top==0;
}

1.9 打印栈

简单封装一下

void StackPrint(Stack* ps)
{

	while (!StackIfEmpty(ps))
	{
		printf("%d ", StackTop(ps));
		StackPop(ps);
	}
	printf("\n");
}

2 队列的表示与实现

2.1 队列的概念与结构

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先
进先出FIFO(First In First Out) 。 即队尾入,队头出。
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头
front 队头, rear队尾 在百度百科找的图
在这里插入图片描述

2.2 队列的数据结构定义

typedef int QueueDataType;
typedef struct QueueNode
{
	QueueDataType data;
	struct QueueNode* next;
}QNode;

typedef struct Queue
{
	QNode* head;
	QNode* tail;
}Queue;

2.3 队列的初始化与销毁

销毁队列记得存储 cur->next
销毁队列记得存储 cur->next
销毁队列记得存储 cur->next

void QueueInit(Queue* pq)
{
	assert(pq);
	pq->head = pq->tail = NULL;
}

void QueueDestory(Queue* pq)
{
	assert(pq);

	QNode* cur = pq->head;
	while (cur)
	{
		QNode* NEXT = cur->next;
		free(cur);
		cur = NEXT;
	}
	pq->head = pq->tail = NULL;
}

2.4 入队

常常忘记队列为空时的情况了

//队尾插入数据
void QueuePush(Queue* pq, QueueDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	
	//插入的第一个节点
	if (pq->tail == NULL)
	{
		pq->head = pq->tail = newnode;
	}
	//已经有一个节点
	else
	{
		pq->tail->next = newnode;
		//pq->tail = newnode;
		pq->tail = pq->tail->next;
	}
}

2.5 出队

//队头取出数据
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->head);
	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		QNode* NEXT = pq->head->next;
		free(pq->head);
		pq->head = NEXT;
	}
}

2.6 取队头数据

QueueDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->head);

	return pq->head->data;
}

2.7 取队尾数据

QueueDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->head);
	return pq->tail->data;
}

2.8 队的个数

int QueueSize(Queue* pq)
{
	assert(pq);
	int size = 0;
	QNode* cur = pq->head;
	while (cur)
	{
		size++;
		cur=cur->next;
	}
	return size;
}

2.9 判断队是否是空

bool QueueIfEmpty(Queue* pq)
{
	assert(pq);
	return pq->head==NULL;
}

2.10 打印出队列

void QueuePrint(Queue* pq)
{
	while (!QueueIfEmpty(pq))
	{
		printf("%d ", QueueFront(pq));
		QueuePop(pq);
	}
	printf("\n");
}

3 栈和队列完整代码

3.1 Stack.h

#pragma once

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>

//1 定义栈的数据结构类型
typedef int StackDataType;

//静态栈一般不用,我们常常使用动态增长的栈
//typedef struct Stack
//{
//	STDataType a[50];
//	int top;
//}Stack;

//动态增长的栈
typedef struct Stack
{
	StackDataType* a;
	int top;
	int capacity;

}Stack;

//2 初始化与销毁
void StackInit(Stack* ps);
void StackDestory(Stack* ps);

//3 入栈
void StackPush(Stack* ps, StackDataType x);

//4 出栈
void StackPop(Stack* ps);

//5 返回栈顶的数据
StackDataType StackTop(Stack* ps);

//6 栈的个数
int StackSize(Stack* ps);

//7 栈是否是空
bool StackIfEmpty(Stack* ps);

//8 打印栈
void StackPrint(Stack* ps);

3.2 Stack.c

#include "Stack.h"
void StackInit(Stack* ps)
{
	assert(ps);
	//刚刚开始给4个数据结构大小
	ps->a = (StackDataType*)malloc(sizeof(StackDataType) * 4);
	if (ps->a == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	ps->capacity = 4;
	ps->top = 0;	//top指向栈顶元素的后一个
	//ps->top = -1;   //top指向栈顶元素

}

void StackDestory(Stack* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->top = ps->capacity = 0;
}

//检查扩容
void StackCheckCapacity(Stack* ps)
{
	assert(ps);
	if (ps->top == ps->capacity)
	{
		StackDataType* tmp = (StackDataType*)realloc(ps->a, ps->capacity * 2 * sizeof(StackDataType));
		if (tmp == NULL)
		{
			printf("realloc fail\n");
			return;
		}
		ps->a = tmp;
		ps->capacity *= 2;   //初始化函数中,capacity大小为4
	}
}

void StackPush(Stack* ps, StackDataType x)
{
	assert(ps);
	//检查扩容
	StackCheckCapacity(ps);

	//ps->a[ps->top] = x;
	//ps->top++;
	ps->a[ps->top++] = x;
}

void StackPop(Stack* ps)
{
	assert(ps);
	//当栈顶没有元素再删除就产生越界
	assert(ps->top > 0);

	ps->top--;
	//ps->a[ps->top - 1] = 0;
}

StackDataType StackTop(Stack* ps)
{
	assert(ps);
	assert(ps->top > 0);
	//取出栈顶元素
	return ps->a[ps->top - 1];
}

int StackSize(Stack* ps)
{
	assert(ps);
	//tope位于栈最后一个元素的下一个,同时是前面的数据个数
	return ps->top;
}

bool StackIfEmpty(Stack* ps)
{
	assert(ps);
	//如果是top是0,真,栈空
	return ps->top==0;
}

void StackPrint(Stack* ps)
{

	while (!StackIfEmpty(ps))
	{
		printf("%d ", StackTop(ps));
		StackPop(ps);
	}
	printf("\n");
}

3.3 Queue.h

#pragma once

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
//队尾入,队头出

//定义队列数据结构
typedef int QueueDataType;
typedef struct QueueNode
{
	QueueDataType data;
	struct QueueNode* next;
}QNode;

typedef struct Queue
{
	QNode* head;
	QNode* tail;
}Queue;

//队列的初始化与销毁
void QueueInit(Queue* pq);
void QueueDestory(Queue* pq);

//插入与取出
void QueuePush(Queue* pq, QueueDataType x);
void QueuePop(Queue* pq);

//取队头数据
QueueDataType QueueFront(Queue* pq);
//取队尾数据
QueueDataType QueueBack(Queue* pq);

//队的个数
int  QueueSize(Queue* pq);
//判断队是否是空
bool QueueIfEmpty(Queue* pq);

//打印出队列
void QueuePrint(Queue* pq);

3.4 Queue.c

#include "Queue.h"

void QueueInit(Queue* pq)
{
	assert(pq);
	pq->head = pq->tail = NULL;
}

void QueueDestory(Queue* pq)
{
	assert(pq);

	QNode* cur = pq->head;
	while (cur)
	{
		QNode* NEXT = cur->next;
		free(cur);
		cur = NEXT;
	}
	pq->head = pq->tail = NULL;
}

//队尾插入数据
void QueuePush(Queue* pq, QueueDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	
	//插入的第一个节点
	if (pq->tail == NULL)
	{
		pq->head = pq->tail = newnode;
	}
	//已经有一个节点
	else
	{
		pq->tail->next = newnode;
		//pq->tail = newnode;
		pq->tail = pq->tail->next;
	}
}


//队头取出数据
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->head);
	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		QNode* NEXT = pq->head->next;
		free(pq->head);
		pq->head = NEXT;
	}
}

QueueDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->head);

	return pq->head->data;
}

QueueDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->head);
	return pq->tail->data;
}

int QueueSize(Queue* pq)
{
	assert(pq);
	int size = 0;
	QNode* cur = pq->head;
	while (cur)
	{
		size++;
		cur=cur->next;
	}
	return size;
}

bool QueueIfEmpty(Queue* pq)
{
	assert(pq);
	return pq->head==NULL;
}

void QueuePrint(Queue* pq)
{
	while (!QueueIfEmpty(pq))
	{
		printf("%d ", QueueFront(pq));
		QueuePop(pq);
	}
	printf("\n");
}

3.5 test.c

#include"Stack.h"
#include"Queue.h"
void test_stack()
{
	Stack stack;
	StackInit(&stack);


	StackPush(&stack, 1);
	StackPush(&stack, 2);
	StackPush(&stack, 3);
	StackPush(&stack, 4);
	StackPush(&stack, 5);
	printf("%d ", StackTop(&stack));
	
	StackPop(&stack);
	printf("%d ", StackTop(&stack));

	StackPop(&stack);
	printf("%d ", StackTop(&stack));

	StackPush(&stack, 11);
	StackPush(&stack, 12);
	printf("\n");
	StackPrint(&stack);

	StackDestory(&stack);

}

void test_Queen()
{
	Queue queue;
	QueueInit(&queue);
	QueuePush(&queue,1);
	QueuePush(&queue,2);
	QueuePush(&queue,3);
	QueuePush(&queue,4);
	QueuePush(&queue,5);

	printf("%d ", QueueSize(&queue));

	//printf("\n");
	//printf("%d ", QueueFront(&queue));
	//printf("%d ", QueueBack(&queue));

	//printf("\n");
	//QueuePop(&queue);
	//QueuePop(&queue);
	//printf("%d ", QueueFront(&queue));
	//printf("%d ", QueueBack(&queue));


	printf("\n");
	//QueuePrint(&queue);
	while (!QueueIfEmpty(&queue))
	{
		printf("%d ", QueueFront(&queue));
		QueuePop(&queue);
	}
	printf("\n");

	QueueDestory(&queue);
}

int main()
{
	//test_stack();
	test_Queen();
	return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

enumerate()函数讲解+同时获取索引和对应的元素值+实例

enumerate()函数是Python内置函数&#xff0c;用于在遍历可迭代对象&#xff08;如列表、字符串、元组等&#xff09;时&#xff0c;同时获取索引和对应的元素值。 它的主要作用是在循环过程中方便地获取索引和元素。 下面以两个例子来进行介绍理解。 目录 一、例子1 二、例…

打造‘产业大数据综合服务平台’,助力智慧园区建设!

随着大数据、人工智能、云计算、物联网等新一代信息技术的发展与应用&#xff0c;我国各类型园区正在向“智慧园区”转型升级&#xff0c;逐步开启数字化、智能化的运营管理模式。智慧园区的建设不仅需要基础设施的智慧化&#xff0c;更要实现园区规划、运营、管理、服务的智慧…

plf::list原理分析

plf::list是一个比std::list性能要好的另外一种实现&#xff0c;根据作者的性能测试&#xff1a; 293% faster insertion 57% faster erasure 17% faster iteration 77% faster sorting 70% faster reversal 91% faster remove/remove_if 63% faster unique 811% faster clear …

Vue 3 + Tailwind CSS:打造现代化项目的完美组合

Vue 3 Tailwind CSS&#xff1a;打造现代化项目的完美组合 本篇教程将向你介绍如何将 Tailwind CSS 与 Vue 3 项目搭配使用&#xff0c;为你的项目提供现代化的 UI 呈现和开发体验。通过本文的逐步演示和示例代码&#xff0c;你将很快掌握在 Vue 3 中集成和使用 Tailwind CSS…

YOLOv7改进实验:一文了解YOLOv7如何打印FPS指标

💡该教程为改进YOLOv7指南,属于《芒果书》📚系列,包含大量的原创首发改进方式🚀 💡🚀🚀🚀本博客内含改进源代码,按步骤操作运行改进后的代码即可 💡更方便的统计更多实验数据,方便写作 新增YOLOv7打印FPS指标 完善(一键YOLOv7打印FPS指标) 文章目录 完善…

【Tomcat】java.net.BindException “Address already in use: NET_Bind“

问题 17:37 Error running Tomcat 7.0.76: Unable to open debugger port (127.0.0.1:14255): java.net.BindException "Address already in use: NET_Bind"调整 把14255 改成 49963就正常了 附件 netstat -aon|findstr "49963" taskkill -f -pid xxx…

机械中常用的一些术语

目录 一、OEMSOP:SOP编写指南 WI(标准作业指导书):标准作业程序 &#xff08;SOP&#xff09;:SOP和WI的区别&#xff1a;一、PFC、FMEA、PCP、WIPPAP、PSW&#xff1a;APQP&#xff1a;BOM&#xff08;Bill of Material&#xff09;物料清单DV&#xff08;设计验证&#xff09…

C++STL的vector模拟实现

文章目录 前言成员变量成员函数构造函数push_backpop_backinserterase析构函数拷贝构造 前言 成员变量 namespace but {template<class T>class vector{public:typedef T* iterator;private:iterator _start;iterator _finish;iterator _end_of_storage;}; }我们之前实…

《opencv实用探索·十八》Camshift进行目标追踪流程

CamShift&#xff08;Continuously Adaptive Mean Shift&#xff09;是一种用于目标跟踪的方法&#xff0c;它是均值漂移&#xff08;Mean Shift&#xff09;的扩展&#xff0c;支持对目标的旋转跟踪&#xff0c;能够对目标的大小和形状进行自适应调整。 cv::CamShift和cv::me…

【CANopen进阶日记】③ CANopen对象字典工具

【CANopen进阶日记】专栏目录 第一章 CAN协议栈详解 第二章 CANopen协议栈详解 第三章 CANopen对象字典工具 文章目录 【CANopen进阶日记】专栏目录前言一、对象字典简介二、CANopen协议栈框架三、NMT主从四、SDO客户端服务器五、PDO生产者消费者5.1 RPDO5.2 TPDO同步周期5.3 …

python代码200行左右,python100行代码案例

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;python代码200行左右&#xff0c;python100行代码案例&#xff0c;今天让我们一起来看看吧&#xff01; 有用的 Python 单行代码片段&#xff0c;只需一行代码即可解决特定编码问题&#xff01; 在本文中&#xff0c;我…

CTF V8 pwn入门(一)

仍然是因为某些原因&#xff0c;需要学学浏览器pwn 环境 depot_tools建议直接去gitlab里下&#xff0c;github上这个我用魔法都没下下来 下完之后执行 echo export PATH$PATH:"/root/depot_tools" >> ~/.bashrc路径换成自己的就ok了 然后是ninja git clo…

DSP28335之CAN通信易错点总结

一、CAN初始化流程 ①接收发送引脚初始化&#xff1b; ②接收和发送邮箱设置&#xff1b; ③邮箱使能&#xff1b; ④波特率配置&#xff1b; ⑤接收掩码设置&#xff1b; ⑥中断配置。 二、几个重要的知识点 ①影子寄存器 因为ECanbRegs是不可以单独对位操作&#xf…

SD-WAN架构:优化连接以提升性能

SD-WAN架构主要分为三种类型&#xff0c;分别为本地架构、支持云的架构、支持云的骨干架构。每一种架构都基于它们利用广域网&#xff08;WAN&#xff09;的方式而有其独特的优势。本文将对三种SD-WAN架构进行简要介绍。 SD-WAN本地架构 SD-WAN本地架构是在现场使用SD-WAN盒或…

焦炭冶金工艺3D可视化仿真展示更直观、形象

冶金行业作为重要的工业领域&#xff0c;其岗位实践培训一直面临着诸多挑战&#xff0c;随着web3d开发和VR虚拟仿真技术的不断创新和应用&#xff0c;冶金3D虚拟仿真实践教学平台应运而生&#xff0c;为钢铁生产培训带来了崭新的变革。 冶金3D虚拟仿真实践教学平台采用了先进的…

AIGC专题报告:ChatGPT纪要分享

今天分享的AIGC系列深度研究报告&#xff1a;《AIGC专题报告&#xff1a;ChatGPT纪要分享》。 &#xff08;报告出品方&#xff1a;久谦中台&#xff09; 报告共计&#xff1a;135页 OpenAI 高管解密 ChatGPT GPT-3 是一种大型语言模型&#xff0c;被训练用来在给定上下文中…

百度文库下载要用券?Kotlin爬虫几步解决

百度作为国内知名的网站&#xff0c;尤其是文库里面有各种丰富的内容&#xff0c;对我们学习生活都有很大的帮助&#xff0c;就因为其内容丰富&#xff0c;如果看见好用有意思的文章还用复制粘贴等方式就显得有点落后了&#xff0c;今天我将用我所学的爬虫知识给你们好好上一课…

Mac 下 Python+Selenium 自动上传西瓜视频

背景 研究下 PythonSelenium 自动化测试框架&#xff0c;简单实现 Mac 下自动化批量上传视频西瓜视频并发布&#xff0c;分享给需要的同学&#xff08;未做过多的异常处理&#xff09;。 脚本实现 首先通过手工手机号登录&#xff0c;保存西瓜视频网站的 cookie 文件 之后加载…

有什么项目可以大量使用c++实现?

有什么项目可以大量使用c实现&#xff1f; 在开始前我有一些资料&#xff0c;是我根据自己从业十年经验&#xff0c;熬夜搞了几个通宵&#xff0c;精心整理了一份「c的资料从专业入门到高级教程工具包」&#xff0c;点个关注&#xff0c;全部无偿共享给大家&#xff01;&#x…

《opencv实用探索·十七》calcBackProject直方图反向投影

在了解反向投影前需要先了解下直方图的概念&#xff0c;可以看我上一章内容&#xff1a;opencv直方图计算calcHist函数解析 直方图反向投影是一种图像处理技术&#xff0c;通常用于目标检测和跟踪。通过计算反向投影&#xff0c;可以将图像中与给定模式&#xff08;目标对象&a…