前言 - 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. ABP 基本操作

    基本信息: 官网:https://aspnetboilerplate.com api:https://aspnetboilerplate.com/Pages/Documents/Articles-Tu ...

  2. OJ笔记

    1.未考虑程序没有输出导致的格式错误: 原代码:(即使没有输出,ans集合元素为0,也输出了空格) set<int>::iterator it=ans.begin(); while(it! ...

  3. fiddler实现B/S端、APP抓包分析遇到的各种疑问

    阅读本文前您需要先下载fiddler并成功安装,并且要有一丢丢测试和接口基础或者在学习fidder时遇到了问题,或许本文可以帮助到你 一.B/S端抓包 Fiddler设置 1. 官网下载fiddler ...

  4. ModuleNotFoundError: No module named 'rest_framework_swagger'

    pip3.6 install django-rest-swagger

  5. 享元模式(Flyweight Pattern)

    定义: 采用一个共享来避免大量拥有相同内容对象的开销.这种开销中最常见.直观的就是内存的损耗.享元模式以共享的方式高效的支持大量的细粒度对象. 享元的英文是flyweight,是一个来自体育方面的专业 ...

  6. 哈希表查找(散列表查找) c++实现HashMap

    算法思想: 哈希表 什么是哈希表 在前面讨论的各种结构(线性表.树等)中,记录在结构中的相对位置是随机的,和记录的关键字之间不存在确定的关系,因此,在结构中查找记录时需进行一系列和关键字的比较.这一类 ...

  7. pandas.DataFrame.sample随机抽样

    https://study.163.com/course/courseMain.htm?courseId=1006383008&share=2&shareId=400000000398 ...

  8. vs2015 如何更改背景主题颜色

    打开vs2015 步骤:工具--> 选项 -->环境-->常规-->主题设置

  9. QT自定义信号和槽

    最近项目中使用到QT,在此记录一下QT的核心,信号与槽: QObject::connect(const QObject *sender, const char *signal, const QObje ...

  10. Eureka Server 集群配置

    注册中心: debug: true spring: application: name: eureka-server logging: level: com.netflix.eureka: 'off' ...