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

目录

一、栈的概念及结构

二、栈的实现

三、栈的实现代码

栈的初始化

栈的销毁

入栈

删除数据

获取栈顶元素

判空

获取栈中有效元素个数

四、代码整合


一、栈的概念及结构

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

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

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

二、栈的实现

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

栈的顺序储存结构

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


栈的链表存储结构

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

三、栈的实现代码

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

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

函数的定义和声明

// 下面是定长的静态栈的结构,实际中一般不实用,所以我们主要实现下面的支持动态增长的栈
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);

栈的初始化

void STInit(ST* pst)
{
    assert(pst);
    pst->a = NULL;

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

    pst->capacity = 0;
}

栈的销毁

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

入栈

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++;// 栈顶指针加一
}

删除数据

void STPop(SL* 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 SREmpty(ST* pst)
{
    assert(pst);
    return pst->top == 0; //看top是否变回初始化的值
}

获取栈中有效元素个数

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

四、代码整合

Stack.h


#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

#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

#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博客

                                                       

  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值