新闻详情

新闻详情

首页 / 资讯中心 / 详情

C 语言通用自增长栈(Generic Self-growing Stack)源码级解析:基于 data_structures/stack 模块

发布时间:2026/10/1 9:44:38来源:尧图网络
C 语言通用自增长栈(Generic Self-growing Stack)源码级解析:基于 data_structures/stack 模块
示例工程【免费下载链接】CCollection of various algorithms in mathematics, machine learning, computer science, physics, etc implemented in C for educational purposes.项目地址https://gitcode.com/gh_mirrors/c/C点击查看免费下载本指南以仓库 data_structures/stack/README.md 为骨架深入讲解其中实现的模块化、泛型、自增长栈它通过void *指针数组容纳任意类型的数据容量不足时自动扩容并向调用方隐藏全部内部状态数据隐藏。读完本文你将掌握该栈的完整公共接口、底层实现机制扩容、偏移量、计数器、两种编译测试方式以及基于链表的对照实现可直接在自己的 C 项目中复用这套数据结构。模块概览一个文件即可引入data_structures/stack目录下包含以下组成部分文件作用stack.h公共接口头文件使用方只需#include stack.hstack.c基于动态数组的栈实现含自增长逻辑main.c面向数组栈的交互式测试框架程序stack_linked_list/另一种基于链表的栈实现含 stack.h、stack.c、main.c、Makefile如 README 所述使用方只需引入stack.h一个头文件即可获得全部能力头文件只暴露函数原型具体的内部数据结构指针数组、容量、计数器等全部隐藏在stack.c中体现了良好的封装与数据隐藏原则。公共接口五个核心函数README 定义的公共接口如下头文件 stack.h 中一一对应声明此外还额外声明了top()函数void initStack(); void push(void *object); void *pop(); int size(); int isEmpty();函数签名行为说明initStackvoid initStack()将栈初始化为容量为10 个元素的动态数组pushvoid push(void *object)将任意指针压入栈顶popvoid *pop()弹出并返回栈顶元素前置条件栈非空违反会触发断言sizeint size()返回当前栈内元素个数isEmptyint isEmpty()栈空返回1否则返回0由于栈元素类型为void *这套接口可以存放任何类型的指针整数、结构体、字符串等这正是泛型generic的含义。同时接口里还隐含了头文件中额外声明的 top()与pop()不同它只查看栈顶元素而不移除。源码级实现原理数据隐藏 自动扩容内部状态与初始化stack.c 通过文件级全局变量维护栈状态调用方完全不可见void **array; /* 指向实际存储元素的 void* 指针数组 */ int max 10; /* 当前容量 */ int counter 0;/* 元素计数器 */ int offset -1;/* 指向栈顶元素的偏移地址 */initStack()在 stack.c 中只做一件事——为max10个void *指针分配内存并用assert(array)确保分配成功void initStack() { array malloc(sizeof(void *) * max); assert(array); /* tests whether pointer is assigned to memory. */ }注意初始化后counter 0、offset -1表示栈为空、栈顶尚不存在任何元素。push 与自动扩容机制push()位于 stack.c是自增长特性的核心。其逻辑为先用assert(object)拒绝空指针入栈若counter max未满offset指向新栈顶*(array offset) object写入元素counter若栈已满调用内部工具函数grow()扩容然后递归调用自身完成入栈。扩容函数 grow() 不在公共接口中属于实现细节void grow() { max 10; /* 容量每次增加 10 */ void **tmp malloc(sizeof(void *) * max); for (i 0; i max - 10; i) /* 拷贝旧数组元素 */ *(tmp i) *(array i); free(array); /* 释放旧数组 */ array tmp; }从源码结构可以看到三个明确结论扩容步长固定为 10 个元素避免频繁调用malloc每次扩容都会重新分配整块内存并整体拷贝属于搬家式扩容与按需倍增的实现相比摊还开销略高但实现直观、便于教学理解push通过递归重试实现满则先扩容再入栈的闭环代码简洁。pop / size / isEmpty / toppop()位于 stack.cvoid *pop() { void *top *(array offset); assert(top); assert(!isEmpty()); /* 前置条件栈非空 */ offset--; counter--; return top; }它先断言栈非空与 README 中assumes: stack not empty的约定一致取出栈顶指针后下移offset、递减counter。注意它返回的是元素指针本身不释放元素内存——谁压入谁负责释放这是使用本栈时需要牢记的内存约定。其余函数实现极为精简stack.cint size() { return counter; } int isEmpty() { return counter 0; } void *top() { return array[offset]; }其中size()直接返回内部计数器isEmpty()等价于判断counter 0top()则按offset直接读取栈顶而不修改任何状态。编译与测试两种验证方式方式一链表栈带 Makefile可直接构建进入 stack_linked_list 目录按 Makefile 执行cd data_structures/stack/stack_linked_list make ./mainmain.c 依次压入 14 四个元素打印栈大小与内容再连续两次Stack_pop并打印可直观验证 LIFO后进先出行为Size: 4 Stack [Top --- Bottom]: 0x4 0x3 0x2 0x1 Stack after popping: Stack [Top --- Bottom]: 0x3 0x2 0x1 Stack after popping: Stack [Top --- Bottom]: 0x2 0x1方式二数组版交互式测试程序根目录下的 main.c 是一个交互式菜单程序提供 Push、Pop、Peek、Update、Display 五个操作可作为理解栈语义的参考测试框架gcc main.c -o stack_menu ./stack_menu运行后按菜单输入选择即可完成压栈、弹栈、查看栈顶、按位置更新元素以及从栈顶到栈底打印全部元素等操作选择0或按Ctrl-C退出。直接集成泛型栈到自有项目若要在自己的项目中复用 stack.c 与 stack.h只需gcc -c stack.c -o stack.o gcc your_main.c stack.o -o your_program并在your_main.c中#include stack.h随后依次调用initStack()→push()/pop()/top()即可。注意每个逻辑上独立的栈共用同一组全局状态如需多个互不干扰的栈实例更适合选用下方的链表实现。对照实现基于链表的栈stack_linked_listREADME 明确列出了第二种实现 stack_linked_list。其头文件 stack.h 采用经典的typedef 隐式指针风格封装句柄#define T Stack_T typedef struct T *T; /* 对外只暴露不透明句柄 */ extern T Stack_init(void); extern int Stack_size(T stack); extern int Stack_empty(T stack); extern void Stack_push(T stack, void *val); extern void *Stack_pop(T stack); extern void Stack_print(T stack);实现 stack.c 中每个节点为elem_t { void *val; struct elem *next; }栈结构体只维护count与head指针Stack_init分配栈句柄并置空Stack_push每次在表头插入新节点t-next stack-head; stack-head t;O(1)Stack_pop从表头摘除节点并free(t)返回保存的值Stack_print从栈顶向栈底打印各元素的指针值。与数组版相比链表版天然无容量上限、无需扩容逻辑且每个栈实例独立句柄封装但每个元素多一个指针节点的内存开销且需要显式Stack_init初始化句柄。两种实现恰好形成数组式自动扩容与链表式动态增长两种典型栈方案的对照。使用注意事项小结必须先initStack()再执行任何入栈/出栈操作否则array为未初始化指针pop()的前置条件是栈非空空栈弹栈会触发assert失败发布构建需自行移除断言或先检查isEmpty()push(NULL)会被断言拦截不可入栈空指针栈内保存的是指针本身栈退出/元素弹出后由调用方负责释放指向的动态内存数组版为全局单例状态适合单栈场景多栈并发或长期运行场景建议使用链表版句柄封装。综上所述data_structures/stack以极简的公共接口initStack/push/pop/size/isEmpty配合容量满 10 增 10的自增长机制为 C 语言学习者提供了一个兼顾封装性、泛型性与可读性的栈参考实现其相邻的链表版实现则展示了同一抽象在不同存储策略下的工程取舍。赞分享示例工程【免费下载链接】CCollection of various algorithms in mathematics, machine learning, computer science, physics, etc implemented in C for educational purposes.项目地址https://gitcode.com/gh_mirrors/c/C点击查看免费下载相关推荐解密Qwen3.6-27B-Fable-Fusion-711多阶段微调如何打造超越GPT-4的开源模型解密Qwen3.6 27B Fable Fusion 711多阶段微调如何打造超越GPT 4的开源模型 Qwen3.6 27B Fable Fusion 71人工智能大模型基础模型多模态Full Stack FastAPI Template基于 FastAPI 的生产级全栈项目模板指南Full Stack FastAPI Template基于 FastAPI 的生产级全栈项目模板指南 本指南介绍 FastAPI 官方推荐的 Full Sta后端Web框架API设计如何将PyTorch-NPU/deberta_base集成到生产环境终极部署指南与最佳实践如何将PyTorch NPU/deberta_base集成到生产环境终极部署指南与最佳实践 想要将先进的 DeBERTa 模型部署到生产环境这篇完整指南将带上一篇Instabot故事功能完全指南下载、上传和监控用户故事下一篇Git-it技术架构揭秘Electron框架下的Git教学工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

