链式栈初始化以及入栈出栈代码

链式栈初始化以及入栈出栈代码

image

整体设计思路

  • 为了方便管理链式栈,我们创建了链式栈的节点以及管理结构体。其中管理结构体包含了栈顶的地址以及栈的大小(由于是链式结构因此不必提取申请一块固定大小的内存),栈节点结构体包含了数据域以及next指针。
  • Note:在遍历整个链式栈的时候,必须必须必须创建一块临时的指针来保存栈顶的地址,为了防止在遍历过程中栈顶节点的丢失。例如我们如果不就行保存,在每次遍历之后必定会使用stack->top=stack->top->next,如果首这样,那么原来的那个栈顶节点的地址就会丢失。

代码展示


/********************************************************************************************************
 *
 * file name  :   链式栈.c
 * author     :   xu1234xcs@163.com
 * data       :   2025.5.12
 * function   :   该程序实现链式栈栈元素的增删改查,目的是提高设计程序的逻辑思维
 * note       :   为了提高可移植性,所以链式栈中元素的数据类型为DataType_t,用户可以根据实际情况修					 改链式表中元素的类型。
 *                另外,为了方便管理链式栈,所以用户设计LinkStack_t结构体,该结构体中包含两个成员:				  栈容量+栈顶元素的地址
 *                对于单个链节点的结构体,该结构体中包括数据域以及其next地址
 *
 * Copyright (c)  2024-2025  xu1234xcs@163.com@163.com   All right Reserved
 * ******************************************************************************************************/
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

// 指的是链式栈中的元素的数据类型,用户可以根据需要进行修改
typedef int DataType_t;

// 链式栈节点结构
typedef struct StackNode
{
    DataType_t data;        // 存储栈中元素的数据域
    struct StackNode *next; // 指向下一个节点的指针(栈的下一层)
} StackNode_t;

// 构造记录链式栈LinkStack各项参数(栈顶地址+栈容量)的结构体
typedef struct LinkStack
{
    StackNode_t *Top;  // 记录栈顶地址
    unsigned int Size; // 记录栈容量

} LinkStack_t;

// 创建链式栈进行初始化
LinkStack_t *LinkStack_Create()
{
    // 1.利用calloc为链式栈的管理结构体申请一块堆内存
    LinkStack_t *Manager = (LinkStack_t *)calloc(1, sizeof(LinkStack_t));
    if (NULL == Manager)
    {
        perror("calloc memory for manager is failed");
        exit(-1); // 程序异常终止
    }

    // 2.对管理链式栈的结构体进行初始化(元素容量 + 最后元素下标)
    Manager->Size = 0;   // 对链式栈中的容量进行初始化
    Manager->Top = NULL; // 由于链式栈为空,则栈顶元素的下标初值为NULL
    return Manager;
}
// 初始化一个新的栈节点
StackNode_t *StackNode_Create(DataType_t data)
{
    // 1.利用calloc为链式栈的新节点申请一块堆内存
    StackNode_t *new = (StackNode_t *)calloc(1, sizeof(StackNode_t));
    if (NULL == new)
    {
        perror("calloc memory for manager is failed");
        exit(-1); // 程序异常终止
    }

    // 2.对管理链式栈的新节点进行初始化(元素容量 + 最后元素下标)
    new->data = data;
    new->next = NULL;
    return new;
}

// 入栈
bool LinkStack_Push(LinkStack_t *Manager, DataType_t Data)
{
    // 1.为新节点分配堆内存并进行初始化
    StackNode_t *new = StackNode_Create(Data);
    if (NULL == new)
    {
        perror("calloc memory for manager is failed");
        exit(-1); // 程序异常终止
    }
    // 2.如果节点创建成功,则把新元素添加到链式栈的栈顶
    new->next = Manager->Top;
    Manager->Top = new;
    Manager->Size++;

    return true;
}

// 判断链式栈是否为空
bool LinkStack_IsEmpty(LinkStack_t *Manager)
{
    return (NULL == Manager->Top) ? true : false;
}

// 出栈
DataType_t LinkStack_Pop(LinkStack_t *Manager)
{

    // 1.判断链式栈是否为空
    if (LinkStack_IsEmpty(Manager))
    {
        printf("LinkStack is Empty!\n");
        return;
    }

    // 2.由于删除了一个元素,则需要让链式栈的栈顶元素下标指向下一个
    StackNode_t *temp = Manager->Top;//备份栈顶元素的地址 方便在进行指针偏移后free操作 不然在进行偏移后 会导致之前首节点的地址丢失
    DataType_t data = temp->data;
    Manager->Top = temp->next;
    free(temp);
    Manager->Size--;
    return data;
}

// 遍历链式表的元素
void LinkStack_Print(LinkStack_t *Manager)
{
    StackNode_t *current = Manager->Top;
    printf("栈中的元素为: ");
    while (current != NULL)
    {
        printf("%d ", current->data); // 访问数据域
        current = current->next;      // 移动到下一个节点
    }
    printf("\n");
}

int main(int argc, char const *argv[])
{
    LinkStack_t *stack = LinkStack_Create();

    LinkStack_Push(stack, 10);
    LinkStack_Push(stack, 20);
    LinkStack_Push(stack, 30);

    LinkStack_Print(stack);

    printf("弹出元素: %d\n", LinkStack_Pop(stack));
    LinkStack_Print(stack);
    return 0;
}

测试结果展示

image

posted @ 2025-05-12 11:00  Arroyol  阅读(62)  评论(0)    收藏  举报