栈的原理与应用

栈的原理与应用


大家学习数据结构的目的是为了更好的处理和存储数据,对于顺序表而言改查比较容易,增删比较麻烦,对于链式表而言,增删比较简单,改查比较麻烦,所以每种数据结构都有不同的特点,用户需要选择合适的数据结构。

linux内存分区,栈内存自顶向下进行递增,其实栈和顺序表以及链式表都一样,都属于线性结构,存储的数据的逻辑关系也是一对一的。

image

只不过栈是一种特殊的线性表,特殊在栈的一端是封闭的,数据的插入与删除只能在栈的另一端进行,也就是栈遵循“*后进先出*”的原则。也被成为“LIFO”结构,意思是“last input first output”。

栈(stack),存储货物或供旅客住宿的地方,可引申为仓库、中转站,所以引入到计算机领域里,就是指数据暂时存储的地方,所以才有进栈(PUSH)、出栈(POP)的说法。

栈就像是一摞书,拿到新书时我们会把它放在书堆的最上面,取书时也只能从最上面的新书开始取。

image

闭合的一端被称为栈底(Stack Bottom),允许数据的插入与删除的一端被称为栈顶(Stack Top),不包含任何元素的栈被称为空栈。把数据插入到栈空间的动作被称为入栈或者压栈

image

l 从栈空间中删除数据的动作被称为出栈或者弹栈

image

由于栈也是一种线性结构,所以可以以数组或者链表作为基础,在此基础上实现栈的操作。

  1. 以数组作为基础实现栈空间(顺序栈)

数组在内存中占用一块连续的空间,也就是数组元素的内存地址是连续的。为了实现栈,一般是把数组头作为栈底,数组头部到数组尾部作为栈的增长方向,也就是用户只在数组尾部对数据进行插入和删除。

image

//指的是顺序栈中的元素的数据类型,用户可以根据需要进行修改

typedef int  DataType_t;

//构造记录顺序栈SequenceStack各项参数(栈底地址+栈容量+栈顶元素的下标)的结构体

typedef struct SequenceStack

{

​	DataType_t * Bottom;     //记录栈底地址unsigned int Size;      //记录栈容量int      Top;      //记录栈顶元素的下标 

}SeqStack_t;

(1) 创建一个空的顺序栈,并为记录顺序栈信息的结构体申请堆内存,并进行初始化即可!

/**

  * @function name      :SeqStack_Create
  * @brief              :创建顺序表并对顺序栈进行初始化
  * @param              :unsigned int size
  * @retval             :SeqStack_t结构体指针
  * @date               :2024/04/25
  * @version 1.0        :V1.0
  * @note               :None
    */

//创建顺序表并对顺序栈进行初始化   为了方便管理顺序栈所以需要构造管理顺序栈信息的结构体类型,用于记录重要参数
SeqStack_t * SeqStack_Create(unsigned int size)
{
    //1.利用calloc为顺序栈的管理结构体申请一块堆内存
    SeqStack_t *Manager = (SeqStack_t *)calloc(1,sizeof(SeqStack_t));

​    if(NULL == Manager)
​    {
​        perror("calloc memory for manager is failed");
​        exit(-1); //程序异常终止
​    }

​    //2.利用calloc为所有元素申请堆内存
​    Manager->Bottom = (DataType_t *)calloc(size,sizeof(DataType_t));

​    if (NULL == Manager->Bottom)
​    {
​        perror("calloc memory for Stack is failed");
​        free(Manager);
​        exit(-1); //程序异常终止
​    }

​    //3.对管理顺序栈的结构体进行初始化(元素容量 + 最后元素下标)
​    Manager->Size = size;   //对顺序栈中的容量进行初始化
​    Manager->Top = -1;      //由于顺序栈为空,则栈顶元素的下标初值为-1
​    
​    return Manager;
}

(2)判断顺序栈是否为已满

/**

  * @function name      :SeqStack_IsFull
  * @brief              :判断顺序栈是否已满
  * @param              :SeqStack_t *Manager
  * @retval             :布尔类型
  * @date               :2024/04/25
  * @version 1.0        :V1.0
  * @note               :None
    */

//判断顺序栈是否已满
bool SeqStack_IsFull(SeqStack_t *Manager)
{
    return (Manager->Top + 1 == Manager->Size) ? true : false;
}

(3)根据栈的特性,把新元素从栈顶入栈,也就是从数组的尾部进行元素插入

/**

  * @function name      :SeqStack_Push
  * @brief              :压栈(push)
  * @param              :SeqStack_t *Manager, DataType_t Data
  * @retval             :布尔类型
  * @date               :2024/04/25
  * @version 1.0        :V1.0
  * @note               :None
    */

//入栈
bool SeqStack_Push(SeqStack_t *Manager, DataType_t Data)
{
    //1.判断顺序栈是否已满
    if ( SeqStack_IsFull(Manager) )
    {
        printf("SeqStack Full is Full!\n");
        return false;
    }

​    //2.如果顺序栈有空闲空间,则把新元素添加到顺序栈的栈顶
​    Manager->Bottom[++Manager->Top] = Data;

​    return true;
}


(4)判断顺序栈是否为空

/**

  * @function name      :SeqStack_IsEmpty
  * @brief              :判断顺序栈是否为空
  * @param              :SeqStack_t *Manager
  * @retval             :布尔类型
  * @date               :2024/04/25
  * @version 1.0        :V1.0
  * @note               :None
    */

//判断顺序栈是否为空
bool SeqStack_IsEmpty(SeqStack_t *Manager)
{
    return (-1 == Manager->Top) ? true : false;
}

(5)根据栈的特性,把元素从栈顶出栈,也就是把元素从数组的尾部把元素删除

//出栈

DataType_t SeqStack_Pop(SeqStack_t *Manager)

{

  DataType_t temp = 0;  //用于存储出栈元素的值

  //1.判断顺序栈是否为空

  if ( SeqStack_IsEmpty(Manager) )

  {

​    printf("SeqStack is Empty!\n");

​    return;

  }

  

  //2.由于删除了一个元素,则需要让顺序栈的栈顶元素下标-1

  temp = Manager->Bottom[Manager->Top--];

  return temp;

}


(6)遍历顺序栈的元素

/**

  * @function name      SeqStack_Print
  * @brief              :遍历顺序栈
  * @param              :SeqStack_t *Manager
  * @retval             :None
  * @date               :2024/04/25
  * @version 1.0        :V1.0
  * @note               :None
    */

//遍历顺序栈的元素
void SeqStack_Print(SeqStack_t *Manager)
{
    for (int i = 0; i <= Manager->Top; ++i)
    {
        printf(" Stack Element[%d] = %d\n",i,Manager->Bottom[i]);
    }
}


posted @   WJnuHhail  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示