综合知识侧重广度,案例分析侧重建模、数据库、算法、设计模式与代码补全等实践能力 2026/10/1 10:21:36

综合知识侧重广度,案例分析侧重建模、数据库、算法、设计模式与代码补全等实践能力

计算机系统知识 包括计算机组成、指令系统、存储系统、校验码、流水线、RAID、操作系统进程管理、存储管理、文件管理等。上午题常考概念辨析和计算。数据结构与算法 重点包括线性表、栈队列、树与二叉树、图、排序、查找、哈希、动态规划、贪心、分治、回溯等。算法题不仅要会…

阅读更多 →
现代计算机大多遵循冯·诺依曼体系结构,其核心思想是“存储程序”和“程序控制” 2026/10/1 10:21:36

现代计算机大多遵循冯·诺依曼体系结构,其核心思想是“存储程序”和“程序控制”

计算机科学是一门研究信息、计算与系统的学科,其知识体系既包括硬件基础,也包括软件方法;既涉及底层数据表示和系统运行,也涉及上层软件工程、信息安全与标准化规范。掌握这些基础知识,有助于理解计算机如何工作、软件…

阅读更多 →
shell与权限 2026/10/1 10:21:35

shell与权限

目录 一、基础指令收尾 1.1 tar :文件归档与压缩,不打开,直接看内容 1.2 scp: 远程拷贝,跨机文件传输工具 1.3 bc: 交互式计算器工具 1.4 面试题讲解 1.5 常用热键 1.6 shutdown :关机 二、shell命令 2.1 操作系统&…

