《数据结构》C语言版 (清华严蔚敏考研版) 第三章 栈和队列 栈相关知识梳理与总结

本文详细介绍了栈的基本概念,包括栈的定义、顺序存储结构中的操作(如栈顶指针管理)以及链式存储结构的实现(如在链表头部插入和删除节点)。讨论了栈的进出栈变化形式,并展示了栈的典型操作如push和pop。
摘要由CSDN通过智能技术生成

个人主页李仙桎

   🔥 个人专栏: 《数据结构与算法》

⛺️生活的理想,就是为了理想的生活!

Alt

⛺️前言:各位铁汁们好啊!!!,今天继续学习数据结构相关的内容,后续不断更新数据结构有关知识内容!!希望各位铁汁多多支持!这一章节主要是《数据结构》第三章 栈和队列 栈的相关知识总结。

1、栈的定义

栈(stack)是只允许一端进行插入和删除的线性表

栈是一种特殊的线性数据结构,仅支持在一个位置进行添加元素(称为“入栈”或“push”操作)和移除元素(称为“出栈”或“pop”操作)的操作。这个位置就是栈顶(Top)。由于栈是后进先出(LIFO, Last In First Out)的数据结构,最后一个添加到栈中的元素将是第一个被移除。

栈进出栈的变化形式

首先提一个问题,最先进栈的元素,是不是一定最后出栈呢?
答案是不一定的,在不是所有元素都进栈的情况下,先进去的元素也可以出栈,保证是栈顶元素出栈就可以

举例,如果我们有a、b、c、d、e三个数字一次进栈,会有哪些出栈次序呢?

第一种:a、b、c、d、e进,再e、d、c、b、a出,出栈次序为edcba
第二种:a进,a出,b进,c进,d进,e进。然后e、d、c、b的次序出,出栈次序为aedcb
第三种,a进,b进,b出,c进,d进,e进,然后e、d、c、a出,出栈顺序为bedca
......

栈的顺序存储结构的有关操作

对于栈来讲,线性表的操作特性它都具备,由于它的特殊性,特别是插入和删除操作,我们改名为push和pop

线性表是用数组来实现的,对于栈这一种只能一头插入的线性表来说,下表为0的一段作为栈底

在栈的实现中,top变量一般用来指示栈顶元素的位置。对于一个空栈来说,不存在任何元素,因此没有一个合理的位置可以被称为栈顶。在这种情况下,需要一个特殊的值来表示栈是空的
在进行入栈和出栈操作时,top的更新逻辑变得简单直接。例如,每当添加一个新元素到栈中时,先将top加1(这将把top从-1改为0,表示第一个元素的位置),然后在top对应的位置上存放新元素

注意++S.top和S.top++的区别:++S.top和S.top++都是将S.top进行+1的操作,但是S.data[++S.top]是先进行+1操作,然后在进行复制操作,但是S.data[S.top++]却是先进行赋值操作,然后在进行+1操作。

栈的链式存储结构的有关操作

讲完了栈的顺序存储,我们接着来看栈的链式存储

当使用链表实现链式栈时,通常选择链表的头部作为栈顶,因为这种方法更高效、实现也更简单:

  • 在链表头部插入或删除节点只需要O(1)的时间复杂度,因为这些操作不需要遍历整个链表。这对于栈操作(即push和pop操作)非常理想,因为它们也应该是O(1)的时间复杂度
  • 链表有头指针,栈有顶部指针,可以做到合二为一

链表的创建

typedef int STDataType;

typedef struct StackNode {
    STDataType data;                     
    struct StackNode* next;       
} StackNode;

typedef struct LinkedStack{
    StackNode* top;               
    int size;                     
} LinkedStack;

初始化

初始化一个空栈,只需要将栈顶指针设置为NULL,栈的大小设置为0

void Initialize(LinkedStack* stack) {
    stack->top = NULL;
    stack->size = 0;
}

压栈和出栈

int Push(LinkedStack* stack, int x) {
    StackNode* Node = (StackNode*)malloc(sizeof(StackNode));
    if (newNode == NULL) {
        printf("Memory allocation failed\n");
        return -1;  // 使用-1表示错误情况,实际使用中应考虑其他错误处理方式
    }
    newNode->data = x ;
    newNode->next = stack->top;    // 新节点的下一个节点就是当前的栈顶
    stack->top = newNode;          // 更新栈顶为新节点
    stack->size++;
    return 1;
}

int Pop(LinkedStack* stack) {
    if (stack->top == NULL) {      // 检查栈是否为空
        printf("Stack is empty\n");
        return -1;                 // 使用-1表示错误情况,实际使用中应考虑其他错误处理方式
    }
    StackNode* temp = stack->top;  // 临时保存栈顶节点
    int data = temp->data;         // 获取栈顶数据
    stack->top = temp->next;       // 更新栈顶指针为下一个节点
    free(temp);                    // 释放原栈顶节点的内存
    stack->size--;
    return data;                   // 返回栈顶数据
}

推入新元素需要创建一个新的节点,并将其插入到链表的头部。弹出栈顶元素先要检查栈是否为空。如果不为空,将栈顶节点从链表中移除,并释放它所占用的内存。

检查栈是否为空

检查链式栈是否为空也很简单,只需检查栈顶指针是否为NULL。

int IsEmpty(LinkedStack* stack) {
    return stack->top == NULL;
}
  • 24
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李仙桎

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值