数据结构:栈与队列之栈的实现

之前我们学习了线性表,了解了线性表的结构与实现、应用场景,现在我们来学习栈和队列,本篇文章带你从零搞定栈。

栈的概念

栈是一种特殊的线性表,它在一端插入和删除数据,这端称为栈顶另一端就叫做栈底。栈遵循"先入后出"(也可以是后入先出)的原则。

我们可以把栈看做一个水杯,只有一端开口,里面存放的东西是线性的。

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

出栈:从栈顶删除元素的操作叫做出栈。

比如这张图中,我们按1 2 3 4 5入栈,出栈的顺序就变成了5 4 3 2 1,这说明了栈是先入后出的。当栈中没有数据的时候,栈顶和栈底是相等的。

我们知道线性表在逻辑结构上是线性的,物理结构上顺序表是连续的,链表不一定,那么我们采用哪种结构来实现栈呢?

栈的底层结构

如果我们用顺序表来实现栈 ,把数组开头看做栈底,数组末尾看做栈顶:

出栈和入栈都在栈顶操作,而在数组末尾插入和删除数据的时间复杂度均为O(1)。

如果我们用链表来实现栈,把头结点看成栈顶,尾结点看成栈底:

在栈顶(头结点)进行入栈和出栈操作时间复杂度也均为O(1)。

在空间不够时,顺序表要进行扩容,而链表每次插入一个新结点都要申请一个结点的空间,相比之下用顺序表来实现栈更合适些。

我们知道顺序表的结构是:

c 复制代码
struct List
{
      int* arr;//指向数组的指针
      int size=0;//有效元素个数
      int capacity;//容量大小
};

相似的,因为栈都是对栈顶进行操作,所以我们定义一个top来表示栈顶,同时也是栈中有效元素个数:

入栈的时候就往top这个位置插入数据就好了。

栈的结构如下:

c 复制代码
struct Stack
{
   int* arr;//指向数组的指针
   int top;//栈顶
   int capacity;//容量
};

然后我们就可以来实现栈了。

栈的实现

我们依然定义一个头文件Stack.h来声明栈的结构和它的接口函数(初始化、入栈、出栈等),一个源文件Stack.c来实现栈的接口函数,一个源文件main.c用来进行测试。

c 复制代码
Stack.h
#pragma once

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

//栈的结构
typedef int SDataType;//数据类型重命名

typedef struct Stack
{
	SDataType* arr;
	int top;//栈顶
	int capacity;//容量
}Stack;

//初始化
void StackInit(Stack* ps);
//入栈
void StackPush(Stack* ps, SDataType x);
//出栈
void StackPop(Stack* ps);
//销毁
void StackDestroy(Stack* ps);
//栈是否为空
bool StackEmpty(Stack* ps);
//返回栈顶元素
SDataType StackTop(Stack* ps);
//有效元素个数
int StackSize(Stack* ps);

初始化

初始化就是把arr置为NULL,top,capacity置为0就好了。

入栈

入栈就是在栈顶插入元素,在插入元素之前,我们要先判断是否要进行扩容。

当top==capacity时,说明栈空间已满或者是还未开辟空间。

第一次我们就选择开辟4个数据的空间大小,后续扩容选择扩充为原来capacity的两倍。

c 复制代码
//判断是否需要扩容
if (ps->capacity == ps->top)
{
	//判断是否为第一次扩容
	int Newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
	//扩容
	SDataType* p = (SDataType*)realloc(ps->arr, Newcapacity * sizeof(SDataType));
	if (p == NULL)
	{
		perror("realloc");
		exit(-1);
	}
	ps->capacity = Newcapacity;
	ps->arr = p;
	p = NULL;
}

然后就可以进行入栈操作了,入栈操作很简单,只需要把数据插入到top位置上,top++就好了。

代码如下:

判空

判断是否为空栈,只需要判断ps->top==0这个表达式结果是否为真,表达式结果为真则返回true,否则返回false。

出栈

出栈就是在栈顶删除元素,top--就好了,就代表把最后一个元素抛弃了。

需要确保不是空栈。

销毁

销毁就是把数组arr内存释放掉,然后把arr置为NULL,top和capacity置为0就好了。

有效元素个数

top就是有效元素个数。

返回栈顶元素

需要确保不是空栈。

测试

c 复制代码
#include"Stack.h"

void test()
{
	Stack st;
	//初始化
	StackInit(&st);
	//入栈
	StackPush(&st, 1);
	StackPush(&st, 2);
	StackPush(&st, 3);
	StackPush(&st, 4);
	StackPush(&st, 5);
	//取栈顶元素
	printf("Top:%d\n", StackTop(&st));
	//出栈
	StackPop(&st);
	StackPop(&st);
	StackPop(&st);
	//取栈顶元素
	printf("Top:%d\n", StackTop(&st));
	//有效元素个数
	printf("Size:%d\n", StackSize(&st));
	//销毁
	StackDestroy(&st);
}

int main()
{
	test();
	return 0;
}
相关推荐
小小龙学IT2 小时前
C++ 并发编程深度解析:从内存模型到无锁数据结构
数据结构·c++
变量未定义~3 小时前
单调栈、单调队列(模板)、子矩阵(模板)
数据结构·算法·蓝桥杯
不会就选b4 小时前
算法日常・每日刷题--<快速排序>2
数据结构·算法
kyle~5 小时前
Schema---数据结构的形式化规则描述
数据结构·windows·microsoft
李小小钦6 小时前
D. Storming Arasaka(Codeforces 2238)
c语言·开发语言·数据结构·c++·算法
先吃饱再说6 小时前
一篇吃透树的遍历:递归与迭代的完整拆解
数据结构·算法
gugucoding19 小时前
31. 【C语言】堆栈与队列的实现
c语言·开发语言·数据结构·链表
ChaoZiLL20 小时前
我的数据结构3——链表(link list)
数据结构·链表
王老师青少年编程1 天前
2026年6月GESP真题及题解(C++七级):消消乐
数据结构·c++·算法·真题·gesp·2026年6月