栈和队列 --- C语言实现

news2024/11/24 8:01:40

本篇文章来详细介绍一下栈和队列,并且通过数组或链表来实现。

目录

1.栈

1.1栈的概念及结构

 1.2栈的实现

2.队列

2.1队列的概念及结构

2.2队列的实现

3.栈和队列面试题

4.相关概念选择题


1.栈

1.1栈的概念及结构

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO (Last ln First Out)的原则。

压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。

出栈:栈的删除操作叫做出栈。出数据也在栈顶。
 

 1.2栈的实现

栈的实现一般可以使用数组或者链表实现,相对而言,数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小


数组实现栈:

 单链表实现栈:

 

 数组代码实现:

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int STDataType;

typedef struct Stack
{
	STDataType* data;
	int top;
	int capacity;
}Stack;

//初始化
void StackInit(Stack* pst);
//销毁
void StackDestroy(Stack* pst);
//入栈
void StackPush(Stack* pst, STDataType x);
//出栈
void StackPop(Stack* pst);
//获取栈顶元素
STDataType StackTop(Stack* pst);
//判空
bool StackEmpty(Stack* pst);
//获取个数
int StackSize(Stack* pst);

接口实现:

//初始化
void StackInit(Stack* pst)
{
	assert(pst);
	pst->data = NULL;
	pst->top = 0;
	pst->capacity = 0;
}
//销毁
void StackDestroy(Stack* pst)
{
	assert(pst);
	free(pst->data);
	pst->data = NULL;
	pst->top = pst->capacity = 0;
}
//入栈 
void StackPush(Stack* pst, STDataType x)
{
	assert(pst);
	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* ptr = (STDataType*)realloc(pst->data, newcapacity * sizeof(STDataType));
		if (ptr == NULL)
		{
			perror("malloc fail");
			return;
		}
		pst->data = ptr;
		pst->capacity = newcapacity;
	}
	pst->data[pst->top] = x;
	pst->top++;
}
//出栈
void StackPop(Stack* pst)
{
	assert(pst);
	assert(!StackEmpty(pst));

	pst->top--;
}
//获取栈顶元素
STDataType StackTop(Stack* pst)
{
	assert(pst);
	assert(!StackEmpty(pst));

	return pst->data[pst->top - 1];
}
//判空
bool StackEmpty(Stack* pst)
{
	assert(pst);
	/*if (pst->top == 0)
	{
		return true;
	}
	else
	{
		return false;
	}*/

	return pst->top == 0;
}
//获取个数
int StackSize(Stack* pst)
{
	assert(pst);
	return pst->top;
}

2.队列

2.1队列的概念及结构

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First ln First Out)。

入队列:进行插入操作的一端称为队尾

出队列:进行删除操作的一端称为队头

2.2队列的实现

队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,数组头删效率会比较低

链表实现队列: 

入队出队示意图: 

 链表代码实现队列:

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

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

typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
	int size;
}Queue;

//初始化
void QueueInit(Queue* pq);
//释放
void QueueDestroy(Queue* pq);
//入队
void QueuePush(Queue* pq, QueDataType x);
//出队
void QueuePop(Queue* pq);
//取队头
QueDataType QueueFront(Queue* pq);
//取队尾
QueDataType QueueBack(Queue* pq);
//判空
bool QueueEmpty(Queue* pq);

 接口实现:

//初始化
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}
//释放
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->phead;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}
//入队
void QueuePush(Queue* pq, QueDataType x)
{
	assert(pq);
	//创建新节点
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->next = NULL;
	newnode->data = x;
	//入队
	if (pq->phead == NULL)
	{
		assert(pq->ptail == NULL);//防止头为空时,尾不为空
		pq->ptail = pq->phead = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;
}
//出队
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

	//1.一个节点
	//2.多个节点
	if (pq->phead->next == NULL)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else
	{
		QNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
	}
	pq->size--;
}

//取队头
QueDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->phead->data;
}
//取队尾
QueDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->ptail->data;
}
//判空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->phead == NULL && pq->ptail == NULL;
}

 另外扩展了解一下,实际中我们有时还会使用一种队列叫循环队列。如操作系统课程讲解生产者消费者模型时可以就会使用循环队列。环形队列可以使用数组实现,也可以使用循环链表实现。

 

 

 Q.rear指向的是有效数据的下一个位置,在这时我们不能知道 Q.rear = Q.front 时,是队列满还是空,所以这里有两种解决办法来判断队满,图中采用的是第二种方法。

1.定义一个size来记录元素个数

2.让队列中少存储一个元素,数组实现让(rear+1) % MaxSize = front,rear 和 front 都是下标,环形链表实现让rear->next = front

