今天我们开始讲解通用单链表(简写为slist, 以后不再说明)的实现。
当然用纯C也有许多种方式来实现通用的slist。不过在正式开始讲解通用slist的实现之前, 我们先复习一下一个简单的int类型的slist的实现。
首先我们先定义出slist的操作接口, 通常来说, 对于slist的操作一般有: 前插入、后插入、获取元素的个数、是否为空、清除所有的slist元素、删除链表头以及获取头和尾的具体元素值信息。
我们将slist(只针对int类型)的通用操作声明如下:
struct _ds_slist;
extern struct _ds_slist* ds_slistNew(void);
extern void ds_slistFree(struct _ds_slist** _ppd);
extern int ds_slistSize(struct _ds_slist* _p);
extern int ds_slistEmpty(struct _ds_slist* _p);
extern void ds_slistClear(struct _ds_slist* _p);
extern int ds_slistPushback(struct _ds_slist* _p, int _x);
extern int ds_slistPushfront(struct _ds_slist* _p, int _x);
extern int ds_slistPopfront(struct _ds_slist* _p);
extern int ds_slistFront(struct _ds_slist* _p);
extern int ds_slistBack(struct _ds_slist* _p);
有了这些操作接口, 相信要具体实现也是很简单的了, 我们在这里只是声明了struct _ds_slist, 这样我们就可以把其的具体数据结构的定义隐藏封装到具体实现文件了。
在具体的实现文件, 我们将struct _ds_slist的具体定义如下:
struct _slist_node {
int _x;
struct _slist_node* _next;
};
struct _ds_slist {
int _size;
struct _slist_node* _head;
struct _slist_node* _tail;
};
由于在具体的slist操作过程中, 如对单链表的插入操作经常会创建一个新的节点, 我们提取出创建一个新的节点的方法, 其实现如下:
static inline
struct _slist_node* _slistNode(int _x) {
struct _slist_node* _n = NULL;
size_t _size = sizeof(struct _slist_node);
DS_malloc(_n, struct _slist_node, _size);
if (NULL != _n) _n->_x = _x;
return _n;
}
现在, slist的相应操作接口的实现如下:
struct _ds_slist* ds_slistNew(void) {
struct _ds_slist* _p = NULL;
size_t _size = sizeof(struct _ds_slist);
DS_malloc(_p, struct _ds_slist, _size);
return _p;
}
void ds_slistFree(struct _ds_slist** _ppd) {
ds_slistClear(*_ppd);
DS_free(*_ppd);
}
int ds_slistSize(struct _ds_slist* _p) {
return (NULL != _p ? _p->_size : 0);
}
int ds_slistEmpty(struct _ds_slist* _p) {
return (NULL != _p ? NULL == _p->_head : 0);
}
void ds_slistClear(struct _ds_slist* _p) {
struct _slist_node* _i = NULL;
if (NULL == _p) return;
while (NULL != _p->_head) {
_i = _p->_head;
_p->_head = _p->_head->_next;
DS_free(_i);
}
_p->_size = 0;
}
int ds_slistPushback(struct _ds_slist* _p, int _x) {
struct _slist_node* _n = _slistNode(_x);
if (NULL == _p || NULL == _n) return 0;
if (NULL == _p->_head) _p->_head = _p->_tail = _n;
else {
_p->_tail->_next = _n;
_p->_tail = _n;
}
_p->_size++;
return 1;
}
int ds_slistPushfront(struct _ds_slist* _p, int _x) {
struct _slist_node* _n = _slistNode(_x);
if (NULL == _p || NULL == _n) return 0;
_n->_next = _p->_head;
_p->_head = _n;
_p->_size++;
return 1;
}
int ds_slistPopfront(struct _ds_slist* _p) {
struct _slist_node* _n = NULL;
if (NULL == _p) return 0;
if (NULL != _p->_head) {
_n = _p->_head;
_p->_head = _p->_head->_next;
DS_free(_n);
_p->_size--;
}
return 1;
}
int ds_slistFront(struct _ds_slist* _p) {
struct _slist_node* _n = NULL;
if (NULL == _p) return DS_ERR_VAL;
_n = _p->_head;
return (NULL != _n ? _n->_x : DS_ERR_VAL);
}
int ds_slistBack(struct _ds_slist* _p) {
struct _slist_node* _n = NULL;
if (NULL == _p) return DS_ERR_VAL;
_n = _p->_tail;
return (NULL != _n ? _n->_x : DS_ERR_VAL);
}
用过STL的同学都知道, 在链表的操作过程中, 还有一个迭代器可以用来遍历链表的各个元素。今天我就先把这个问题留给各位, 下次我们再来讲解这个简单迭代器的实现。