头文件:

#ifndef STACK_H
#define STACK_H#define STACK_INC_SIZE   5   //栈每次的增长大小
#define STACK_DEBUG 0X0010
#define STACK_INFO 0X0001
#define STACK_MSG(level, format, argc...) do{\if(stack_debug_level & level) \printf("["#level"]"format, ##argc);    \else   \;  \}while(0)struct data{void *value;int size;
};typedef struct stack{int top; struct data *data;struct stack *next;int used;int (*push)(struct stack* stack, void *data, int size);void* (*pop)(struct stack* stack);void (*destory)(struct stack** stack);
}t_stack;t_stack *init_stack(void);#endif

c文件

/*实现一个动态增长的栈思路:用多个栈组成链表leon2016-1-3 22:30:19
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "stack.h"static int stack_debug_level = 0; //STACK_DEBUG | STACK_INFO;/*返回栈内数据的指针!*/
static void* pop(struct stack* stack)
{t_stack *s = stack;if(!s){return NULL;}while(s->next && s->next->used){s = s->next;}if(s->top == 0){STACK_MSG(STACK_INFO, "The stack is enpty\n");return NULL;}/*这是栈里的最后一个元素,标记栈为未使用*/if(s->top == 1){s->used = 0;}s->top--;STACK_MSG(STACK_DEBUG, "stack pop success, the value addr %p\n", s->data[s->top].value);return s->data[s->top].value;
}static int push(struct stack* stack, void *data, int size)
{t_stack *inserted_stack;if(!stack){return -1;}/*找到最后一个可以使用的栈*/while(stack->next && stack->used){stack = stack->next;}if(stack->top < STACK_INC_SIZE){inserted_stack = stack;}else /*溢出*/{/*没有可以使用的栈,则初始化新栈*/if(!stack->next){inserted_stack = init_stack();if(!inserted_stack){return -1;}stack->next = inserted_stack;}   /*used = 0, 以前有开辟新栈,只是出栈使其成为了空栈*/else{inserted_stack = stack->next;}STACK_MSG(STACK_INFO, "increce stack size\n");    }inserted_stack->data[inserted_stack->top].value = malloc(size);if(!inserted_stack->data[inserted_stack->top].value){printf("The memery is not enough!\n");return -1;}memcpy(inserted_stack->data[inserted_stack->top].value, data, size);inserted_stack->data[inserted_stack->top].size = size;inserted_stack->top++;inserted_stack->used = 1;STACK_MSG(STACK_DEBUG, "stack push success, top = %d\n", inserted_stack->top);return 0;
}static void destory(struct stack** stack)
{t_stack *s = *stack;t_stack *del = s;int i;if(!s){return;}while(s){for(i = 0; i < STACK_INC_SIZE; i++){if(s->data[i].value)free(s->data[i].value);}free(s->data);del = s;s = s->next;free(del);}*stack = NULL;STACK_MSG(STACK_INFO, "stack destory success\n");return;
}/*初始化一个栈*/
t_stack *init_stack(void)
{t_stack *s = (t_stack *)malloc(sizeof(t_stack));if(!s){printf("The memery is not enough!\n");return NULL;}memset(s, 0x0, sizeof(t_stack));s->data = malloc(sizeof(struct data) * STACK_INC_SIZE);if(!s->data){printf("The memery is not enough!\n");return NULL;}memset(s->data, 0x0, sizeof(struct data) * STACK_INC_SIZE);s->pop = &pop;s->push = &push;s->destory = &destory;STACK_MSG(STACK_INFO, "stack init success\n");return s;
}

最开始我用 s->data[s->top]->value的方式取value编译报错,一开始想不明白,因为data定义为指针的,就想着应该用'->'而不是'.'。后来明白了,data[]这个中括号,会取值,因此后面该接‘.’。如果执意要用‘->’,需要这要写:(s->data + s->top)->value.

测试代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "stack.h"int main(int argc, char *argv[])
{t_stack *s = init_stack();if(!s)return -1;int i = 0;for(i = 1; i < argc; i++){s->push(s, (void *)argv[i], strlen(argv[i]) + 1);}char *p = (char *)(s->pop(s));while(p){printf("%s\n", p);p = (char *)(s->pop(s));}s->destory(&s);return 0;
}

makefile

TARGET = a.outOBJ = main.o stack.oall: $(OBJ)gcc -o $(TARGET) $(OBJ)./$(TARGET) 0 1 2 3 4 5 6 7%.o: %.c gcc -Wall -Werror -g -MMD -c $< clean:-rm $(OBJ) $(OBJ:%.o=%.d) a.out-include $(OBJ:%.o=%.d).PHONY: all clean

