C语言实现一个泛型栈

C语言不能很好的处理泛型数据,不过下面这个泛型栈提供了一种思路,把对数据的操作看作是对一格一格内存的操作,利用Memory头文件里的函数可以做到这一点。可以通过这种思路延伸到队列等其他数据结构中,把对数据的操作抽象为对内存的操作。当然在处理过程当中要处处小心,特别是对指针操作的时候。

另外,我写了一个用这个栈解数独的程序,可参考:《穷举法解数独》更智能的解数独算法,让效率提升5倍!


#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <memory.h>

void newStack(stack *s, size_t elemSize);
void disposeStack(stack *s, void (*remainPro)(void *elem));
void push(stack *s, void *elem);
void pop(stack *s, void *elem);
int isEmpty(stack *s);  

typedef struct
{
        void    *elem;                 // 元素起始指针
        int     elemSize;         // 单位元素大小
        int     top;              // 栈顶元素位置
        int     mallocNum;        // 已分配元素数量
}stack;

void newStack(stack *s, size_t elemSize)
{
        assert(elemSize > 0);
        s->elem = malloc(4 * elemSize);       // 初始分配4个单位长度 
        assert(s->elem != NULL);
        s->elemSize = elemSize;
        s->top = 0;
        s->mallocNum = 4;
}

void disposeStack(stack *s, void (*remainPro)(void *elem))
{
        if(s->top > 0 && remainPro != NULL){     // 栈不为空,并且定义了处理函数
                void *tmpElem;
                while(s->top > 0){
                        pop(s,&tmpElem);                   // 弹出元素,并交给处理函数处理
                        remainPro(tmpElem);
                }
        }
        free(s->elem);
}

void push(stack *s, void *elem)
{
        if (s->top == s->mallocNum){         // 如果栈满了,那么重新分配2倍大的空间 
                s->mallocNum *= 2;
                s->elem = realloc(s->elem, s->mallocNum * s->elemSize);
                assert(s->elem != NULL);
        }

        memcpy(s->elem + s->top * s->elemSize, elem, s->elemSize);      // 内存块复制实现入栈 
        s->top++;
}

void pop(stack *s, void *elem)
{
        assert(s->top > 0);
        s->top--;
        memcpy(elem, s->elem + s->top * s->elemSize, s->elemSize);      // 复制内存块出栈 
}      

int isEmpty(stack *s)
{
        return s->top == 0;
}

说明:disposeStack函数的第二个参数是一个函数指针,指向的函数原型是void remainPro(void *elem),用于在销毁栈时处理栈中残余的元素,比如当栈中的元素是malloc所分配的指针时,remainPro可以调用free处理栈中剩余的元素

测试代码:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <memory.h>
#include <string.h>

#define LEN 5

void freeStr(void *str)
{
        printf("%s\n",str);
        free(str);
}

int main(int argc, const char *argv[])
{
        stack myStack;
        char *str[LEN];
        char *tmp;

        str[0] = strdup("abc");
        str[1] = strdup("def");
        str[2] = strdup("ghi");
        str[3] = strdup("jkl");
        str[4] = strdup("mno");
        
        newStack(&myStack,sizeof(char *));
        push(&myStack, &str[0]);
        push(&myStack, &str[1]);
        push(&myStack, &str[2]);
        push(&myStack, &str[3]);
        push(&myStack, &str[4]);
        
        pop(&myStack,&tmp);
        printf("%s\n",tmp);
        free(tmp);

        disposeStack(&myStack,freeStr);

        return 0;
}

输出结果:

mno
jkl
ghi
def
abc


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值