3.栈和队列面试题

1.括号匹配问题。OJ链接

2.用队列实现栈。OJ链接

3.用栈实现队列。OJ链接

4.设计循环队列。OJ链接
 

4.相关概念选择题

答案在最后

1.一个栈的初始状态为空。现将元素1、2、3、4、5、A、B、C、D、E依次入栈,然后再依次出栈,则元素出栈的顺序是()。

  • A 12345ABCDE
  • B EDCBA54321
  • C ABCDE12345
  • D 54321EDCBA

2.若进栈序列为1,2,3,4,进栈过程中可以出栈,则下列不可能的一个出栈序列是()

  • A 1,4,3,2
  • B 2,3,4,1
  • C 3,1,4,2
  • D 3,4,2,1

3.循环队列的存储空间为 Q(1:100),初始状态为front=rear=100。经过一系列正常的入队与退队操作后,front=rear=99 ,则循环队列中的元素个数为()

  • A 1
  • B 2
  • C 99
  • D 0或者100

4.以下()不是队列的基本运算?

  • A 从队尾插入一个新元素
  • B 从队列中删除第i个元素
  • C 判断一个队列是否为空
  • D 读取队头元素的值

5.现有一循环队列,其队头指针为front,队尾指针为rear;循环队列长度为N。其队内有效长度为?(假设队头不存放数据)

  • A ( rear - front + N ) % N + 1
  • B ( rear - front + N ) % N
  • C ( rear - front ) % ( N +1 )
  • D ( rear - front + N ) % ( N - 1 )

答案

  1. B
  2. C
  3. D
  4. B
  5. B

本篇结束

 

 

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

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

相关文章

项目初始化--uniapp--vscode--vue3--ts

