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

C语言 之 【栈的简介、栈的实现(初始化、销毁、入栈、出栈、判空、栈的大小、访问栈顶元素、打印)】

目录

1.栈的简介

2.栈的实现

2.1实现须知

2.2头文件预览

2.2.1头文件细节

2.3 栈的初始化

2.4 栈的销毁

2.5 入栈

2.6 出栈

2.7 判空

2.8 栈的大小

2.9 访问栈顶元素

2.10 出栈的打印


1.栈的简介

栈是一种数据结构,是一种特殊的线性表,

栈只允许在一端进行插入和删除数据的操作

 进行数据插入和删除操作的一端称为栈顶,另一端称为栈底

栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。

可以把栈理解为一个垃圾桶,先丢进去的垃圾在桶底,

后丢进去的东西会覆盖在表面(即在桶顶)

只有先倒出桶顶的垃圾,才能倒出桶底的垃圾

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

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

 

2.栈的实现

2.1实现须知

前面说了,栈是是一种线性表,所以既可以用数组实现栈也可以用链表实现栈

但是,数组的缓存利用较高,所以选择用数组实现栈

显然,实践中都是按需申请空间,所以使用动态数组实现栈

2.2头文件预览

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>typedef int STDataType;
typedef struct Stack
{STDataType* a;int top;int capacity;
}ST;
//初始化
void StackInit(ST* st);
//销毁
void StackDestroy(ST* st);
//入栈
void StackPush(ST* st, STDataType val);
//出栈
void StackPop(ST* st);
//判空
bool STEmpty(ST* st);
//大小
int STSize(ST* st);
//访问栈顶元素
STDataType STTop(ST* st);

2.2.1头文件细节

(1)防止头文件内容在同一个编译单元内被多次展开

#pragma once

(2)包含必要的头文件(库函数、开空间、断言、布尔值)

(3)数据类型重命名,(以后只改这一处,就可以改变栈所存储的数据类型)

typedef int STDataType;

(4)与顺序表相同,多个数据存储在结构体中,其中

变量a,指向堆上一块用来存储数据的空间,

变量top,标明栈顶元素的位置或栈顶元素位置的下一个位置(依照具体实现而定)

变量capacity,标明栈的容量

(5)结构体typedef一下,不然名字太长了

(6)关于函数接口的设计

一:用户在函数外可以直接创建一个栈对象,然后传入它的地址,各函数用一级指针接收后,在函数内部使用指针就可以改变栈对象

二:如果用户在函数外创建的是一个栈类型的指针,初始化函数体内部就malloc一个栈对象,然后要么返回malloc后的指针,要么参数使用二级指针,以达到目的

方法一可以使各接口参数列表基本一致,所以我选择它(个人按需选择)

2.3 栈的初始化

void StackInit(ST* st)
{//传入的结构体指针一定不为空assert(st);//为栈存储数据开好空间,初始化的时候未指向有效内存,可以直接使用st->ast->a = (STDataType*)malloc(sizeof(STDataType) * 4);if (st->a == NULL){perror("malloc fail");exit(1);}st->capacity = 4;st->top = 0;     //栈顶元素的下一个位置,站的元素个数
}

 (1)结构体指针一定不为空,所以加断言

(1)最开始结构体中的变量a并未指向有效内存,可以直接用它接收返回值

(1)注意空间开辟失败的问题

top的初始值一般常取0 或1

(1)top == 0

此时 top 指向的是栈顶元素的下一个位置,因为

当第一个元素入栈时,top++,top的值就是1,正好是该元素下标的下一个位置

(2)top == -1

此时 top 指向的是栈顶元素的位置,因为

当第一个元素入栈时,top++,top的值就是0,正好是该元素的下标

2.4 栈的销毁

void StackDestroy(ST* st)
{assert(st);free(st->a);st->a = NULL;st->capacity = st->top = 0;
}

断言结构体指针,释放堆上申请的空间,还原成空对象即可

2.5 入栈

