数据结构-C语言版本(三)栈

数据结构中的栈:概念、操作与实战

第一部分 栈分类及常见形式

栈是一种遵循后进先出(LIFO, Last In First Out)原则的线性数据结构。栈主要有以下几种实现形式:

1. 数组实现的栈(顺序栈)

#define MAX_SIZE 100typedef struct {int data[MAX_SIZE];int top;
} ArrayStack;

2. 链表实现的栈(链式栈)

typedef struct StackNode {int data;struct StackNode* next;
} StackNode;typedef struct {StackNode* top;
} LinkedStack;

3. 动态扩容栈

当栈满时能自动扩容的栈(基于数组实现)

typedef struct {int *data;int top;int capacity;
} DynamicStack;

4. 双栈共享同一存储空间

两个栈共享一个数组空间,从两端向中间生长

typedef struct {int data[MAX_SIZE];int top1;  // 栈1的栈顶指针int top2;  // 栈2的栈顶指针
} DoubleStack;

第二部分 栈常见操作

1. 初始化栈

// 初始化数组栈
void initArrayStack(ArrayStack *stack) {stack->top = -1;
}// 初始化链式栈
void initLinkedStack(LinkedStack *stack) {stack->top = NULL;
}// 初始化动态栈
void initDynamicStack(DynamicStack *stack, int initialCapacity) {stack->data = (int*)malloc(initialCapacity * sizeof(int));stack->top = -1;stack->capacity = initialCapacity;
}

2. 入栈操作

// 数组栈入栈
void pushArrayStack(ArrayStack *stack, int value) {if(stack->top >= MAX_SIZE - 1) {printf("栈已满\n");return;}stack->data[++stack->top] = value;
}// 链式栈入栈
void pushLinkedStack(LinkedStack *stack, int value) {StackNode* newNode = (StackNode*)malloc(sizeof(StackNode));newNode->data = value;newNode->next = stack->top;stack->top = newNode;
}// 动态栈入栈(带自动扩容)
void pushDynamicStack(DynamicStack *stack, int value) {if(stack->top == stack->capacity - 1) {stack->capacity *= 2;stack->data = (int*)realloc(stack->data, stack->capacity * sizeof(int));}stack->data[++stack->top] = value;
}

3. 出栈操作

