现在我们来讲这个通用STACK的具体实现, 在头文件里面我们只是声明了struct _ds_stk, 由于接口里面使用到的都是其指针类型而将其具体定义实现了隐藏。
其具体的结构定义如下所示:
struct _ds_stk {
size_t _top; /** top of the stack */
struct node {
void* value; /** stack value */
struct node* next;/** next stack value */
}* _head;
ds_alloc_func _allocF; /** allocate function */
ds_free_func _freeF; /** deallocate function */
ds_copy_func _copyF; /** copy data function */
};
在这个结构里面我们可以看到使用了一个 struct node的链表来存储到栈里面的具体数据信息, _top用于记录该栈里面存储的元素个数, 同时还有需要使用到的相应元素操作的函数。
先实现默认的元素操作函数(为了防止客户程序员忘记实现自己对于的操作函数, 内部默认的元素操作接口, 都只是对指针的单纯记录, 并不对具体元素的信息进行拷贝……)
static void* _defAlloc(void* v) { return v; }
static void _defFree(void* v) {}
static int _defCopy(void* dest, void* src) {
dest = src; return 1;
}
接下来, 便是该通用STACK的各个相关操作接口的具体实现了, 为了实现栈的(FILO), 我们对该链表的元素插入操作实行了头插法, 这样出栈就可以是直接释放掉链表头结点的元素数据信息了, 这样便实现了栈的先进后出。其具体实现如下所示:
struct _ds_stk*
ds_stk_new(ds_alloc_func allocF, ds_free_func freeF, ds_copy_func copyF) {
struct _ds_stk* stk = NULL;
size_t _sz = sizeof(struct _ds_stk);
stk = (struct _ds_stk*)malloc(_sz);
if (NULL == stk) return NULL;
memset(stk, 0, _sz);
stk->_allocF = NULL != allocF ? allocF : _defAlloc;
stk->_freeF = NULL != freeF ? freeF : _defFree;
stk->_copyF = NULL != copyF ? copyF : _defCopy;
return stk;
}
void
ds_stk_free(struct _ds_stk** stk) {
struct node* i = NULL;
struct node* u = NULL;
if (NULL == *stk) return;
for (i = (*stk)->_head; NULL != i; i = u) {
u = i->next;
(*stk)->_freeF(i->value);
free(i);
}
free(*stk);
*stk = NULL;
}
size_t
ds_stk_size(struct _ds_stk* stk) {
return (NULL != stk ? stk->_top : 0L);
}
int
ds_stk_empty(struct _ds_stk* stk) {
return (NULL != stk ? 0L == stk->_top : 0);
}
int
ds_stk_push(struct _ds_stk* stk, void* v) {
struct node* e = NULL;
size_t sz = sizeof(struct node);
if (NULL == stk) return 0;
e = (struct node*)malloc(sz);
if (NULL == stk) return 0;
memset(e, 0, sz);
e->value = stk->_allocF(v);
e->next = stk->_head;
stk->_head = e;
stk->_top++;
return 1;
}
int
ds_stk_pop(struct _ds_stk* stk, void* v) {
struct node* e = NULL;
if (NULL == stk || NULL == v || stk->_top <= 0)
return 0;
e = stk->_head;
stk->_head = e->next;
stk->_top--;
stk->_copyF(v, e->value);
stk->_freeF(e->value);
free(e);
e = NULL;
return 1;
}
现在看了通用栈的具体实现觉得很简单是吧? 嘿嘿, 其实这样也是一种设计的原则, 很多东西我们自己是不知道的, 但是客户知道, 那我们就让客户去实现不就成了, 这样我们就只需要向客户提供实现的原则方法便OK了。
好了今天就到此为止吧, 其实明白了这个通用STACK的实现, 实现别的通用数据结构就很简单了。(如有不合理的地方希望大家多多指出, 若有更优秀的见解希望高人不吝赐教, 谢谢!)