C语言【数据结构】--栈

目录

一、栈的概念及结构

二、栈的实现

三、栈的实现代码

栈的初始化

栈的销毁

入栈

删除数据

获取栈顶元素

判空

获取栈中有效元素个数

四、代码整合


一、栈的概念及结构

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。

栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则
压栈 :栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶
出栈 :栈的删除操作叫做出栈,出数据也在栈顶

栈遵循**后进先出,**可以理解为弹夹里的子弹,后装入的先打出去

二、栈的实现

栈的实现一般可以使用 数组或者链表实现, 相对而言数组的结构实现更优一些**。因为栈只会在一端进行插入和删除操作** ,用数组效率还是比较高,数组在尾上插入数据的代价比较小。当然,也会存在一些问题,就是每次空间不够,要重新开辟空间,可能会造成一些内存浪费。

栈的顺序储存结构

数组的首元素作为栈底,另外一端作为栈顶,同时定义一个变量 top 来记录栈顶元素在数组中的位置


栈的链表存储结构

单链表的尾部作为栈底,头部作为栈顶,方便插入和删除(进栈头插,出栈头删),头指针和栈顶指针 top 合二为一

三、栈的实现代码

要实现一个栈,我们先梳理一下基本结构,我们还是分两个源文件 "text.c(测试),Stack.c(函数的定义) "和一个头文件(Stack.h)函数的声明.

静态栈在现实中并没有动态栈实用,所以我主要讲一下动态栈

函数的定义和声明

cpp 复制代码
// 下面是定长的静态栈的结构,实际中一般不实用,所以我们主要实现下面的支持动态增长的栈
typedef int STDataType;
#define N 10
typedef struct Stack
{
    STDataType a[N];
    int top; // 栈顶
}Stack;
// 支持动态增长的栈
typedef int STDataType;
typedef struct Stack
{
    STDataType* a;
    int top; // 栈顶
    int capacity; // 容量
}Stack;
    // 初始化栈
    void StackInit(Stack* pst);
    // 入栈
    void StackPush(Stack* pst, STDataType data);
    // 出栈
    void StackPop(Stack* pst);
    // 获取栈顶元素
    STDataType StackTop(Stack* pst);
    // 获取栈中有效元素个数
    int StackSize(Stack* ps);
    // 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
    int StackEmpty(Stack* pst);
    // 销毁栈
    void StackDestroy(Stack* pst);

栈的初始化

cpp 复制代码
void STInit(ST* pst)
{
    assert(pst);
    pst->a = NULL;

    pst->top = 0;//top指向栈顶数据的下一个
    //ps->top = -1; // 意味着top指向栈顶数据

    pst->capacity = 0;
}

栈的销毁

cpp 复制代码
void STDestroy(ST* pst)
{
    assert(pst);
    free(pst->a);
    pst->a = NULL;
    pst->top = pst->capacity = 0;
}

入栈