// 数组栈出栈
int popArrayStack(ArrayStack *stack) {if(stack->top == -1) {printf("栈为空\n");return -1; // 错误码}return stack->data[stack->top--];
}// 链式栈出栈
int popLinkedStack(LinkedStack *stack) {if(stack->top == NULL) {printf("栈为空\n");return -1; // 错误码}StackNode* temp = stack->top;int value = temp->data;stack->top = stack->top->next;free(temp);return value;
}

4. 查看栈顶元素

// 查看数组栈顶元素
int peekArrayStack(ArrayStack *stack) {if(stack->top == -1) {printf("栈为空\n");return -1;}return stack->data[stack->top];
}// 查看链式栈顶元素
int peekLinkedStack(LinkedStack *stack) {if(stack->top == NULL) {printf("栈为空\n");return -1;}return stack->top->data;
}

5. 判断栈是否为空

// 判断数组栈是否为空
int isEmptyArrayStack(ArrayStack *stack) {return stack->top == -1;
}// 判断链式栈是否为空
int isEmptyLinkedStack(LinkedStack *stack) {return stack->top == NULL;
}

6. 获取栈大小

// 获取数组栈大小
int sizeArrayStack(ArrayStack *stack) {return stack->top + 1;
}// 获取链式栈大小
int sizeLinkedStack(LinkedStack *stack) {int count = 0;StackNode* current = stack->top;while(current != NULL) {count++;current = current->next;}return count;
}

第三部分 栈编程题例子

1. 括号匹配检查

int isValidParentheses(char* s) {char stack[10000];int top = -1;for(int i = 0; s[i] != '\0'; i++) {if(s[i] == '(' || s[i] == '[' || s[i] == '{') {stack[++top] = s[i];} else {if(top == -1) return 0;char topChar = stack[top--];if((s[i] == ')' && topChar != '(') ||(s[i] == ']' && topChar != '[') ||(s[i] == '}' && topChar != '{')) {return 0;}}}return top == -1;
}

2. 逆波兰表达式求值

int evalRPN(char** tokens, int tokensSize) {int stack[10000];int top = -1;for(int i = 0; i < tokensSize; i++) {if(strcmp(tokens[i], "+") == 0) {int b = stack[top--];int a = stack[top--];stack[++top] = a + b;} else if(strcmp(tokens[i], "-") == 0) {int b = stack[top--];int a = stack[top--];stack[++top] = a - b;} else if(strcmp(tokens[i], "*") == 0) {int b = stack[top--];int a = stack[top--];stack[++top] = a * b;} else if(strcmp(tokens[i], "/") == 0) {int b = stack[top--];int a = stack[top--];stack[++top] = a / b;} else {stack[++top] = atoi(tokens[i]);}}return stack[top];
}

3. 用栈实现队列

typedef struct {int inStack[MAX_SIZE];int outStack[MAX_SIZE];int inTop;int outTop;
} MyQueue;MyQueue* myQueueCreate() {MyQueue* queue = (MyQueue*)malloc(sizeof(MyQueue));queue->inTop = -1;queue->outTop = -1;return queue;
}void push(MyQueue* obj, int x) {obj->inStack[++obj->inTop] = x;
}int pop(MyQueue* obj) {if(obj->outTop == -1) {while(obj->inTop != -1) {obj->outStack[++obj->outTop] = obj->inStack[obj->inTop--];}}return obj->outStack[obj->outTop--];
}int peek(MyQueue* obj) {if(obj->outTop == -1) {while(obj->inTop != -1) {obj->outStack[++obj->outTop] = obj->inStack[obj->inTop--];}}return obj->outStack[obj->outTop];
}int empty(MyQueue* obj) {return obj->inTop == -1 && obj->outTop == -1;
}

4. 最小栈(能在O(1)时间内检索到最小元素的栈)

typedef struct {int dataStack[MAX_SIZE];int minStack[MAX_SIZE];int top;
} MinStack;MinStack* minStackCreate() {MinStack* stack = (MinStack*)malloc(sizeof(MinStack));stack->top = -1;return stack;
}void minStackPush(MinStack* obj, int val) {obj->dataStack[++obj->top] = val;if(obj->top == 0) {obj->minStack[obj->top] = val;} else {obj->minStack[obj->top] = val < obj->minStack[obj->top-1] ? val : obj->minStack[obj->top-1];}
}void minStackPop(MinStack* obj) {obj->top--;
}int minStackTop(MinStack* obj) {return obj->dataStack[obj->top];
}int minStackGetMin(MinStack* obj) {return obj->minStack[obj->top];
}

5. 栈的压入、弹出序列验证

int validateStackSequences(int* pushed, int pushedSize, int* popped, int poppedSize) {if(pushedSize != poppedSize) return 0;int stack[pushedSize];int top = -1;int popIndex = 0;for(int i = 0; i < pushedSize; i++) {stack[++top] = pushed[i];while(top != -1 && stack[top] == popped[popIndex]) {top--;popIndex++;}}return top == -1;
}

6. 每日温度(计算需要等待多少天才能得到更暖和的温度)

int* dailyTemperatures(int* temperatures, int temperaturesSize, int* returnSize) {*returnSize = temperaturesSize;int* result = (int*)malloc(temperaturesSize * sizeof(int));memset(result, 0, temperaturesSize * sizeof(int));int stack[temperaturesSize];int top = -1;for(int i = 0; i < temperaturesSize; i++) {while(top != -1 && temperatures[i] > temperatures[stack[top]]) {int prevIndex = stack[top--];result[prevIndex] = i - prevIndex;}stack[++top] = i;}return result;
}

栈作为一种基础而重要的数据结构,在编译器设计、操作系统、算法实现等领域有广泛应用。掌握栈的各种操作和典型应用场景,对于提升编程能力和算法思维至关重要。通过练习这些题目,可以深入理解栈的特性及其解决问题的思路。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/77662.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何以特殊工艺攻克超薄电路板制造难题?

一、超薄PCB的行业定义与核心挑战 超薄PCB通常指厚度低于1.0毫米的电路板&#xff0c;而高端产品可进一步压缩至0.4毫米甚至0.2毫米以下。这类电路板因体积小、重量轻、热传导性能优异&#xff0c;被广泛应用于折叠屏手机、智能穿戴设备、医疗植入器械及新能源汽车等领域。然而…

AI 赋能 3D 创作!Tripo3D 全功能深度解析与实操教程

大家好&#xff0c;欢迎来到本期科技工具分享&#xff01; 今天要给大家带来一款革命性的 AI 3D 模型生成平台 ——Tripo3D。 无论你是游戏开发者、设计师&#xff0c;还是 3D 建模爱好者&#xff0c;只要想降低创作门槛、提升效率&#xff0c;这款工具都值得深入了解。 接下…

如何理解抽象且不易理解的华为云 API?

API的概念在华为云的使用中非常抽象&#xff0c;且不容易理解&#xff0c;用通俗的语言 形象的比喻来讲清楚——什么是华为云 API&#xff0c;怎么用&#xff0c;背后原理&#xff0c;以及主要元素有哪些&#xff0c;尽量让新手也能明白。 &#x1f9e0; 一句话先理解&#xf…

第 7 篇:总结与展望 - 时间序列学习的下一步

第 7 篇&#xff1a;总结与展望 - 时间序列学习的下一步 (图片来源: Guillaume Hankenne on Pexels) 恭喜你&#xff01;如果你一路跟随这个系列走到了这里&#xff0c;那么你已经成功地完成了时间序列分析的入门之旅。我们从零开始&#xff0c;一起探索了时间数据的基本概念、…

PPT无法编辑怎么办?原因及解决方法全解析

在日常办公中&#xff0c;我们经常会遇到需要编辑PPT的情况。然而&#xff0c;有时我们会发现PPT文件无法编辑&#xff0c;这可能由多种原因引起。今天我们来看看PPT无法编辑的几种常见原因&#xff0c;并提供实用的解决方法&#xff0c;帮助你轻松应对。 原因1&#xff1a;文…

前端面试题---GET跟POST的区别(Ajax)

GET 和 POST 是两种 HTTP 请求方式&#xff0c;它们在传输数据的方式和所需空间上有一些重要区别&#xff1a; ✅ 一句话概括&#xff1a; GET 数据放在 URL 中&#xff0c;受限较多&#xff1b;POST 数据放在请求体中&#xff0c;空间更大更安全。 &#x1f4e6; 1. 所需空间…

第 5 篇:初试牛刀 - 简单的预测方法

第 5 篇&#xff1a;初试牛刀 - 简单的预测方法 经过前面四篇的学习&#xff0c;我们已经具备了处理时间序列数据的基本功&#xff1a;加载、可视化、分解以及处理平稳性。现在&#xff0c;激动人心的时刻到来了——我们要开始尝试预测 (Forecasting) 未来&#xff01; 预测是…

从代码学习深度学习 - 学习率调度器 PyTorch 版

文章目录 前言一、理论背景二、代码解析2.1. 基本问题和环境设置2.2. 训练函数2.3. 无学习率调度器实验2.4. SquareRootScheduler 实验2.5. FactorScheduler 实验2.6. MultiFactorScheduler 实验2.7. CosineScheduler 实验2.8. 带预热的 CosineScheduler 实验三、结果对比与分析…

k8s 基础入门篇之开启 firewalld

前面在部署k8s时&#xff0c;都是直接关闭的防火墙。由于生产环境需要开启防火墙&#xff0c;只能放行一些特定的端口&#xff0c; 简单记录一下过程。 1. firewall 与 iptables 的关系 1.1 防火墙&#xff08;Firewall&#xff09; 定义&#xff1a; 防火墙是网络安全系统&…

RSS 2025|苏黎世提出「LLM-MPC混合架构」增强自动驾驶,推理速度提升10.5倍!

论文题目&#xff1a;Enhancing Autonomous Driving Systems with On-Board Deployed Large Language Models 论文作者&#xff1a;Nicolas Baumann&#xff0c;Cheng Hu&#xff0c;Paviththiren Sivasothilingam&#xff0c;Haotong Qin&#xff0c;Lei Xie&#xff0c;Miche…

list的学习

list的介绍 list文档的介绍 list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。list的底层是双向链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&#xff0c;在节点中通过指针指向其前一个元素和后一…

生物信息学技能树(Bioinformatics)与学习路径

李升伟 整理 生物信息学是一门跨学科领域&#xff0c;涉及生物学、计算机科学以及统计学等多个方面。以下是关于生物信息学的学习路径及相关技能的详细介绍。 一、基础理论知识 1. 生物学基础知识 需要掌握分子生物学、遗传学、细胞生物学等相关概念。 对基因组结构、蛋白质…

AOSP Android14 Launcher3——远程窗口动画关键类SurfaceControl详解

在 Launcher3 执行涉及其他应用窗口&#xff08;即“远程窗口”&#xff09;的动画时&#xff0c;例如“点击桌面图标启动应用”或“从应用上滑回到桌面”的过渡动画&#xff0c;SurfaceControl 扮演着至关重要的角色。它是实现这些跨进程、高性能、精确定制动画的核心技术。 …

超详细实现单链表的基础增删改查——基于C语言实现

文章目录 1、链表的概念与分类1.1 链表的概念1.2 链表的分类 2、单链表的结构和定义2.1 单链表的结构2.2 单链表的定义 3、单链表的实现3.1 创建新节点3.2 头插和尾插的实现3.3 头删和尾删的实现3.4 链表的查找3.5 指定位置之前和之后插入数据3.6 删除指定位置的数据和删除指定…

17.整体代码讲解

从入门AI到手写Transformer-17.整体代码讲解 17.整体代码讲解代码 整理自视频 老袁不说话 。 17.整体代码讲解 代码 import collectionsimport math import torch from torch import nn import os import time import numpy as np from matplotlib import pyplot as plt fro…

前端性能优化:所有权转移

前端性能优化&#xff1a;所有权转移 在学习rust过程中&#xff0c;学到了所有权概念&#xff0c;于是便联想到了前端&#xff0c;前端是否有相关内容&#xff0c;于是进行了一些实验&#xff0c;并整理了这些内容。 所有权转移&#xff08;Transfer of Ownership&#xff09;…

Missashe考研日记-day23

Missashe考研日记-day23 0 写在前面 博主前几天有事回家去了&#xff0c;断更几天了不好意思&#xff0c;就当回家休息一下调整一下状态了&#xff0c;今天接着开始更新。虽然每天的博客写的内容不算多&#xff0c;但其实还是挺费时间的&#xff0c;比如这篇就花了我40多分钟…

Docker 中将文件映射到 Linux 宿主机

在 Docker 中&#xff0c;有多种方式可以将文件映射到 Linux 宿主机&#xff0c;以下是常见的几种方法&#xff1a; 使用-v参数• 基本语法&#xff1a;docker run -v [宿主机文件路径]:[容器内文件路径] 容器名称• 示例&#xff1a;docker run -it -v /home/user/myfile.txt:…

HarmonyOS-ArkUI-动画分类简介

本文的目的是,了解一下HarmonyOS动画体系中的分类。有个大致的了解即可。 动效与动画简介 动画,是客户端提升界面交互用户体验的一个重要的方式。可以使应用程序更加生动灵越,提高用户体验。 HarmonyOS对于界面的交互方面,围绕回归本源的设计理念,打造自然,流畅品质一提…

C++如何处理多线程环境下的异常?如何确保资源在异常情况下也能正确释放

多线程编程的基本概念与挑战 多线程编程的核心思想是将程序的执行划分为多个并行运行的线程&#xff0c;每个线程可以独立处理任务&#xff0c;从而充分利用多核处理器的性能优势。在C中&#xff0c;开发者可以通过std::thread创建线程&#xff0c;并使用同步原语如std::mutex、…