void StackPush(ST* st, STDataType val)
{assert(st);if (st->top == st->capacity){STDataType* temp = (STDataType*)realloc(st->a, sizeof(STDataType) * st->capacity * 2);if (temp == NULL){perror("realloc fail");exit(1);}st->a = temp;//谨防内存泄漏,需要使用临时变量st->capacity *= 2;}st->a[st->top] = val;st->top++;
}

(1)老生常谈,断言结构体指针

(2)入栈之前,判断一下扩容操作

1.top的值正好是栈中元素的个数,当个数等于容量时就进行扩容

2.可以进行2倍扩容,并注意使用临时变量接收返回值,防止接受失败导致内存泄漏

(3)top初始值是0,指向栈顶元素的下一个位置,那么直接在top位置插入元素

然后top++

2.6 出栈

void StackPop(ST* st)
{assert(st);assert(!STEmpty(st));st->top--;}

(1)结构体指针不为空,栈中必须有元素才能进行出栈操作

(2)堆上申请的是一段连续的空间,并不支持一段空间释放,

只要不太浪费内存,没必要重新开空间存储剩下的数据,直接top--

2.7 判空

bool STEmpty(ST* st)
{assert(st);return st->top == 0;
}

(1)判空结构体指针

(2)top的值就是栈中元素的个数

2.8 栈的大小

int STSize(ST* st)
{assert(st);return st->top;
}

(1)判空结构体指针

(2)top的值就是栈中元素的个数

2.9 访问栈顶元素

STDataType STTop(ST* st)
{assert(st);assert(!StackEmpty(st));return st->a[st->top - 1];
}

 (1)判空结构体指针

(2)top的初始值是0,是栈顶元素下标的后一个位置

2.10 栈的打印

栈并不支持遍历访问,只能访问栈顶元素即不提供遍历访问的接口

想要知道所有元素

只有边访问栈顶元素,边出栈

当然,如果需要保留元素,可提前保存一下

ST st;
StackInit(&st);
StackPush(&st, 1);
StackPush(&st, 2);
StackPush(&st, 3);
StackPush(&st, 4);
StackPush(&st, 5);
StackPush(&st, 6);while (!STEmpty(&st))
{printf("%d ", STTop(&st));StackPop(&st);
}

相关文章:

  • 【多线程】六、基于阻塞队列的生产者消费者模型
  • AI赋能新媒体运营:效率提升与能力突破实战指南
  • 【云盘】使用阿里云盘托管项目大文件
  • Rain World 雨世界 [DLC 解锁] [Steam Epic] [Windows SteamOS]
  • 【Linux系统】线程
  • LOJ #193 线段树历史和 Solution
  • 腾讯云服务器:bgp服务器搭建要怎么做?bgp服务器的应用有哪些?
  • 初始化列表详解
  • GPT-4o 图像生成与八个示例指南
  • 算法技巧——打表
  • 数字智慧方案5860丨智慧机场整体解决方案(41页PPT)(文末有下载方式)
  • Java大师成长计划之第10天:锁与原子操作
  • PINNs案例——多介质分区温度场
  • Nacos使用
  • DeepSeek实战--Function Calling
  • [官方 IP] Utility Flip-Flop
  • 不小心误删了文件,找Windows数据恢复工具来帮忙
  • 泰迪杯特等奖案例学习资料:基于CLIP模型微调与知识蒸馏的多模态图文检索系统设计
  • Linux-常用监控工具
  • 【Touching China】2002-2006
  • 南京大屠杀幸存者刘贵祥去世,享年95岁
  • 天津航空一航班盘旋14圈才降落,客服:因天气影响
  • 格桑花盛放上海,萨迦艺术团襄阳公园跳起藏族舞
  • 《水饺皇后》领跑五一档票房,《哪吒2》上座率仍居第一
  • 来上海喝云南咖啡!上海国际咖啡文化节助力咖啡产业破圈出海
  • 刘国中:毫不松懈巩固拓展脱贫攻坚成果,全力以赴抓好农业防灾减灾工作