【数据结构篇】~栈和队列(附源码)

embedded/2024/9/23 4:26:43/

数据结构篇】~栈和队列

  • 前言
  • 一、栈的实现
    • 1.头文件
    • 2.源文件
    • 3.一个算法题——[有效的括号](https://leetcode.cn/problems/valid-parentheses/description/%E2%80%8B)
  • 二、队列
    • 1.头文件
    • 2.源文件

前言

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

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

一、栈的实现

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

1.头文件

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
//栈的实现很多和顺序表相同
typedef int stdatatype;
typedef struct stack
{stdatatype* arr;int capacity;//有效容量int top;//栈顶
}st;
void stinit(st* ps);// 初始化栈
void stdestroy(st* ps);// 销毁栈
void stpush(st* ps, stdatatype x);// 入栈
void stpop(st* ps);//出栈
stdatatype stTop(st* ps);//取栈顶元素
int stsize(st* ps);//获取栈中有效元素个数
bool stempty(st* ps);//栈是否为空

2.源文件

#include"Stack.h"
void stinit(st* ps)// 初始化栈
{assert(ps);ps->arr = NULL;ps->capacity = ps->top = 0;}
bool stempty(st* ps)//栈是否为空(有效数据(top)为0)
{assert(ps);return ps->top==0;
}
void stdestroy(st* ps)// 销毁栈
{assert(ps);if (ps->arr)free(ps->arr);ps->arr = NULL;//防止成为野指针ps->capacity = ps->top = 0;
}
void stpush(st* ps, stdatatype x)// 入栈(只能从栈顶入)
{assert(ps);if (ps->capacity == ps->top)//如果容量不够就要扩容{int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;stdatatype* tmp = (stdatatype*)realloc(ps->arr,sizeof(stdatatype)*newcapacity );if (tmp == NULL){perror("realloc fail!");return 1;}ps->capacity = newcapacity;ps->arr = tmp;}//出if条件就说明容量足够ps->arr[ps->top++] = x;
}
void stpop(st* ps)//出栈
{assert(ps);assert(!stempty(ps));//如果报错就说明是空栈--ps->top;
}
stdatatype stTop(st* ps)//取栈顶元素
{assert(ps);assert(!stempty(ps));return ps->arr[ps->top - 1];
}
int stsize(st* ps)//获取栈中有效元素个数
{assert(ps);return ps->top;
}

3.一个算法题——有效的括号

在这里插入图片描述

在这里插入图片描述

bool isValid(char* s) {st st;stinit(&st);if(*s=='\0')return false;else{while(*s != '\0'){//如果是左括号就入栈if(*s=='['||*s=='{'||*s=='(' ){stpush(&st, *s);}          else//左括号全部入栈,然后取栈顶元素和右括号匹配,然后出栈{ if(stempty(&st)){ return false;}if(stTop(&st)=='('&& *s ==')'||stTop(&st)=='{'&& *s =='}'||stTop(&st)=='['&& *s ==']'){stpop(&st);//出栈}else{return false;}}s++;}bool ret=stempty(&st);stdestroy(&st);// 销毁栈return ret;}   
}

二、队列

概念:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先
出FIFO(First In First Out) ​
入队列:进行插入操作的一端称为队尾 ​
出队列:进行删除操作的一端称为队头

在这里插入图片描述

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

在这里插入图片描述

1.头文件

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int qudatatype;
typedef struct queuenode {qudatatype data;struct queuenode* next;
}qunode;
typedef struct queue {qunode* phead;qunode* ptail;int size;//节点个数
}qu;
void quinit(qu* pq);//初始化队列
void qudestroy(qu* pq);//销毁队列
void qupush(qu* pq, qudatatype x);// 入队列,队尾
void qupop(qu* pq);// 出队列,队头
qudatatype qufront(qu* pq);//取队头数据
qudatatype quback(qu* pq);//取队尾数据
bool quempty(qu* pq);//队列判空
int qusize(qu* pq);//队列有效元素个数

2.源文件

#include"Queue.h"
//队列底层是用单链表实现的
void quinit(qu* pq)//初始化队列
{assert(pq);pq->phead = pq->ptail = NULL;
}
bool quempty(qu* pq)//队列判空
{assert(pq);return pq->phead == NULL;}
void qupush(qu* pq, qudatatype x)// 入队列,队尾(单链表尾插)
{assert(pq);qunode* newnode = (qunode*)malloc(sizeof(qunode));if (newnode == NULL){perror("malloc fail");return 1;}newnode->data = x;newnode->next = NULL;if (pq->phead == NULL){pq->phead = pq->ptail = newnode;}pq->ptail->next = newnode;pq->ptail = pq->ptail->next;pq->size++;
}
void qupop(qu* pq)// 出队列,队头(单链表头删)
{assert(pq);assert(!quempty(pq));if (pq->phead == pq->ptail)//只有一个节点是,要避免成为野指针{free(pq->phead);pq->phead = pq->ptail = NULL;		}pq->phead = pq->phead->next;
}
void qudestroy(qu* pq)//销毁队列
{assert(pq);assert(!quempty(pq));while (pq->phead){qunode* Next = pq->phead->next;free(pq->phead);pq->phead = NULL;pq->phead = Next;}//出循环时说明全部节点都释放了(除了phead、ptail)pq->phead = pq->ptail = NULL;pq->size = 0;
}
int qusize(qu* pq)//队列有效元素个数
{assert(pq);return pq->size;
}
qudatatype qufront(qu* pq)//取队头数据(取数据时,队列不能为空!)
{assert(pq);assert(!quempty(pq));return pq->phead->data;}
qudatatype quback(qu* pq)//取队尾数据
{assert(pq);assert(!quempty(pq));return pq->ptail->data;
}

详解都在注释中哦!


http://www.ppmy.cn/embedded/100272.html

相关文章

【Linux】Linux项目自动化构建工具-make/Makefile

背景 1.会不会写makefile&#xff0c;从一个侧面说明了一个人是否具备完成大型工程的能力。 2.一个工程中的源文件不计其数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;makefile 定义了一系列的规则来指定&#xff0c;哪些文件需要先编译&#xff0c;哪…

wo是如何克服编程学习中的挫折感的?

你是如何克服编程学习中的挫折感的&#xff1f; 编程学习之路上&#xff0c;挫折感就像一道道难以逾越的高墙&#xff0c;让许多人望而却步。然而&#xff0c;真正的编程高手都曾在这条路上跌倒过、迷茫过&#xff0c;却最终找到了突破的方法。你是如何在Bug的迷宫中找到出口的…

Linux:CentOS配置

一&#xff0c;安装VMware 这个可以通过官网获取 vmware下载 也可以联系我&#xff0c;我发给你 二&#xff0c;安装CentOS Centos官网找要下载的版本&#xff1a; https://vault.centos.org/ 阿里云镜像&#xff1a;https://mirrors.aliyun.com/centos-vault/?spma2c6h.13…

Excel数据提取技巧:快速整理非结构化数据

在Excel中快速整理非结构化数据&#xff0c;需要掌握一系列有效的数据提取技巧。以下是一些实用的方法和步骤&#xff0c;可以帮助你高效地处理非结构化数据&#xff1a; 1. 使用文本函数 Excel提供了多种文本函数&#xff0c;如LEFT、RIGHT、MID、FIND、SEARCH等&#xff0c…

CAsyncSocket类实现网络通信

CAsyncSocket类编程模型   在一个MFC应用程序中,要想轻松处理多个网 络协议,而又不牺牲灵活性时,可以考虑使用CAsyncSocket类,它的效率比CSocket 类要高。CAsyncSocket类针对字节流型套接字的编程模型简述如下:   1、构造一个CAsyncSocket对象,并用这个 对象的Create…

运维学习————nginx2-配置详解及负载均衡

目录 一、配置文件详解 1.1、结构 1.2、重要配置解释 1.3、详细配置 全局配置 Events HTTP 服务器配置 server虚拟主机配置 location URL匹配配置 1.4、完整配置 二、负载均衡 2.1、概念 2.2、集群规划及实现 2.3、具体实现 2.3.1、克隆 2.3.2、修改tomcat1配…

“学会吊打面试官系列”8.12~8.24面试难点记录

一共面了三家小公司&#xff0c;以下为个人记录的比较重要的10道题目 redis大key是什么问题&#xff1f;如何避免&#xff1f; “大 Key”是指那些占用大量内存的键值对。大 Key 会导致各种性能问题&#xff0c;比如&#xff1a;内存消耗增大&#xff0c;性能影响增大&#x…

iOS 开发:Object-C 和 Swift 的区别 (AI问答)

一&#xff1a;语言类型的区别&#xff08;最主要区别&#xff09; object-c 是动态类型语言&#xff1b; swift是静态类型语言&#xff1b; 看一下AI的回答&#xff0c;很全面~~ Objective-C 和 Swift 的语言类型区别主要体现在以下几个方面&#xff1a; 1. 静态类型 vs. 动…