用C语言实现栈:从基础到实战

news/2024/12/12 22:33:08/文章来源:https://www.cnblogs.com/happy-coding/p/18603574

栈(Stack)是一种基础的数据结构,遵循后进先出(LIFO,Last In First Out)的原则。它被广泛应用于函数调用、表达式求值、括号匹配等问题中。在这篇技术博客中,我们将详细介绍如何使用C语言实现一个栈,并涵盖基本的操作以及实战应用。


什么是栈?

栈是一种特殊的线性表,只允许在一端进行插入和删除操作。这一端被称为栈顶(Top)。栈的基本操作包括:

  • Push: 将元素压入栈顶。
  • Pop: 从栈顶移除元素。
  • Peek/Top: 查看栈顶元素而不移除。
  • IsEmpty: 判断栈是否为空。
  • IsFull: 判断栈是否已满(对于有固定容量的栈)。

栈的实现方法

在C语言中,栈的实现可以分为基于数组和基于链表两种方法。我们将分别介绍这两种实现方式。

1. 基于数组实现栈

基于数组的栈实现通常适用于固定大小的栈。以下是代码示例:

#include <stdio.h>
#include <stdlib.h>#define MAX_SIZE 100typedef struct {int data[MAX_SIZE];int top;
} Stack;// 初始化栈
void initStack(Stack *stack) {stack->top = -1;
}// 判断栈是否为空
int isEmpty(Stack *stack) {return stack->top == -1;
}// 判断栈是否已满
int isFull(Stack *stack) {return stack->top == MAX_SIZE - 1;
}// 压栈操作
void push(Stack *stack, int value) {if (isFull(stack)) {printf("Stack overflow! Cannot push %d\n", value);return;}stack->data[++stack->top] = value;
}// 弹栈操作
int pop(Stack *stack) {if (isEmpty(stack)) {printf("Stack underflow! Cannot pop\n");return -1;}return stack->data[stack->top--];
}// 查看栈顶元素
int peek(Stack *stack) {if (isEmpty(stack)) {printf("Stack is empty! Cannot peek\n");return -1;}return stack->data[stack->top];
}// 打印栈中元素
void printStack(Stack *stack) {if (isEmpty(stack)) {printf("Stack is empty!\n");return;}printf("Stack elements: ");for (int i = 0; i <= stack->top; i++) {printf("%d ", stack->data[i]);}printf("\n");
}int main() {Stack stack;initStack(&stack);push(&stack, 10);push(&stack, 20);push(&stack, 30);printStack(&stack);printf("Popped: %d\n", pop(&stack));printStack(&stack);printf("Top element: %d\n", peek(&stack));return 0;
}

核心特点:

  • 使用数组存储数据。
  • 通过top变量管理栈顶位置。
  • 操作简单但存在固定容量的限制。

2. 基于链表实现栈

链表实现的栈不需要固定大小,动态分配内存,适用于需要灵活容量的场景。

#include <stdio.h>
#include <stdlib.h>typedef struct Node {int data;struct Node *next;
} Node;// 初始化栈
Node* initStack() {return NULL;
}// 判断栈是否为空
int isEmpty(Node *top) {return top == NULL;
}// 压栈操作
void push(Node **top, int value) {Node *newNode = (Node *)malloc(sizeof(Node));if (newNode == NULL) {printf("Memory allocation failed! Cannot push %d\n", value);return;}newNode->data = value;newNode->next = *top;*top = newNode;
}// 弹栈操作
int pop(Node **top) {if (isEmpty(*top)) {printf("Stack underflow! Cannot pop\n");return -1;}Node *temp = *top;int value = temp->data;*top = temp->next;free(temp);return value;
}// 查看栈顶元素
int peek(Node *top) {if (isEmpty(top)) {printf("Stack is empty! Cannot peek\n");return -1;}return top->data;
}// 打印栈中元素
void printStack(Node *top) {if (isEmpty(top)) {printf("Stack is empty!\n");return;}printf("Stack elements: ");Node *current = top;while (current != NULL) {printf("%d ", current->data);current = current->next;}printf("\n");
}int main() {Node *stack = initStack();push(&stack, 10);push(&stack, 20);push(&stack, 30);printStack(stack);printf("Popped: %d\n", pop(&stack));printStack(stack);printf("Top element: %d\n", peek(stack));return 0;
}