cpp 复制代码
void STPush(ST* pst)
{
    assert(pst);
    
    if(pst->top == pst->capacity)//检查栈空间是否满了
    {
        int newcapacity = pst->capacity == 0 ? 4 pst->capacity * 2;
        STDataType* tmp = (STDataType*)realloc(pst->a,newcapacity * sizeof(STDataType);// 扩容至新容量
        if(tmp == 0)
            {
                perror("realloc fail");
                return;
            }
        pst->a = tmp;
        pst->capacity = newcapacity; // 更新容量
    }
    pst->a[pst->top] = x; // 将新增元素放入栈顶空间
    pst->top++;// 栈顶指针加一
}

删除数据

cpp 复制代码
void STPop(SL* pst)
{
    assert(pst);
    assert(pst->top > 0); //栈不能为空
    pst->top--; // 栈顶指针减一,相当于直接覆盖元素
}

获取栈顶元素

cpp 复制代码
STDataType STTop(ST* pst)
{
    assert(pst);
    assert(pst->top > 0);
    
    return pst->a[pst->top - 1];
}

判空

cpp 复制代码
bool SREmpty(ST* pst)
{
    assert(pst);
    return pst->top == 0; //看top是否变回初始化的值
}

获取栈中有效元素个数

cpp 复制代码
int STSize(ST* pst)
{
    assert(pst);
    return pst->top;
}

四、代码整合

Stack.h

cpp 复制代码
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>

typedef struct Stack
{
    STDataType a[N];
    int top; // 栈顶
}Stack;
// 初始化和销毁
void STInit(ST* pst);
void STDestroy(ST* pst);
 
// 入栈  出栈
void STPush(ST* pst, STDataType x);
void STPop(ST* pst);
 
// 取栈顶数据
STDataType STTop(ST* pst);
 
// 判空
bool STEmpty(ST* pst);
// 获取数据个数
int STSize(ST* pst);

Stac.c

cpp 复制代码
#include"Stack.h"
 
// 初始化和销毁
void STInit(ST* pst)
{
	assert(pst);
 
	pst->a = NULL;
	// top指向栈顶数据的下一个位置
	pst->top = 0;
	pst->capacity = 0;
}
 
void STDestroy(ST* pst)
{
	assert(pst);
 
	free(pst->a);
	pst->a = NULL;
	pst->top = pst->capacity = 0;
}
 
// 入栈  出栈
void STPush(ST* pst, STDataType x)
{
	assert(pst);
 
	// 扩容
	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
 
		pst->a = tmp;
		pst->capacity = newcapacity;
	}
 
	pst->a[pst->top] = x;
	pst->top++;
}
 
void STPop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);
 
	pst->top--;
}
 
 
// 取栈顶数据
STDataType STTop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);
 
	return pst->a[pst->top - 1];
}
 
// 判空
bool STEmpty(ST* pst)
{
	assert(pst);
 
	return pst->top == 0;
}
 
// 获取数据个数
int STSize(ST* pst)
{
	assert(pst);
 
	return pst->top;
}

text.c

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

int main()
{
	// 入栈:1 2 3 4
	// 出栈:4 3 2 1  /  2 4 3 1
	ST s;
	STInit(&s);
	STPush(&s, 1);
	STPush(&s, 2);
	STPush(&s, 3);
	STPush(&s, 4);
 
	printf("%d ", STTop(&s));
	STPop(&s);
 
	STPush(&s, 5);
	STPush(&s, 6);
 
	while (!STEmpty(&s))
	{
		printf("%d ", STTop(&s));
		STPop(&s);
	}
 
	STDestroy(&s);
}

本篇到这里就结束了,如有问题欢迎在评论区指正!

个人主页:uyeonashi-CSDN博客

相关推荐
Fanxt_Ja1 天前
【LeetCode】算法详解#15 ---环形链表II
数据结构·算法·leetcode·链表
2303_Alpha1 天前
SpringBoot
笔记·学习
萘柰奈1 天前
Unity学习----【进阶】TextMeshPro学习(三)--进阶知识点(TMP基础设置,材质球相关,两个辅助工具类)
学习·unity
沐矢羽1 天前
Tomcat PUT方法任意写文件漏洞学习
学习·tomcat
好奇龙猫1 天前
日语学习-日语知识点小记-进阶-JLPT-N1阶段蓝宝书,共120语法(10):91-100语法+考え方13
学习
今后1231 天前
【数据结构】二叉树的概念
数据结构·二叉树
向阳花开_miemie1 天前
Android音频学习(十八)——混音流程
学习·音视频
小莞尔1 天前
【51单片机】【protues仿真】基于51单片机的篮球计时计分器系统
c语言·stm32·单片机·嵌入式硬件·51单片机
工大一只猿1 天前
51单片机学习
嵌入式硬件·学习·51单片机
小莞尔1 天前
【51单片机】【protues仿真】 基于51单片机八路抢答器系统
c语言·开发语言·单片机·嵌入式硬件·51单片机