阅读更多 →
【C语言学习】冒泡排序与选择排序详解及代码实战 2026/10/1 10:21:29

【C语言学习】冒泡排序与选择排序详解及代码实战

上一期讲解了C语言排序的一些知识点,这一期要介绍冒泡排序和选择排序两种排序方式,包括注意点和代码。 一、冒泡排序 冒泡排序:相邻的元素两两比较,大的放右边,小的放左边。 1.第一轮比较完毕后,max确定 2.…

阅读更多 →
GEO 为什么没有公认榜单?附一套可复现的自建评测标准 2026/10/1 10:21:22

GEO 为什么没有公认榜单?附一套可复现的自建评测标准

先说结论:GEO 这个品类不会有公认榜单,短期内也不会有。 不是没人想做,是它在结构上做不成。评估对象的效果无法跨主体比较,有能力出榜单的三类角色又各自带着利益冲突。等一份可信名单,等于把节奏交给一个可能永远不会…

阅读更多 →
**数据结构、操作系统、数据库、网络**是核心拿分模块,应重点投入 2026/10/1 10:21:09

**数据结构、操作系统、数据库、网络**是核心拿分模块,应重点投入

数据表示:二进制、八进制、十进制、十六进制转换;原码、反码、补码;浮点数表示。运算与校验:逻辑运算、校验码,如 CRC、海明码。CPU 与指令系统:运算器、控制器、寄存器、指令流水线、CISC/RISC。存储系统&…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