C语言实现可伸缩的栈结构

// stack.h

#ifndef _STACK_H_
#define _STACK_H_

#ifdef __cplusplus
extern "C" {
#endif

/* 栈使用方法举例
 *      // 声明栈结构并初始化
 *      stack_t *stack = NULL;
 *      // 数据压栈
 *      void *data = get_data(); // get_data为用户函数
 *      stack_push(&stack, data);
 *      // 数据出栈
 *      void *data = stack_pop(&stack);
 *      // 数据不出栈, 获取栈顶数据
 *      void *data = stack_top(&stack);
 *      // 销毁栈
 *      stack_destroy(&stack, destroy_data); // destroy_data为销毁data的函数
 */

// 接口声明
typedef struct stack stack_t;
void stack_push(stack_t **pstk, void *value);
void* stack_pop(stack_t **pstk);
void* stack_top(stack_t **pstk);

// 调用者自行实现销毁栈的函数, 或调用如下函数销毁栈
static inline void
stack_destroy(stack_t **pstk, void (*destroy_element)(void*))
{
    void *value;
    while (!!(value = stack_pop(pstk)))
        if (destroy_element)
            destroy_element(value);
}

#ifdef __cplusplus
} // extern "C"
#endif

#endif // _STACK_H_

// stack.c

#include "stack.h"

// stack结构无需对用户暴露
struct stack {
    int top;
    int cnt;
    struct stack *next;
    void *value[1];
};

static inline int
stack_empty(stack_t *stk)
{
    return (stk->top == -1);
}

static inline int
stack_full(stack_t *stk)
{
    return (stk->top + 1 == stk->cnt);
}

#define DEFAULT_STACK_CNT 128

static inline void
stack_expand(stack_t **pstk)
{
    // 这里假定内存分配不会失败,可以实现这样的函数,例如kmem_alloc(size, KM_SLEEP), 分配不到内存则睡眠等待
    stack_t *stk = malloc(sizeof(stack_t)
        + sizeof(void*) * (DEFAULT_STACK_CNT - 1));
    stk->next = *pstk;
    stk->top = -1;
    stk->cnt = DEFAULT_STACK_CNT;
    
    *pstk = stk;
}

static inline void
stack_reduce(stack_t **pstk)
{
    stack_t *stk = *pstk;
    while (stk && stack_empty(stk)) {
        stack_t *next = stk->next;
        free(stk);
        stk = next;
    }
    *pstk = stk;
}

void
stack_push(stack_t **pstk, void *value)
{
    if (!*pstk || stack_full(*pstk))
        stack_expand(pstk);
    
    stack_t *stk = *pstk;
    stk->value[++stk->top] = value;
}

void*
stack_pop(stack_t **pstk)
{
    if (!*pstk)
        return (NULL);
    
    /* stk!=NULL则stk->top一定有效, 因为每次出栈后都会reduce,
     * 如果全部元素出栈, reduce会释放栈空间, stk会置NULL */
    stack_t *stk = *pstk;
    void *value = stk->value[stk->top--];
    stack_reduce(pstk);
    
    return (value);
}

void*
stack_top(stack_t **pstk)
{
    stack_t *stk = *pstk;
    return (stk ? stk->value[stk->top] : NULL);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小瓶子36

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值