【数据结构】(C语言):栈
栈:
- 线性的集合。
- 后进先出(LIFO,last in first out)。
- 两个指针:指向栈顶和栈底。栈顶指向最后进入且第一个出去的元素。栈底指向第一个进入且最后一个出去的元素。
- 两个操作:入栈(往栈尾添加元素),出栈(从栈尾取出元素)。
- 可以使用链表实现,也可以使用数组实现。本文使用双链表举例。
入栈:往栈顶(栈尾部)添加元素。
(头指针:指向第一个元素。尾指针:指向最后的元素。)

出栈:从栈顶(栈尾部)删除元素。
(头指针:指向第一个元素。尾指针:指向最后的元素。)

C语言实现(双链表):
创建节点(结构体数据类型),并创建具体节点实例的函数:
// 节点(结构体数据类型)
typedef struct Node
{int value; // 存储数据为整数struct Node *next; // 指向下一个数据的指针struct Node *prev; // 指向上一个数据的指针
} LinkNode; // 别名LinkNode
// 创建具体节点实例的函数
LinkNode * createNode(int data)
{LinkNode *node = (LinkNode *)malloc(sizeof(LinkNode)); // 分配内存空间if(node == NULL){perror("Memory allocation failed");exit(-1);}node->value = data;node->prev = NULL;node->next = NULL;return node;
}
本文将头指针、尾指针和栈长度作为全局变量:
LinkNode *header = NULL; // 头指针,指向第一个节点,初始化为NULL
LinkNode *tail = NULL; // 尾指针,指向最后节点,初始化为NULL
int length = 0; // 统计栈有多少元素,初始化为0
入栈:
// 入栈(往栈顶即尾部添加数据)
void push(int data)
{LinkNode *node = createNode(data);if(length == 0) // 空栈,头指针和尾指针都指向新节点{header = node;tail = node;length++;return ;}tail->next = node; // 原最后节点的下一个为新节点node->prev = tail; // 新节点的上一个为原最后节点tail = node; // 尾指针指向新节点,即新节点为最后节点 length++; // 每添加一个元素,length+1
}
获取栈顶元素:
int gettop(void)
{// 栈不为空,则栈顶元素为尾指针指向的最后节点的值if(length != 0) return tail->value;
}
出栈:
int pop(void)
{if(length != 0){// 获取最后节点的值int top = tail->value;// 通过最后节点的prev找到倒数第二个节点,其next指向NULL,则原倒数第二个节点为新的最后节点tail->prev->next = NULL;// 每删除一个节点,length-1length--;// 返回原最后节点的值return top;}
}
遍历栈:
void travel(void)
{if(length == 0) return ;LinkNode *cur = header; // 从链表头部开始遍历,直到最后printf("stack elements:");while(cur != NULL){printf("%d \t", cur->value);cur = cur->next;}printf("\n");
}
完整代码:(stack.c)
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>/* structrue */
typedef struct Node // node structure
{int value;struct Node *next;struct Node *prev;
} LinkNode;/* global variables */
LinkNode *header = NULL; // the header pointer
LinkNode *tail = NULL; // the tailer pointer
int length = 0; // the number of the stack elements/* function prototype */
void push(int data); // add element to the end of the stack
int pop(void); // delete element from the end of the stack
int gettop(void); // show element at the end of the stack
void travel(void); // show element one by one/* main function */
int main(void)
{// cycle input a number until 'q' or non-numeric, add the number to the stackwhile(1) // 循环输入数字,并入栈,输入q退出输入循环{int data = 0, c;printf("if quit,input 'q'. Input a number: ");c = getchar(); // 获取输入的一个字符if(tolower(c) == 'q') break; // 若输入q,则退出输入循环if(c < '0' || c > '9') break; // 输入的不是数字,则退出输入循环while(c != '\n') // 若整数为多位数,通过一位一位计算最终获得多位整数{data *= 10;data += c - 48; // ASCII码表中,0对应码值48c = getchar();}push(data); // 入栈printf("length is %d \n", length); // 输出栈元素个数travel(); // 遍历栈}// when stack not empty,cycle look and delete the top element until input 'n'if(length == 0) exit(-1);char k;printf("if you want to look and delete the top element? (y/n) ");scanf(" %c", &k); // 获取输入的内容while(tolower(k) == 'y' && length != 0) // 循环输入是否查看并删除栈顶元素{printf("top element is %d \n", gettop()); // 输出栈顶元素pop(); // 出栈printf("length is %d \n", length); // 输出栈元素个数travel(); // 遍历栈printf("if you want to look and delete the top element? (y/n) ");scanf(" %c", &k); // 获取下一个输入的内容}
}/* subfunction */
LinkNode * createNode(int data) // create a node
{LinkNode *node = (LinkNode *)malloc(sizeof(LinkNode));if(node == NULL){perror("Memory allocation failed");exit(-1);}node->value = data;node->prev = NULL;node->next = NULL;return node;
}void push(int data) // add element to the end of the stack
{LinkNode *node = createNode(data);if(length == 0){header = node;tail = node;length++;return ;}tail->next = node;node->prev = tail;tail = node;length++;
}int pop(void) // delete element from the end of the stack
{if(length != 0){int top = tail->value;tail->prev->next = NULL;length--;return top;}
}int gettop(void) // show element at the end of the stack
{if(length != 0) return tail->value;
}void travel(void) // show element one by one
{if(length == 0) return ;LinkNode *cur = header;printf("stack elements:");while(cur != NULL){printf("%d \t", cur->value);cur = cur->next;}printf("\n");
}
编译链接: gcc -o stack stack.c
执行可执行文件: ./stack

相关文章:
【数据结构】(C语言):栈
栈: 线性的集合。后进先出(LIFO,last in first out)。两个指针:指向栈顶和栈底。栈顶指向最后进入且第一个出去的元素。栈底指向第一个进入且最后一个出去的元素。两个操作:入栈(往栈尾添加元素…...
c++类成员指针用法
1)C入门级小知识,分享给将要学习或者正在学习C开发的同学。 2)内容属于原创,若转载,请说明出处。 3)提供相关问题有偿答疑和支持。 c中新增类成员指针操作,为了访问方便,他是指…...
[240625] Continue -- 开源 Copilot | Web-Check 网站分析工具 | Story of EOL
目录 Continue -- 开源 CopilotWeb-Check 网站分析工具Web-Check 提供全面的网站分析功能Web-Check 支持多种部署方式:配置选项开发环境Web-Check 使用多种数据源进行分析 Story of EOLASCII 文本中的换行符问题 Continue – 开源 Copilot 让 Continue 和 Ollama 成…...
【Mac】Auto Mouse Click for Mac(高效、稳定的鼠标连点器软件)软件介绍
软件介绍 Auto Mouse Click for Mac 是一款专为 macOS 平台设计的自动鼠标点击软件,它可以帮助用户自动化重复的鼠标点击操作,从而提高工作效率。以下是这款软件的主要特点和功能: 1.自动化点击操作:Auto Mouse Click 允许用户录…...
javaSE知识点整理总结(下)、MySQL数据库
目录 一、异常 1.常见异常类型 2.异常体系结构 3.异常处理 (1)finally (2)throws 二、JDBC 1.JDBC搭建 2.执行SQL语句两种方法 三、MySQL数据库 1.ddl 2.dml 3.dql (1)字符函数 (…...
Perl入门学习
Perl是一种强大的脚本语言,以其灵活性和文本处理能力而闻名,常用于系统管理、Web开发、生物信息学以及数据处理等领域。以下是Perl语言入门学习的一些关键点: ### 1. Perl简介 - **起源与特点**:Perl由Larry Wall在1987年创建&am…...
2024年7月计划(ue5肉鸽视频完成)
试过重点放在独立游戏上,有个indienova独立游戏团队是全职的,由于他们干了几个月,节奏暂时跟不上,紧张焦虑了。五一时也有点自暴自弃了,实在没必要,按照自己的节奏走即可。精力和时间也有限,放在…...
恢复策略(上)-撤销事务(UNDO)、重做事务(REDO)
一、引言 利用前面所建立的冗余数据,即日志和数据库备份,要将数据库从一个不一致的错误状态恢复到一个一致性状态,还需要相关的恢复策略,不同DBMS的事务处理机制所采用的缓冲区管理策略可能不同,发生故障后的数据库不…...
【鸿蒙学习笔记】位置设置
官方文档:位置设置 目录标题 align:子元素的对齐方式direction:官方文档没懂,看图理解吧 align:子元素的对齐方式 Stack() {Text(TopStart)}.width(90%).height(50).backgroundColor(0xFFE4C4).align(Alignment.TopS…...
41.HOOK引擎设计原理
上一个内容:41.HOOK引擎设计原理 在一个游戏里通过hook来完成各种各样的功能,比如hook点是a、b、c,然后a点会有它自己所需要的hook逻辑,b、c也是有它们自己的hook逻辑(hook逻辑指的是hook之后要做的事)&am…...
STM32启动流程 和 map文件的作用
一,启动流程 1. 复位/上电 2. 根据 BOOT0/BOOT1 确定程序从哪个存储位置执行 3. 初始化 SP 及 PC 指针 将 0X08000000 位置的栈顶地址存放在 SP 指针中 将 0x08000004 位置存放的向量地址装入 PC 程序计数器 4. 初始化系统时钟 5. 初始化用户堆栈 6. 进入main函数 二…...
深度解析华为仓颉语言
什么是华为仓颉语言? 华为仓颉语言(Huawei Cangjie Language,HCL)是华为公司推出的一种新型编程语言,旨在解决大规模分布式系统开发中的复杂性问题。仓颉语言以高效、简洁和易用为设计目标,特别适用于云计…...
Android简介-历史、API等级与体系结构
1. Android简介 Android是一种基于Linux内核的自由及开放源代码的操作系统。最初是由安迪鲁宾(Andy Rubin)开发的一款相机操作系统。2005年8月被Google收购。2007年11月,Google与84家硬件制造商、软件开发商及电信营运商组建开放手机联盟共同研发改良Android系统。…...
SpringBoot:使用Spring Batch实现批处理任务
引言 在企业级应用中,批处理任务是不可或缺的一部分。它们通常用于处理大量数据,如数据迁移、数据清洗、生成报告等。Spring Batch是Spring框架的一部分,专为批处理任务设计,提供了简化的配置和强大的功能。本文将介绍如何使用Spr…...
用JQueryUI库在.net MVC中配置datepicker(时间日期控件)
原文参考:如何在MVC中添加jQuery Datepicker_mvc datepicker-CSDN博客 好文章被埋没了,可能和时间发的早有关。 1.首先我们引入JQuery和JQuery UI <!-- ... --> <link rel"stylesheet" href"https://code.jquery.com/ui/1.12…...
算法:链表
目录 链表的技巧和操作总结 常用技巧: 链表中的常用操作 题目一:反转一个单链表 题目二:链表的中间结点 题目三:返回倒数第k个结点 题目四:合并两个有序链表 题目五:移除链表元素 题目六ÿ…...
Redis基础教程(一):redis配置
💝💝💝首先,欢迎各位来到我的博客,很高兴能够在这里和您见面!希望您在这里不仅可以有所收获,同时也能感受到一份轻松欢乐的氛围,祝你生活愉快! 💝Ὁ…...
短视频矩阵系统:打造品牌影响力的新方式
一、短视频矩阵概念 短视频营销革命:一站式解决策略!短视频矩阵系统是一款专为企业营销设计的高效工具,旨在通过整合和优化众多短视频平台资源,为企业呈现一个全面的短视频营销策略。该系统致力于协助企业以迅速且高效的方式制作…...
品牌推广的三个阶段与核心内容,一篇文章全掌握!
在竞争激烈的市场环境中,品牌推广是企业成功的关键。精心策划的推广策略能够帮助企业在消费者心中树立独特的品牌形象,进而促进销售增长。 作为一家手工酸奶品牌的创始人,目前全国也复制了100多家门店,我理解的品牌推广分为3个阶…...
队列与循环队列
目录 1. 前言: 2. 队列 2.1 队列的概念 2.2 队列的实现 2.3 队列的声明 2.4 队列的初始化 2.5 队列的入队 2.6 队列的出队 2.7 队列获取队头元素 2.8 队列获取队尾元素 2.9 队列获取有效数据个数 2.10 队列判断是否为空 2.11 打印队列 2.12 销毁队列 …...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
python爬虫——气象数据爬取
一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用: 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests:发送 …...
前端开发者常用网站
Can I use网站:一个查询网页技术兼容性的网站 一个查询网页技术兼容性的网站Can I use:Can I use... Support tables for HTML5, CSS3, etc (查询浏览器对HTML5的支持情况) 权威网站:MDN JavaScript权威网站:JavaScript | MDN...
【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!
【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅! 🌱 前言:一棵树的浪漫,从数组开始说起 程序员的世界里,数组是最常见的基本结构之一,几乎每种语言、每种算法都少不了它。可你有没有想过,一组看似“线性排列”的有序数组,竟然可以**“长”成一棵平衡的二…...
