前言 - stack 设计思路

  先说说设计 stack 结构的原由. 以前我们再释放查找树的时候多数用递归的后续遍历去释放.

其内部隐含了运行时的函数栈, 有些语言中存在爆栈风险. 所以想运用显示栈来替代隐式函数栈.

这就是我们设计 stack 的背景.  而我们这里的 stack 设计思路也比较直白, 运用可变数组进行尾

部压入和尾部弹出操作. 具体可见下图. 从左到右式弹出过程,

从右到左就是压入过程.

正文 - stack 详细设计

  话不多说, 先看实现 code

stack.hhttps://github.com/wangzhione/structc/blob/master/structc/struct/stack.h

#ifndef _STACK_H
#define _STACK_H #include "struct.h" #define INT_STACK (1 << 8) //
// struct stack 对象栈
// stack empty <=> tail = -1
// stack full <=> tail == cap
//
struct stack {
int tail; // 尾结点
int cap; // 栈容量
void ** data; // 栈实体
}; //
// stack_init - 初始化 stack 对象栈
// stack_free - 清除掉 stack 对象栈
// return : void
//
inline void stack_init(struct stack * s) {
assert(s && INT_STACK > );
s->tail = -;
s->cap = INT_STACK;
s->data = malloc(sizeof(void *) * INT_STACK);
} inline void stack_free(struct stack * s) {
free(s->data);
} //
// stack_delete - 删除 stack 对象栈
// s : stack 对象栈
// fdie : node_f push 结点删除行为
// return : void
//
inline void stack_delete(struct stack * s, node_f fdie) {
if (s) {
if (fdie) {
while (s->tail >= )
fdie(s->data[s->tail--]);
}
stack_free(s);
}
} //
// stack_empty - 判断 stack 对象栈是否 empty
// s : stack 对象栈
// return : true 表示 empty
//
inline bool stack_empty(struct stack * s) {
return s->tail < ;
} //
// stack_top - 获取 stack 栈顶对象
// s : stack 对象栈
// return : 栈顶对象
//
inline void * stack_top(struct stack * s) {
return s->tail >= ? s->data[s->tail] : NULL;
} //
// stack_pop - 弹出栈顶元素
// s : stack 对象栈
// return : void
//
inline stack_pop(struct stack * s) {
if (s->tail >= ) --s->tail;
} //
// stack_push - 压入元素到对象栈栈顶
// s : stack 对象栈
// m : 待压入的对象
// return : void
//
inline void stack_push(struct stack * s, void * m) {
if (s->cap <= s->tail) {
s->cap <<= ;
s->data = realloc(s->data, sizeof(void *) * s->cap);
}
s->data[++s->tail] = m;
} #endif//_STACK_H

INT_STACK 是拍脑门搞得 8 x 8, 唯一的损耗点可能在 stack_top 和 stack_empty 配合的时候, 需要

冗余判断一步 tail >= 0. 不过随着条件的分支预测, 实际影响不大, 也还好. 我们不妨写个业务测试.

#include <stack.h>

void stack_test(void) {
struct stack s; stack_init(&s); char * str = NULL;
stack_push(&s, ++str);
stack_push(&s, ++str);
stack_push(&s, ++str); // 数据输出
for (char * now; (now = stack_top(&s)); stack_pop(&s))
printf("now = %p\n", now); stack_push(&s, ++str);
stack_push(&s, ++str); for (char * now; (now = stack_top(&s)); stack_pop(&s))
printf("now = %p\n", now); stack_free(&s);
}

那最终看 stack 实际运用场景吧, 运用显示栈来销毁查找树

// rtree_die - 后序删除树结点
static void rtree_die(struct $rtree * root, node_f fdie) {
struct $rtree * pre = NULL;
struct stack s; stack_init(&s);
stack_push(&s, root);
do {
struct $rtree * cur = stack_top(&s);
if ((!cur->left && !cur->right)
|| ((cur->left == pre || cur->right == pre) && pre)) {
fdie(pre = cur);
stack_pop(&s);
} else {
if (cur->right)
stack_push(&s, cur->right);
if (cur->left)
stack_push(&s, cur->left);
}
} while (!stack_empty(&s));
stack_free(&s);
}

更多细节代码可以阅读 rtree.h 对于二叉树后续非递归遍历, 压入右子树, 左子树,对比上次弹出的结点 ...

后记 - stack 未来展望

  Friendhttps://music.163.com/#/song?id=523560 

  错误是难免的, 欢迎交流提升 ~

  基于当前 stack 设计, 未来展望具体从两方面处理. 复杂方面, 可以优化一下内存相关操作, 初始化,

扩容, 缩容等. 简单方面, 大家也看出来了, 这个栈代码极其少, 纯追求性能都可以直接放弃封装, 内嵌到

需要使用的地方和大业务混为一体. 那今天就到这里了, 2019/08/25 21:50 Dota2 OG 王朝真强