HBuilderX 创建 uni-app 项目 注意开启服务端口 目录结构 ├─pages 业务页面文件存放的目录 │ └─index │ └─index.vue index页面 ├─static 存放应用引用的本地静态资源的目录(注意&#xff1a;静态资源只能存放于此) ├─unpackage …

eclipse中经常遇到的maven相关的问题

maven工程依赖的jar包无法部署到tomcat中 右键maven工程&#xff0c;选择“属性” 将工程在tomcat重新发布即可。 2、Update Project or use Quick Fix maven工程总是提示更新&#xff0c;一更新java版本又回到1.5 在pom.xml添加如下&#xff1a; <build><finalN…

【jenkins】idea+jenkins+docker+dockerfile+compose流水线部署java应用

目录 整体架构 环境准备 安装docker以及docker-compose jenkins安裝 maven安装 portainer面板安装 sonarqube安装 在项目中增加dockerfile和compose.yml脚本 Dockerfile脚本内容 compose.yml脚本内容 jenkins安装必要插件 jenkins增加流水线任务 增加pipeline任务j…

windows下搭建php开发环境

http://wed.xjx100.cn/news/139397.html?actiononClick https://www.bilibili.com/read/cv23429835/ https://www.php.cn/faq/498307.html 安装iis 选择卸载程序 安装php 官网https://www.php.net/下载 选择线程安全 国内地址 下载完成后解压放到想存放的路径 添加p…

【Deviation】50 Matplotlib Visualizations, Python实现,源码可复现

详情请参考博客: Top 50 matplotlib Visualizations 因编译更新问题&#xff0c;本文将稍作更改&#xff0c;以便能够顺利运行。 本文介绍一下5中图示&#xff1a; Diverging Bars Diverging Texts Diverging Dot Plot Diverging Lollipop Chart with Markers Area Chart 1 Di…

OpenCv之车辆统计项目

目录 一、加载视频 二、去除背景 三、通过形态学识别车辆 四、对车辆统计 一、加载视频 代码如下: import cv2 import numpy as np import matplotlib.pyplot as plt# 视频加载 cap cv2.VideoCapture(2.mp4)# 循环读取视频帧 while True:ret,frame cap.read()if ret Tr…

【Vue】day03-VueCli(脚手架)

day03 一、今日目标 1.生命周期 生命周期介绍 生命周期的四个阶段 生命周期钩子 声明周期案例 2.综合案例-小黑记账清单 列表渲染 添加/删除 饼图渲染 3.工程化开发入门 工程化开发和脚手架 项目运行流程 组件化 组件注册 4.综合案例-小兔仙首页 拆分模块-局部…

Java-API简析_java.net.Proxy类(基于 Latest JDK)(浅析源码)

【版权声明】未经博主同意&#xff0c;谢绝转载&#xff01;&#xff08;请尊重原创&#xff0c;博主保留追究权&#xff09; https://blog.csdn.net/m0_69908381/article/details/131881661 出自【进步*于辰的博客】 因为我发现目前&#xff0c;我对Java-API的学习意识比较薄弱…

Element Ui 时间组件

很多时候在我们做项目的时候一般都会用到时间组件&#xff0c;其次js中&#xff1a;new dateNow new Date();得到的是Thu Jul 28 2022 15:04:32 GMT0800 (中国标准时间)&#xff0c;都需要去转换自己需要的时间格式。 接下来介绍Element Ui中的一个组件: <el-date-picker…

windows 服务器允许 ping

打开 Widnows 防火墙&#xff0c;高级 – 入站规则 找到以下 4 条规则&#xff0c;一条一条的点击右边的 &#xff1a; 启用规则 文件和打印机共享(回显请求 - ICMPv4-In) 文件和打印机共享(回显请求 - ICMPv6-In) 虚拟机监控(回显请求 - ICMPv6-In) 虚拟机监控(回显请求- IC…

【Linux网络编程】- 认识 ‘’协议‘‘ | 网络版本计算器

目录 一、“协议” 的概念 二、结构化数据的传输 三、序列化和反序列化 序列化和反序列化的目的 四、网络版本计算器 服务端&#xff08;server&#xff09; 协议定制&#xff08;protocal&#xff09; 客户端&#xff08;client&#xff09; 服务器处理请求逻辑&#…

【Unity3D】地面网格特效

1 前言 本文实现了地面网格特效&#xff0c;包含以下两种模式&#xff1a; 实时模式&#xff1a;网格线宽度和间距随相机的高度实时变化&#xff1b;分段模式&#xff1a;将相机高度分段&#xff0c;网格线宽度和间距在每段中对应一个值。 本文完整资源见→Unity3D地面网格特效…

C++ —— 类与对象(上)

前言 由于C在C语言的基础上移植了新的编程理念&#xff0c;所以我们先回顾一下C语言所遵循的旧的理念。一般来说&#xff0c;计算机语言要处理两个概念——数据和算法。数据是程序使用和处理的信息&#xff0c;而算法是程序使用的方法。C语言与当前最主流的语言一样&#xff0…

关于 Qt中的QString内容存在\u0000使用QChart(0x00)消除 的解决方法

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/131860574 红胖子(红模仿)的博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软…

Maven 基础之简介,基础配置

Maven 基本概念 Maven 是基于项目对象模型&#xff08;Project Object Model&#xff09;&#xff0c;可以通过一小段描述信息来管理项目的构建&#xff0c;报告和文档的软件项目管理工具。 Maven 主要有 2 个功能&#xff1a;「项目构建」和「依赖管理」。 &#x1f58b; 说…

Godot 4 源码分析 - 增加管道通信

学习研究Godot 4&#xff0c;很爽&#xff0c;虽然很庞杂&#xff0c;但相对于自己的水平来说&#xff0c;很强大&#xff0c;尤其是vulkan这块直接打包可用&#xff0c;省得自己从头琢磨。 一点一点地消化、优化与完善&#xff0c;最终才能成为自己的。 这段时间就在Godot的…

POSIX线程编程

死在山野的风里&#xff0c;活在自由的梦里 本专栏参考教材是四川轻化工大学陈年老师的linux实验指导手册&#xff08;含学习通的一些程序笔记&#xff09;。 POSIX线程编程 1.线程是什么2.创建线程创建一个用户级的线程&#xff0c;实现在线程中更改进程&#xff08;主线程&a…

Bean小结

Bean是Spring框架中最核心的两个概念之一&#xff08;另一个是面向切面编程AOP&#xff09;。 Bean 定义 Spring 官方文档对 bean 的解释是&#xff1a; In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC contain…

从Vue2到Vue3【三】——Composition API(第三章)

系列文章目录 内容链接从Vue2到Vue3【零】Vue3简介从Vue2到Vue3【一】Composition API&#xff08;第一章&#xff09;从Vue2到Vue3【二】Composition API&#xff08;第二章&#xff09;从Vue2到Vue3【三】Composition API&#xff08;第三章&#xff09;从Vue2到Vue3【四】C…

webrtc QOS方法二.4(flexfec 实现可优化点)

一、冗余报文和媒体报文组织结构优化点 以单帧10个媒体报文&#xff0c;冗余度20%为例。这里webrtc输出要有10个媒体包2个冗余包。webrtc输出的报文序列如下&#xff1a; 代码实现如下&#xff1a; UlpfecGenerator::AddPacketAndGenerateFec&#xff1a;攒够足够的帧 Forwar…