当前位置: 首页 > news >正文

【数据结构初阶】--栈和队列(一)

 🔥个人主页:@草莓熊Lotso

🎬作者简介:C++研发方向学习者

📖个人专栏: 《C语言》 《数据结构与算法》《C语言刷题集》《Leetcode刷题指南》

⭐️人生格言:生活是默默的坚持,毅力是永久的享受。  

前言: 前面我们学习完了顺序表和链表,那么接下来我们会继续学习栈和队列的知识,还是和之前一样会完全实现一遍,有了前面的基础其实栈和队列的实现会轻松很多的


目录

一.栈的概念和结构

二.栈的初始化和销毁

 三.栈的入栈和出栈

入栈:

出栈:

四.取栈顶元素和获取栈中有效元素个数

取栈顶元素:

获取栈中元素个数:

 五.代码展现

Stack.h:

Stack.c:

test.c:


一.栈的概念和结构

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

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

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

 我们可以把栈的结构想成水杯,杯底是封闭的,接水和倒水都在杯顶

--我们栈的实现一般可以使用数据或者链表实现,相对而言数组的结构实现更优一些。我们将数组的尾部作为栈顶,数组首部作为栈底,数组的尾部操作时间复杂度都是O(1)。其实链表使用头部操作也可以,但是综合空间来说使用数组更优一点

--我们先来看下栈的结构的定义

typedef int STDataType;
typedef struct Stack
{STDataType* arr;int top;int capacity;
}ST;

二.栈的初始化和销毁

初始化:

//初始化
void STInit(ST* ps)
{ps->arr = NULL;ps->top = ps->capacity = 0;
}

销毁: 

//销毁
void STDestory(ST* ps)
{if (ps->arr)free(ps->arr);ps->arr = NULL;ps->top = 0;ps->capacity = 0;
}

重点提示:

栈的创建和销毁都是跟顺序表差不多的,没有很大的区别,为了区分我们把size这里定义的是top


 三.栈的入栈和出栈

--栈的入栈和出栈操作我们实现起来也都很简单,我们直接来看看吧

入栈:

void STPush(ST* ps, STDataType x)
{assert(ps);//检查空间//空间不够就增容if (ps->top == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;STDataType* tmp = (STDataType*)realloc(ps->arr, newcapacity * sizeof(STDataType));if (tmp == NULL){perror("realloc fail!");exit(1);}ps->arr = tmp;ps->capacity = newcapacity;}//空间足够ps->arr[ps->top++] = x;
}

看到这些代码,大家应该都不会很陌生,跟顺序表一样,空间足够直接尾部插入一个数据,top++,空间不够就扩容,扩容操作和顺序表是一模一样,不是很了解的可以看下博主前面顺序表实现的博客

--在实现出栈之前,我们先要实现一个判空操作的接口

//判空
bool STEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}

如果top为0,就证明了栈为空

出栈:

//出栈
void STPop(ST* ps)
{assert(!STEmpty(ps));ps->top--;
}

栈不为空,就直接ps->top--就ok了,不需要其它的操作,实现起来很方便  


四.取栈顶元素和获取栈中有效元素个数

 --取栈顶元素实现了之后,我们就可以在test.c中实现取栈顶元素,打印再出栈的操作了,可以观察一下我们栈的先进后出特性

取栈顶元素:

//取栈顶元素
STDataType STTop(ST* ps)
{assert(!STEmpty(ps));return 	ps->arr[ps->top - 1];;
}

注意这里取出来的一定是下标为ps->top-1的元素 

 test.c:

#include"stack.h"void test1()
{ST ps;STInit(&ps);//入栈STPush(&ps, 1);STPush(&ps, 2);STPush(&ps, 3);STPush(&ps, 4);while (!STEmpty(&ps)){//取栈顶元素,打印STDataType top = STTop(&ps);printf("%d ", top);//出栈STPop(&ps);}printf("\n");//销毁STDestory(&ps);
}int main()
{test1();
}

--测试完成,打印没有问题,先进的后出,退出码为0

获取栈中元素个数:

//求栈中有效数据个数
int STSize(ST* ps)
{assert(ps);return ps->top;
}

这个实现起来也是非常简单了,直接返回ps->top刚好就是有效元素个数 


 五.代码展现

