数据结构(3.3)——栈的链式存储结构

链栈的定义

采用链式存储的栈成为链栈,链栈的优点是便于多个栈共享存储空间和提高其效率,且不存在栈满上溢的情况通常采用单链表实现。

typedef struct Linknode {
    int data;          // 数据域
    struct Linknode* next; // 指针域
} LiStack; // 栈类型定义

链栈的初始化

// 初始化链栈的函数
bool InitLiStack(LiStack* top) {
    top = (LiStack*)malloc(sizeof(LiStack)); // 分配头结点的内存
    if (top == NULL) {
        return false; // 分配失败,返回false
    }else{
    top->data = 0; // 初始化数据域,这里可根据需要设置
    top->next = NULL; // 头结点的next指针指向NULL
    return true; // 分配成功,返回true
}

链栈的入栈操作

栈的链式存储操作其实和单链表的头插法插入很相似,我们完全可以使用单链表的头插法插入元素来模拟入栈操作

//进栈操作
bool Push(LiStack* top, int value) {
    LiStack* newNode = (LiStack*)malloc(sizeof(LiStack));//分配新结点的内存
    if (newNode == NULL) {
        return false;//分配失败,返回false
    }
    else {
        newNode->data = value;//设置新结点的数据域
        newNode->next = top;//新结点的next指针指向当前的栈顶
        top = newNode;//更新栈顶指针
        return true;//进栈成功,返回true
    }
}

链栈的出栈操作

//出栈操作
bool Pop(LiStack* top, int* value) {
    if (top == NULL) {
        return false;
    }
    else {
        *value = top->data;//获取栈顶结点的数据
        LiStack* temp = top;//临时保存栈顶结点
        top = top->next;//更新栈顶指针
        free(temp);//释放栈顶结点内存
        return true;
    }
}

在栈操作中,释放 temp 而不是 top 是因为 temp 指向的是即将被弹出的栈顶元素,而 top 指向的是新的栈顶元素。以下是详细解释:

  1. 栈的基本概念:栈是一种后进先出(LIFO)的数据结构。在栈中,最后插入的元素是最先被删除的。

  2. 出栈操作:出栈操作涉及从栈顶删除元素。在链式栈中,这意味着需要删除与 top 指针关联的节点。

  3. temp 的作用:在出栈操作中,temp 被用来临时存储指向当前栈顶节点的指针。这样做的目的是,在删除当前栈顶节点后,top 指针可以安全地移动到下一个节点,而不会丢失对当前栈顶节点的引用。

  4. 释放 temp:一旦 top 指针已经更新为指向下一个节点,temp 指向的节点就不再需要了。此时,释放 temp 指向的内存是安全的,因为它已经不再是栈的一部分。

  5. 不释放 toptop 指针在出栈操作后仍然指向新的栈顶节点。如果释放了 top 指向的节点,那么 top 指针将指向一个已经被释放的内存区域,这将导致未定义行为,可能引发程序崩溃。

  6. 内存管理:在链式栈中,每个节点都是动态分配的内存。当一个节点被弹出栈时,必须释放该节点的内存,以避免内存泄漏。

  7. 代码实现:在您的代码中,free(temp) 正确地释放了即将被弹出的栈顶节点的内存。如果 free(top) 被错误地调用,那么 top 指针将指向一个无效的内存区域,这将破坏栈的结构。

总结来说,释放 temp 是因为 temp 指向的是即将被移除的栈顶节点,而 top 指向的是新的栈顶节点,需要保留以维护栈的结构。

读取栈顶

// 读取栈顶元素的值,不移除它
bool Peek(LiStack* top, int* value) {
    if (top == NULL) {
        return false; // 栈为空,无法读取栈顶元素
    }
    else {
        *value = top->data; // 将栈顶元素的值赋给value指针指向的变量
        return true; // 成功读取栈顶元素
    }

在这个示例中,Peek 函数接受一个指向栈顶节点的指针 top,以及一个指向 int 类型的指针 value,用于存储栈顶元素的值。如果栈不为空,函数将栈顶元素的值赋给 value 指针指向的变量,并返回 true。如果栈为空,则返回 false。 

判空判满

在链式栈中,由于它是动态分配内存的,所以它不会像数组那样有固定的容量限制,也就不会出现“满”的情况。因此,我们只需要实现一个判断链栈是否为空的方法。

bool IsEmpty(LiStack* stack) {
    return stack->top == NULL; // 如果栈顶指针为NULL,则栈为空
}

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值