C基础 stack 设计的更多相关文章

  1. (2.15)Mysql之SQL基础——开发设计最佳规范

    (2.15)Mysql之SQL基础——开发设计最佳规范 关键字:mysql三大范式,mysql sql开发规范 分析: show profile.mysqllsla.mysqldrmpslow.exp ...

  2. 小D课堂 - 新版本微服务springcloud+Docker教程_2_04微服务下电商项目基础模块设计

    笔记 4.微服务下电商项目基础模块设计     简介:微服务下电商项目基础模块设计 分离几个模块,课程围绕这个基础项目进行学习             小而精的方式学习微服务 1.用户服务       ...

  3. SpringCloud Alibaba实战(3:存储设计与基础架构设计)

    1.存储设计 在上一章中,我们已经完成了基本业务流程的梳理和服务模块的划分,接下来,开始设计数据存储. 虽然在微服务的理论中,没有对数据库定强制性的规范,但一般,服务拆分之后,数据库也会对应的拆分. ...

  4. Swift基础之设计折线坐标图

    最近添加了折线视图的样式,所以在这里用Swift语言重新再使用设计一下 首先设置纵坐标的数值是:体重 //体重        let weightLabel = UILabel.init(frame: ...

  5. 网页基础:网页设计(我所知道的所有的html和css代码(含H5和CSS3)),如有错误请批评指正

    最基础的网页设计,就是给你一个图片你做成一个网页,当然,我的工作是C#,个人网页的功底不是很高首先先认识一下网页的一些相关知识: 一般的,现在一个html网页一般包含html文件,css文件,js文件 ...

  6. 赢友网络通用框架V10.0.0(WinuAppSoft) 基础框架设计表

    /* * 版权所有:赢友网络(http://www.winu.net/) * 开发人员:新生帝(JsonLei) * 设计名称:赢友网络通用框架V10.0.0(WinuAppSoft) * 设计时间: ...

  7. WCF基础之设计和实现服务协定

    本来前面还有一个章节“WCF概述”,这章都是些文字概述,就不“复制”了,直接从第二章开始. 当然学习WCF还是要些基础的.https://msdn.microsoft.com/zh-cn/hh1482 ...

  8. C++标准库分析总结(五)——<Deque、Queue、Stack设计原则>

    本节主要总结标准库Deque的设计方法和特性以及相关迭代器内部特征 1.Deque基本结构 Deque(双向队列)也号称连续空间(其实是给使用者一个善意的谎言,只是为了好用),其实它使用分段拼接起来的 ...

  9. 一、基础篇--1.1Java基础-MVC设计思想

    MVC简介: MVC(Model View Controller) 是模型(model)-视图(view)-控制器(controller)的缩写.一种软件设计典范,用一种业务逻辑.数据.界面显示分离的 ...

随机推荐

  1. rushjs来自微软的单体仓库管理工具

    rushjs 是来自微软的单体仓库管理工具 ,与lerna 类似但是使用上稍显复杂 安装 npm install -g @microsoft/rush   简单使用 一个传统的基于npm 的处理 ~$ ...

  2. RFM - Customer Level Data

    Introduction ## Warning: package 'DT' was built under R version 3.5.2 RFM (recency, frequency, monet ...

  3. 服务器使用bbr加速配置

    服务器内核升级: 以centos7为例,配置之前可使用以下命令查看内核版本,若是4.0以上则无需对内核升级: uname -r 对内核升级的方法: 直接使用以下命令进行内核版本的下载: rpm --i ...

  4. mysql初始

    数据(data) : -描述事物的符号记录称为数据,符号既可以是数据,文字,图片,声音,语言等,符号都可以经过数字化后存入计算机中 - 计算机中描述一个事物,就需要抽取这一事物的典型特征,组成一条记录 ...

  5. map访问key不存在的情况下,用find。比[]直接访问的意思不一样,map[key]不返null

    key不存在的话则创建一个pair并调用默认构造函数 map<CGuid, CLibItem>::iterator iterItem = m_world->m_library_sce ...

  6. starUML

    下载地址: https://www.qqxiazai.com/down/10296.html 下载后解压,先运行 绿化.exe 然后右键管理员运行 StarUML.exe 进入后就可以画UML以及时序 ...

  7. 面试官问线程安全的List,看完再也不怕了!

    最近在Java技术栈知识星球里面有球友问到了线程安全的 List: 扫码查看答案或加入知识星球 栈长在之前的文章<出场率比较高的一道多线程安全面试题>里面讲过 ArrayList 的不安全 ...

  8. Json文件的BOM

    1.什么是BOM BOM: Byte Order Mark UTF-8 BOM又叫UTF-8 签名,其实UTF-8 的BOM对UFT-8没有作用,是为了支持UTF-16,UTF-32才加上的BOM,B ...

  9. [Gamma阶段]第四次Scrum Meeting

    Scrum Meeting博客目录 [Gamma阶段]第四次Scrum Meeting 基本信息 名称 时间 地点 时长 第四次Scrum Meeting 19/05/30 大运村寝室6楼 35min ...

  10. JAVA字符编码一:Unicode,GBK,GB2312,UTF-8概念基础

    第一篇:JAVA字符编码系列一:Unicode,GBK,GB2312,UTF-8概念基础 来源:holen'blog   对字符编码与Unicode,ISO 10646,UCS,UTF8,UTF16, ...