一个动态增长的栈实现相关推荐

  1. java动态扩展_java栈内存动态扩展要怎么理解?要如何实现?

    小伙伴们知道如何在java栈中内存动态扩展吗?这是虚拟机中的一个概念,下面让我们一起来看看该如何实现吧. 一.内存概念 在java中,我们一般会简单把java内存区域划为两种:堆内存与栈内存.其实这种 ...

  2. 用 python 做一个动态可视化交互大屏

    你可能经常会在公司前台.展会.路演时看到可视化数据的交互大屏.今天我们就来用 python 做一个动态可视化的交互大屏图. 一.项目背景 随着科技的飞速发展,数据呈现爆发式的增长,任何人都摆脱不了与数 ...

  3. golang切片slice详解:介绍、内存分析、定义、遍历、切片可以继续切片、切片可以动态增长、切片的拷贝及底层原理

    切片的引入 [1]切片(slice)是golang中一种特有的数据类型 [2]数组有特定的用处,但是却有一些呆板(数组长度固定不可变),所以在 Go 语言的代码里并不是特别常见.相对的切片却是随处可见 ...

  4. 手撸一个动态数据源的Starter 完整编写一个Starter及融合项目的过程 保姆级教程

    手撸一个动态数据源的Starter! 文章目录 手撸一个动态数据源的Starter! 前言 一.准备工作 1,演示 2,项目目录结构 3,POM文件 二.思路 三.编写代码 1,定义核心注解 Ds 2 ...

  5. 动态区域(栈、堆)、静态存储区(数据段和程序段)

    动态区域(栈.堆).静态存储区(数据段和程序段) 内容收集比较混乱,仅供参考 版本一:      堆 1 类成员变量存放在堆区,所有类的实例和数组都是在堆上分配内存的,堆内存由存活和死亡的对象,空闲碎 ...

  6. android碎片调用动态碎片,Android Training - 使用碎片创建一个动态UI

    为了能够在Android中创建动态和多窗口的用户界面,你需要封装UI组件和activity行为在不同的模块中,以便你可以在不同的activity间切换.你可以使用Fragment类创建这些模块,类似于 ...

  7. 每天一道LeetCode-----实现一个栈,提供一个接口用于返回栈中最小值

    Min Stack 原题链接Min Stack 实现一个栈,除了基本功能外需要提供一个接口用于返回栈中元素的最小值 基本功能使用std::stack就够了,如果每次需要最小值时都遍历栈中元素的话会很麻 ...

  8. sqlserver如何定义一个静态变量_[Bazel]自定义规则实现将多个静态库合并为一个动态库或静态库...

    1 前言 2 自定义规则实现 2.1 规则功能 2.2 实现规则的理论基础 2.3 规则代码实现 3 总结 4 参考资料 1 前言 为了实现如标题所述的将多个静态库合并为一个动态库,内置的 Bazel ...

  9. 设单链表中存放n个字符,试设计一个算法,使用栈推断该字符串是否中心对称...

    版权声明:本文为博主原创文章.未经博主同意不得转载. vasttian https://blog.csdn.net/u012860063/article/details/28281631 转载请注明出 ...

最新文章

  1. java beetl 视频_08.Beetl自定义方法以及直接访问java类方法---《Beetl视频课程》
  2. Python | 用PrettyPrinter,让Python输出更漂亮,你值得拥有
  3. java存款程序_JAVA实现账户取款和存款操作
  4. JavaScript笔记(3)
  5. 程序员面试金典 - 面试题 04.01. 节点间通路(图的遍历)
  6. 信息技术计算机网络课堂实录,信息技术教案:计算机网络简介
  7. 51nod--1212 最小生成树
  8. 前端基础到进阶(1):HTML基础入门
  9. 更新IIS下WCF服务产生的两则问题
  10. 电子计算机工作的特征是什么,电子计算机的基本特征是什么?
  11. Eclipse-Mybatis-generatorConfig.xml
  12. 字节跳动算法工程师总结:中高级java开发面试题
  13. 利用两数之和实现两个数交换(java版本)
  14. UDF-java获取名字中的姓
  15. 3. 请列举java ee的主要新特性_JavaEE考试题
  16. web压力测试工具比较
  17. java学生管理系统界面设计
  18. python 爬取taptap热门榜
  19. element el-table表格数据合并
  20. flash player 11.2 64位 linux,Adobe Flash Player 11.2.202 Beta 1支持 64位操作系统

热门文章

  1. pwm一个时间单位_通过PWM进行数模转换的滤波电路分析计算
  2. python 数据清洗 豆瓣电影_Python高阶操作--关于数据清洗
  3. php io操作,lua 的io操作,非常详细
  4. diskgenius创建efi分区_DISKGEN 专业版修改硬盘为GPT分区 ESP分区图文教程
  5. Oracle 开窗函数--转
  6. vux在ISO中异常 this.$vux.confirm.show
  7. Selenium基于Python 进行 web 自动化测试
  8. javascript二维数组
  9. Java连接SQLite数据库
  10. hibernate的数据关联映射