核心特点:

  • 动态分配内存,无容量限制。
  • 通过链表节点表示栈元素。
  • 实现更加灵活,但需要注意内存管理。

实战案例:括号匹配问题

栈可以用于解决括号匹配的问题。以下是一个简单的实现:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define MAX_SIZE 100typedef struct {char data[MAX_SIZE];int top;
} CharStack;// 初始化字符栈
void initCharStack(CharStack *stack) {stack->top = -1;
}// 判断栈是否为空
int isCharStackEmpty(CharStack *stack) {return stack->top == -1;
}// 压栈操作
void pushChar(CharStack *stack, char ch) {if (stack->top == MAX_SIZE - 1) {printf("Stack overflow! Cannot push %c\n", ch);return;}stack->data[++stack->top] = ch;
}// 弹栈操作
char popChar(CharStack *stack) {if (isCharStackEmpty(stack)) {printf("Stack underflow! Cannot pop\n");return '\0';}return stack->data[stack->top--];
}// 检查括号匹配
int isBalanced(const char *expr) {CharStack stack;initCharStack(&stack);for (int i = 0; i < strlen(expr); i++) {char ch = expr[i];if (ch == '(' || ch == '{' || ch == '[') {pushChar(&stack, ch);} else if (ch == ')' || ch == '}' || ch == ']') {if (isCharStackEmpty(&stack)) {return 0; // 多余的右括号}char top = popChar(&stack);if ((ch == ')' && top != '(') ||(ch == '}' && top != '{') ||(ch == ']' && top != '[')) {return 0; // 括号不匹配}}}return isCharStackEmpty(&stack);
}int main() {const char *expr = "{[()]}";if (isBalanced(expr)) {printf("The expression is balanced.\n");} else {printf("The expression is not balanced.\n");}return 0;
}

总结

通过这篇博客,我们从基础概念到代码实现,深入探讨了如何使用C语言实现栈。无论是数组还是链表方法,各有优缺点。栈的应用范围广泛,是编程中不可或缺的工具。希望这篇文章能帮助您更好地理解和掌握栈的实现与应用!

参考链接

探索C语言中的栈:原理、实现与实战

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

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

相关文章

Spring Cloud 搭建 Nacos (windows )

一、Nacos服务搭建 1、下载安装: Windows: 在Nacos的GitHub页面,提供有下载链接,可以下载编译好的Nacos服务端或者源代码: GitHub主页:https://github.com/alibaba/nacos GitHub的Release下载页:https://github.com/alibaba/nacos/releases 解压后出现目录:说明:(默认…

一、HTML基础实例

1.HTML 文档 (1)所有 HTML 文档都必须以文档类型声明开头: 。 (2)HTML 文档以 开始,以 结束。 (3)HTML 文档的可见部分位于 和 之间。 实例: <!DOCTYPE html> <html> <body><h1>我的第一个标题</h1> <p>我的第一个段落。</…

node和rasa交互之可通信

本文主要实现node和rasa的交互,这样为后面node介入rasa奠定基础,目前实现的是node获取rasa响应后的结果,从接口访问rasa然后返回rasa的结果。涉及如何配置,训练模型,启动rasa服务器,打通路由,交互。1.2 通过node和rasa交互 1.2.1 配置 更改 config.yml # The config rec…

网络安全系统学习实验1:RDP远程登录配置

网络安全系统学习实验1:RDP远程登录配置 准备工作: 0、准备好虚拟机1、服务器侧(虚拟机Windows 2003-01)IP地址: # 获得服务器的IP地址192.168.58.223 ipconfig /all2、客户端侧(虚拟机Win7 pte_czj)IP地址: # 客户端侧IP地址192.168.58.222 ipconfig /all1、启用远程桌面…

使用PaliGemma2构建多模态目标检测系统:从架构设计到性能优化的技术实践指南

目标检测技术作为计算机视觉领域的核心组件,在自动驾驶系统、智能监控、零售分析以及增强现实等应用中发挥着关键作用。本文将详细介绍PaliGemma2模型的微调流程,该模型通过整合SigLIP-So400m视觉编码器与Gemma 2系列的高级语言模型,专门针对目标检测任务进行了优化设计。 本…

APP 内存泄露优化

原理 https://juejin.cn/post/6864492188404088846 分析 我的APP主要的VC路径如下:如果没有内存泄露的话,我们从一个VC_A开始push一个VC_B,无论在VC_B操作了什么,pop回到VC_A,这个时候的内存大小应该和VC_A在puhs VC_B的时候是一样大的。 如图: 页面结构:曲谱列表 push 曲…

VMware ESXi 8.0U3c macOS Unlocker OEM BIOS 2.7 集成网卡驱动和 NVMe 驱动 (集成驱动版)

VMware ESXi 8.0U3c macOS Unlocker & OEM BIOS 2.7 集成网卡驱动和 NVMe 驱动 (集成驱动版)VMware ESXi 8.0U3c macOS Unlocker & OEM BIOS 2.7 集成网卡驱动和 NVMe 驱动 (集成驱动版) 发布 ESXi 8.0U3 集成驱动版,在个人电脑上运行企业级工作负载 请访问原文链接:…

12.12实验八:随机森林算法实现与测试

实验八:随机森林算法实现与测试 一、实验目的 深入理解随机森林的算法原理,进而理解集成学习的意义,能够使用 Python 语言实现随机森林算法的训练与测试,并且使用五折交叉验证算法进行模型训练与评估。二、实验内容 (1)从 scikit-learn 库中加载 iris 数据集,使用留出法…

VMware ESXi 8.0U3c 发布 - 领先的裸机 Hypervisor

VMware ESXi 8.0U3c 发布 - 领先的裸机 HypervisorVMware ESXi 8.0U3c 发布 - 领先的裸机 Hypervisor 同步发布 Dell (戴尔)、HPE (慧与)、Lenovo (联想)、IEIT SYSTEMS (浪潮信息)、Cisco (思科)、Fujitsu (富士通)、Hitachi (日立)、NEC (日电)、Huawei (华为)、xFusion (超聚…

VMware ESXi 8.0U3c macOS Unlocker OEM BIOS 2.7 标准版和厂商定制版

VMware ESXi 8.0U3c macOS Unlocker & OEM BIOS 2.7 标准版和厂商定制版VMware ESXi 8.0U3c macOS Unlocker & OEM BIOS 2.7 标准版和厂商定制版 ESXi 8.0U3 标准版,Dell (戴尔)、HPE (慧与)、Lenovo (联想)、IEIT SYSTEMS (浪潮信息)、Cisco (思科)、Fujitsu (富士通…

使用Flex布局的几个小技巧

前情 Flex 是 Flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性,任何一个容器都可以指定为 Flex 布局,如果说目前我开发中离不开的布局方式那就非Flex莫属了,而且小程序就是推荐使用Flex布局的,对 Grid布局的支持不太理想。 在一次次使用fl…

C#学习笔记(一) Array学习笔记

之前一直学习各种基础知识,光学习,没有总结,趁着有时间,总结总结C#有关知识 Array类是最基础的数组类,官方文档截图如下:Array是一个抽象类,不能实例化,只能使用里面的方法,属性。 Array 类不是 System.Collections 命名空间的一部分。 但是,它仍被视为集合,因为它基…