【数据结构】【版本1.3】【线性时代】——地下栈域

简介: 【数据结构】【版本1.3】【线性时代】——地下栈域

引言

数据结构世界拥有链表后,就迎来了一种特殊的线性表——Stack


数据结构世界在完整拥有了顺序和链式的力量后,开始孕育山川大泽,世间万物。在千百年后,一个庞大的地下洞穴空间展现在世人眼前——地下栈域,里面拥有奇特的法则——后进先出


一、栈的概念与结构

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

压栈: 栈的插入操作叫做进栈 / 压栈 / 入栈, 入数据在栈顶

出栈: 栈的删除操作叫做出栈。 出数据也在栈顶

image

image

二、栈的实现

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

image

2.1 定义 

这里,当前元素个数用栈顶top来表示,是栈独有的表示方法  

image


2.2 初始化

栈的初始化,top可以为0或-1,top为0,则指向栈顶元素的下一个位置,top为-1,则指向栈顶元素的位置。这里选用top为0,因为后面写的适合方便理解 

image

2.3 销毁

栈的销毁和顺序表一样,直接释放数组空间即可  

image

2.4 压栈

 压栈前,先判断是否需要扩容,再将元素压栈。因为这里只有压栈函数需要判断扩容,所以就不用专门再写一个扩容函数 

这里realloc函数在pst为NULL时,充当malloc的作用,所以既可以为初始栈开辟空间,又可以扩容 

image

2.5 检测栈是否为空 

专门写一个函数判断,增强复用性可读性 。如果top为0,则栈为空,返回真;反之,返回假 

image

2.6 出栈 

出栈前,先assert断言判断,栈是否为空,因为top不能减到负数  

image

2.7 获取栈顶元素

同样,先判断栈是否为空,再返回栈顶元素。因为这里top指向的是栈顶元素的下一位,所以下标访问时top要减一  

image

2.8 检测栈中有效元素个数

image

这里很多函数实现都很简单,有些操作直接外部对结构体都可以直接实现,但最后还是写成函数封装,因为top的含义有多重,防止别人使用时误解,导致使用错误  

2.9 元素访问 

栈中元素访问(打印),不是用函数实现。因为它的特殊结构,决定了它的元素不能从任意位置访问 ,必须符合后进先出原则才可以。所以,我们通常用循环的方式进行访问,同时每访问一个元素,就将它弹出栈,在进行下一个元素的访问。 

image

以及变式

image

有人可能会疑惑,将元素访问以后就弹出栈,不进行其他操作吗?其实,在实际生产中,栈也是这样实现特定的需求的。  

这样我们就实现了增删等功能

三、栈oj题

仅仅了解栈的知识是不够的,让我们来刷刷题吧!

20.有效的括号(LeetCode)-CSDN博客

232.用栈实现队列(LeetCode)-CSDN博客

225.用队列实现栈(LeetCode)-CSDN博客

看到这里了还不给博主扣个:
⛳️ 点赞☀️收藏 ⭐️ 关注

💛 💙 💜 ❤️ 💚💓 💗 💕 💞 💘 💖

拜托拜托这个真的很重要!

你们的点赞就是博主更新最大的动力!

有问题可以评论或者私信呢秒回哦。

源代码

stack.h

#pragma once
#include<stdio.h>
#include<stdbool.h>
#include<assert.h>
#include<stdlib.h>
 
typedef int STDataType;
typedef struct Stack
{
    STDataType* a;
    int top;
    int capacity;
}ST;
 
//初始化
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);

stack.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"stack.h"
 
void STInit(ST* pst)
{
    assert(pst);
    
    pst->a = NULL;
    pst->top = 0;//top指向栈顶元素的下一个位置
    pst->capacity = 0;
}
 
void STDestroy(ST* pst)
{
    assert(pst);
    
    free(pst->a);
    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;
}
 
void STPop(ST* pst)
{
    assert(pst);
    assert(!STEmpty(pst));
    
    pst->top--;
}
 
STDataType STTop(ST* pst)
{
    assert(pst);
    assert(!STEmpty(pst));
    
    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;
}

test.c 

#define _CRT_SECURE_NO_WARNINGS 1
#include"stack.h"
 
void TestStack1()
{
    ST st;
    //初始化
    STInit(&st);
    //压栈
    STPush(&st, 1);
    STPush(&st, 2);
    printf("%d\n", STTop(&st));
    STPop(&st);
    STPush(&st, 3);
    STPush(&st, 4);
    STPush(&st, 5);
    //打印
    while (!STEmpty(&st))
    {
        printf("%d\n", STTop(&st));
        STPop(&st);
    }
    //销毁
    STDestroy(&st);
}
 
int main()
{
    TestStack1();
    return 0;
}


相关文章
|
5月前
|
存储 C语言
数据结构中的线性表链式存储介绍及其基本操作
链式存储是线性表的一种重要存储方式,它通过节点和指针的结构,实现了灵活的动态存储管理。本文介绍了单向链表的基本操作,并提供了相应的C语言代码示例。理解和掌握链表的操作对学习和应用数据结构具有重要意义。希望这篇博客能帮助你更好地理解线性表的链式存储。
124 2
|
2月前
|
存储 Java
java数据结构,线性表链式存储(单链表)的实现
文章讲解了单链表的基本概念和Java实现,包括头指针、尾节点和节点结构。提供了实现代码,包括数据结构、接口定义和具体实现类。通过测试代码演示了单链表的基本操作,如添加、删除、更新和查找元素,并总结了操作的时间复杂度。
java数据结构,线性表链式存储(单链表)的实现
|
2月前
|
机器学习/深度学习 算法 Java
[算法与数据结构] 谈谈线性查找法~
该文章详细介绍了线性查找法的基本概念与实现方法,通过Java代码示例解释了如何在一个数组中查找特定元素,并分析了该算法的时间复杂度。
|
3月前
|
存储
数据结构中的 线性结构和非线性结构
这篇文章介绍了数据结构中的线性结构和非线性结构,其中线性结构包括顺序存储结构和链式存储结构,如数组、队列、链表和栈;非线性结构包括图结构、树结构、二维数组、广义表和多维数组。
|
5月前
|
存储 算法 NoSQL
数据结构和算法——哈希查找冲突处理方法(开放地址法-线性探测、平方探测、双散列探测、再散列,分离链接法)
数据结构和算法——哈希查找冲突处理方法(开放地址法-线性探测、平方探测、双散列探测、再散列,分离链接法)
124 1
|
5月前
|
存储 算法 Java
Java数据结构与算法:线性数据结构之数组
Java数据结构与算法:线性数据结构之数组
|
6月前
|
存储
【数据结构】【版本1.1】【线性时代】——链式之力
【数据结构】【版本1.1】【线性时代】——链式之力
【数据结构】【版本1.1】【线性时代】——链式之力
|
6月前
|
C语言
【C语言/数据结构】排序(快速排序及多种优化|递归及非递归版本)
【C语言/数据结构】排序(快速排序及多种优化|递归及非递归版本)
45 0
|
6月前
|
存储 算法 程序员
【数据结构】【版本2.0】【树形深渊】——二叉树入侵
【数据结构】【版本2.0】【树形深渊】——二叉树入侵
|
6月前
【数据结构】【版本1.4】【线性时代】——公平队列
【数据结构】【版本1.4】【线性时代】——公平队列