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

发布于:2025-08-09 ⋅ 阅读:(18) ⋅ 点赞:(0)

😘个人主页@Cx330❀

👀个人简介一个正在努力奋斗逆天改命的二本觉悟生

📖个人专栏:《C语言》《LeetCode刷题集》《数据结构-初阶》

前言:在之前几篇博客中,我们学习了顺序表和链表,接下来我们将学习栈的相关知识,希望大家继续坚持下去🌹🌹🌹


目录

一、栈的概念与结构

二、栈的初始化和销毁

注意事项:

三、、入栈

四、出栈

五、取栈顶元素

注意事项:

测试结果:

六、获取栈中元素个数

七、全部代码实现

Stack.h:

Stack.c:

test.c:


一、栈的概念与结构

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

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

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

例子:我们可以将栈想象为水杯,水杯的地步就是栈底,开口的地方就是栈顶,在水杯里面放石头,直到放满为止,先放进杯子的石头是最后才能拿出来的。

注意:栈的实现一般可以用数组或者链表来实现,但是相对而言数组的结构实现更优一些,将数组的尾部作为栈顶,数组的头部作为栈顶,插入删除数据的时间复杂度都为O(1),但是链表使用头部也可以进行插入删除,时间复杂度也为O(1),但是每次插入都会申请一个节点大小的空间,在空间上相对而言,数组的结构更加优秀

栈的结构:

//定义栈的结构
typedef int STDataType;
typedef struct Stack
{
	STDataType* arr;
	int top;//指向栈顶的位置--刚好就是栈中有效数据个数
	int capacity;//栈的空间大小
}ST;

二、栈的初始化和销毁

初始化:

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

销毁:

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

注意事项:

这里的结构和顺序表几乎是一样的,但是为了区分size,这里我们使用top作为栈顶


三、、入栈

//入栈--栈顶
void STPush(ST* ps, STDataType x)
{
	assert(ps);
	//判断空间是否足够
	if (ps->capacity == ps->top)
	{
		//增容
		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;
}

相信大家看到这些代码的时候并不陌生,这里的逻辑和顺序表几乎一模一样,当在栈中插入数据时,由于栈顶插入,所以要先判断栈的空间是否足够,若不够先增容,足够的话就将x赋给ps->arr[ps->top++]就可以了


四、出栈

在出栈之前首先要判断栈是否为空,若不为空才可以进行出栈操作,所以这里封装一个判空的接口

//栈是否为空
bool STEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;//栈顶为0,栈就为空
}

出栈:

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

栈不为空,直接让ps->top--就可以了,非常简单


五、取栈顶元素

//取栈顶元素
STDataType STTop(ST* ps)
{
	assert(!STEmpty(ps));
	return ps->arr[ps->top-1];//易错top是空的,top-1才是栈顶元素
}

注意事项:

这里要注意的是,top是栈顶,而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();
}

测试结果:


六、获取栈中元素个数

//获取栈中有效数据个数
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 STDesTroy(ST* ps);
//入栈--栈顶
void STPush(ST* ps, STDataType x);
//栈是否为空
bool STEmpty(ST* ps);
//出栈--栈顶
void STPop(ST* ps);
//取栈顶元素
STDataType STTop(ST* ps);

Stack.c:

#include"stack.h"
//初始化
void STInit(ST* ps)
{
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}
//销毁
void STDesTroy(ST* 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 : 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];//易错top是空的,top-1才是栈顶元素
}

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

test.c:

#include"stack.h"
void test01()
{
	ST st;
	STInit(&st);
	STPush(&st, 1);
	STPush(&st, 2);
	STPush(&st, 3);
	STPush(&st, 4);
	
	printf("size:%d\n", STSize(&st));
	while (!STEmpty(&st))
	{
		//取栈顶
		STDataType top = STTop(&st);
		printf("%d ", top);
		//出栈
		STPop(&st);
	}
	printf("\n");
	STDesTroy(&st);
}
int main()
{
	test01();
	return 0;
}

往期回顾:

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

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

总结:这篇博客带着给大家实现了栈的全部接口了,其实可以看出来栈的结构很简单,但是大家不能眼高手低,下去一定要自己画图操作,那么下篇博客将带着大家实现队列,大家敬请期待!如果文章对你有帮助的话,欢迎评论,点赞,收藏加关注,感谢大家的支持🌹🌹🌹


网站公告

今日签到

点亮在社区的每一天
去签到