[数据结构]栈详解

目录

一、栈的概念及其结构

二、栈的实现

[1.栈的初始化 void STInit(ST* ps);](#1.栈的初始化 void STInit(ST* ps);)

[2.栈的插入 void STPush(ST* ps, STDataType x);](#2.栈的插入 void STPush(ST* ps, STDataType x);)

[3.栈的删除 void STPop(ST* ps);](#3.栈的删除 void STPop(ST* ps);)

[4.栈的大小计算 int STSize(ST* ps);](#4.栈的大小计算 int STSize(ST* ps);)

[5.判断栈是否为空 bool STEmpty(ST* ps);](#5.判断栈是否为空 bool STEmpty(ST* ps);)

[6.栈的销毁 void STDestroy(ST* ps);](#6.栈的销毁 void STDestroy(ST* ps);)

[7.访问栈顶元素 STDataType STTop(ST* ps);](#7.访问栈顶元素 STDataType STTop(ST* ps);)

三、栈的操作合集

Stack.h

stack.c

test.c


一、栈的概念及其结构

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

二、栈的实现

栈的实现一般可以使用 数组或者链表实现 ,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小。

1.栈的初始化 void STInit(ST* ps);

复制代码
//栈的初始化
void STInit(ST* ps)
{
       assert(ps);
       ps->a = malloc(sizeof(STDataType) * 4);
       if (ps->a == NULL)
       {
              perror("malloc fail");
              return;
       }
       ps->capacity = 4;
       ps->top = 0;//代表top表示的是栈顶元素的下一个位置:刚开始top指向的是第一个元素,表示0,当第一个元素插入后top++表示1
}

2.栈的插入 void STPush(ST* ps, STDataType x);

复制代码
//栈的插入
void STPush(ST* ps, STDataType x)
{
       assert(ps);
       if (ps->top == ps->capacity)
       {
              STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) *  ps->capacity * 2);//扩容到当前的二倍
              if (tmp == NULL)
              {
                      perror("realloc fail");
                      return;
              }
                      ps->a = tmp;
                      ps->capacity *= 2;
       }
       ps->a[ps->top] = x;
       ps->top++;
}

3.栈的删除 void STPop(ST* ps);

复制代码
//栈的删除
void STPop(ST* ps)
{
       assert(ps);
       assert(!STEmpty(ps));
       ps->top--;
      
}

在栈操作函数中,栈指针 ps 是操作栈的基础,如果 ps 为 NULL,那么后续对 ps 指向的栈结构的任何访问(如 ps->top)都会导致未定义行为,通常是程序崩溃。因此,在进行栈操作之前,需要先确保 ps 不是 NULL,assert(!STEmpty(ps)); 实际上是在检查栈不为空的情况下才继续执行后续操作

4.栈的大小计算 int STSize(ST* ps);

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

5.判断栈是否为空 bool STEmpty(ST* ps);

复制代码
//判断栈是否为空
bool STEmpty(ST* ps)
{
       assert(ps);
       return ps->top == 0;
}

6.栈的销毁 void STDestroy(ST* ps);

复制代码
//栈的销毁
void STDestroy(ST* ps)
{
       assert(ps);
       free(ps->a);
       ps->a = NULL;
       ps->top = 0;
       ps->capacity = 0;
}

7.访问栈顶元素 STDataType STTop(ST* ps);

复制代码
//访问栈顶元素
STDataType STTop(ST* ps)
{
       assert(ps);
       assert(!STEmpty(ps));
       return ps->a[ps->top-1];
}

三、栈的操作合集

Stack.h

复制代码
#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
#define N 10
typedef int STDataType;
typedef struct Stack
{
       int* a;
       int top;//下标
       int capacity;
}ST;
//栈的初始化
void STInit(ST* ps);
//栈的插入
void STPush(ST* ps, STDataType x);
//栈的删除
void STPop(ST* ps);
//
int STSize(ST* ps);
//判断栈是否为空
bool STEmpty(ST* ps);
//栈的销毁
void STDestroy(ST* ps);
//访问栈顶元素
STDataType STTop(ST* ps);
//不支持打印,因为不能保证后进先出

stack.c

复制代码
#include"Stack.h"
//栈的初始化
void STInit(ST* ps)
{
       assert(ps);
       ps->a = malloc(sizeof(STDataType) * 4);
       if (ps->a == NULL)
       {
              perror("malloc fail");
              return;
       }
       ps->capacity = 4;
       ps->top = 0;//代表top表示的是栈顶元素的下一个位置:刚开始top指向的是第一个元素,表示0,当第一个元素插入后top++表示1
}
//栈的插入
void STPush(ST* ps, STDataType x)
{
       assert(ps);
       if (ps->top == ps->capacity)
       {
              STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) *  ps->capacity * 2);//扩容到当前的二倍
              if (tmp == NULL)
              {
                      perror("realloc fail");
                      return;
              }
                      ps->a = tmp;
                      ps->capacity *= 2;
       }
       ps->a[ps->top] = x;
       ps->top++;
}
//栈的删除
void STPop(ST* ps)
{
       assert(ps);
       assert(!STEmpty(ps));
       ps->top--;
       /*在栈操作函数中,栈指针 ps 是操作栈的基础,如果 ps 为 NULL,
              那么后续对 ps 指向的栈结构的任何访问(如 ps->top)都会导致未定义行为,
              通常是程序崩溃。因此,在进行栈操作之前,需要先确保 ps 不是 NULL
              assert(!STEmpty(ps)); 实际上是在检查栈不为空的情况下才继续执行后续操作*/
}
//
int STSize(ST* ps)
{
       assert(ps);
       return ps->top;
}
//判断栈是否为空
bool STEmpty(ST* ps)
{
       assert(ps);
       return ps->top == 0;
}
//栈的销毁
void STDestroy(ST* ps)
{
       assert(ps);
       free(ps->a);
       ps->a = NULL;
       ps->top = 0;
       ps->capacity = 0;
}
//访问栈顶元素
STDataType STTop(ST* ps)
{
       assert(ps);
       assert(!STEmpty(ps));
       return ps->a[ps->top-1];
}

test.c

复制代码
#include"Stack.h"
int main()
{
       ST st;
       STInit(&st);
       STPush(&st, 1);
       STPush(&st, 2);
       STPush(&st, 3);
       STPush(&st, 4);
       STPush(&st, 5);
       while (!STEmpty(&st))
       {
              printf("%d ", STTop(&st));
              STPop(&st);
       }
       STDestroy(&st);
}
相关推荐
想要成为糕糕手13 小时前
前端必修课:JavaScript 数组与数据结构底层逻辑全解析
javascript·数据结构·面试
tyung15 小时前
Go 手写 Wait-Free SPSC 无界队列:无 CAS、无锁、泛型节点池
数据结构·后端·go
Chen_harmony15 小时前
一、数据结构概念和复杂度计算
数据结构
小欣加油15 小时前
leetcode287寻找重复数
数据结构·c++·算法·leetcode
fie888917 小时前
LBP + HOG 特征检测与识别 MATLAB 实现
数据结构·算法·matlab
退休倒计时18 小时前
【每日一题】LeetCode 15. 三数之和 TypeScript
数据结构·算法·leetcode·typescript
AbandonForce19 小时前
滑动窗口:定长滑动窗口与不定长滑动窗口
数据结构·c++·算法
炸薯条!19 小时前
二叉树的链式表示(2)
java·数据结构·算法
YHHLAI20 小时前
JavaScript 数据结构精讲:数组底层与实战避坑
开发语言·javascript·数据结构
Coder-magician20 小时前
《代码随想录》刷题打卡day12:二叉树part02
数据结构·c++·算法