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

相关推荐
秃头佛爷2 小时前
Python学习大纲总结及注意事项
开发语言·python·学习
dayouziei4 小时前
java的类加载机制的学习
java·学习
励志成为嵌入式工程师4 小时前
c语言简单编程练习9
c语言·开发语言·算法·vim
Peter_chq5 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
wheeldown6 小时前
【数据结构】选择排序
数据结构·算法·排序算法
hikktn7 小时前
如何在 Rust 中实现内存安全:与 C/C++ 的对比分析
c语言·安全·rust
观音山保我别报错7 小时前
C语言扫雷小游戏
c语言·开发语言·算法
dsywws7 小时前
Linux学习笔记之vim入门
linux·笔记·学习
晨曦_子画8 小时前
3种最难学习和最容易学习的 3 种编程语言
学习
城南vision8 小时前
Docker学习—Docker核心概念总结
java·学习·docker