[数据结构]栈详解

目录

一、栈的概念及其结构

二、栈的实现

[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);
}
相关推荐
charliejohn15 小时前
计算机考研 408 数据结构 树形查找 相关概念及计算题例题
数据结构·考研
Doro再努力1 天前
【数据结构08】队列实现及练习
数据结构·算法
Jayden_Ruan1 天前
C++分解质因数
数据结构·c++·算法
bubiyoushang8881 天前
MATLAB实现雷达恒虚警检测
数据结构·算法·matlab
wu_asia1 天前
编程技巧:如何高效输出特定倍数数列
c语言·数据结构·算法
星火开发设计1 天前
C++ queue 全面解析与实战指南
java·开发语言·数据结构·c++·学习·知识·队列
橘颂TA1 天前
【剑斩OFFER】算法的暴力美学——力扣 394 题:字符串解码
数据结构·c++·结构与算法
星火开发设计1 天前
C++ list 全面解析与实战指南
开发语言·数据结构·c++·学习·list·知识
栈与堆1 天前
LeetCode 19 - 删除链表的倒数第N个节点
java·开发语言·数据结构·python·算法·leetcode·链表
-森屿安年-1 天前
unordered_map 和 unordered_set 的实现
数据结构·c++·散列表