Stack.h:

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>typedef int STDataType;
typedef struct Stack
{STDataType* arr;int top;int capacity;
}ST;//初始化
void STInit(ST* ps);
//销毁
void STDestory(ST* ps);
//入栈
void STPush(ST* ps, STDataType x);
//出栈
void STPop(ST* ps);
//取栈顶元素
STDataType STTop(ST* ps);
//判空
bool STEmpty(ST* ps);
//求栈中有效数据个数
int STSize(ST* ps);

Stack.c:

#include"stack.h"//初始化
void STInit(ST* ps)
{ps->arr = NULL;ps->top = ps->capacity = 0;
}//销毁
void STDestory(ST* ps)
{if (ps->arr)free(ps->arr);ps->arr = NULL;ps->top = 0;ps->capacity = 0;
}//入栈
void STPush(ST* ps, STDataType x)
{assert(ps);//检查空间//空间不够就增容if (ps->top == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;STDataType* tmp = (STDataType*)realloc(ps->arr, newcapacity * sizeof(STDataType));if (tmp == NULL){perror("realloc fail!");exit(1);}ps->arr = tmp;ps->capacity = newcapacity;}//空间足够ps->arr[ps->top++] = x;
}//判空
bool STEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}
//出栈
void STPop(ST* ps)
{assert(!STEmpty(ps));ps->top--;
}//取栈顶元素
STDataType STTop(ST* ps)
{assert(!STEmpty(ps));return 	ps->arr[ps->top - 1];;
}//求栈中有效数据个数
int STSize(ST* ps)
{assert(ps);return ps->top;
}

test.c:

#include"stack.h"void test1()
{ST ps;STInit(&ps);//入栈STPush(&ps, 1);STPush(&ps, 2);STPush(&ps, 3);STPush(&ps, 4);while (!STEmpty(&ps)){//取栈顶元素,打印STDataType top = STTop(&ps);printf("%d ", top);//出栈STPop(&ps);}printf("\n");//销毁STDestory(&ps);
}int main()
{test1();
}

往期回顾:

【数据结构初阶】--单链表(二)

【数据结构初阶】--双向链表(一)

【数据结构初阶】--双向链表(二)

结语:这篇博客我们完成了栈这个数据结构的实现,大家可以发现,有了前面的基础我们再来实现起来简直就是如鱼得水,很顺畅。那么我们在下篇博客中会继续队列这个数据结构的实现,如果文章对你有帮助的话,欢迎评论,点赞,收藏加关注,感谢大家的支持

http://www.lryc.cn/news/596631.html

相关文章:

  • 洛谷 B3939:[GESP样题 四级] 绝对素数 ← 素数判定+逆序整数
  • 二、PV输入升压电路
  • opencv-图像处理
  • Typecho三种版权保护方法对比与实战指南
  • ArKTS: DAL,Model,BLL,Interface,Factory using SQLite
  • 欧式装修颜色要怎么搭配?
  • 前端学习日记(十)
  • 【专题十三】队列 +宽搜
  • 3.5 模块化编程实践
  • 秋招Day17 - Spring - 事务
  • 使用 Ansys Fluent 软件参数化工作流程对搅拌罐中的稳态涡流进行仿真
  • 力扣 78.子集
  • ros0基础-day17
  • 电商项目_秒杀_架构及核心
  • Linux文件系统深入理解
  • 交叉编译opencv(Cpp)于arm64架构开发板上
  • 决策规划内容整理
  • 三轴云台之图像处理算法篇
  • 跨越语言壁垒!ZKmall开源商城多语言架构如何支撑电商全球化布局
  • Ext4文件系统全景解析
  • C++基础学习——文件操作详解
  • wangEditor5添加键盘事件/实现定时保存功能
  • 单张显卡运行多个vllm模型
  • 进程优先级切换调度-进程概念(6)
  • 【C++】继承和多态扩展学习
  • PyQt5在Pycharm上的环境搭建 -- Qt Designer + Pyuic + Pyrcc组合,大幅提升GUI开发效率
  • Qt多语言支持初步探索
  • 按键精灵脚本:自动化利刃的双面性 - 从技术原理到深度实践与反思
  • Web3面试题
  • 拥抱区块链红利:机遇无限,风险暗涌