C语言不能很好的处理泛型数据,不过下面这个泛型栈提供了一种思路,把对数据的操作看作是对一格一格内存的操作,利用Memory头文件里的函数可以做到这一点。可以通过这种思路延伸到队列等其他数据结构中,把对数据的操作抽象为对内存的操作。当然在处理过程当中要处处小心,特别是对指针操作的时候。
另外,我写了一个用这个栈解数独的程序,可参考:《穷举法解数独》《更智能的解数独算法,让效率提升5倍!》
#include #include #include #include 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 #include #include #include #include #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