您的位置:首页 > 理论基础 > 数据结构算法

通用双向链表(二)———接口实现

2014-04-08 18:21 676 查看
/*****************************************dlist.c*********************************************/
#include <stdlib.h>
#include "dlist.h"

#define RETURN_LAST_IF_FAIL 1

typedef struct _DListNode
{
struct _DListNode* prev;
struct _DListNode* next;

void* data;
}DListNode;

struct _DList
{
DListNode* first;
void* data_destroy_ctx;
DListDataDestroyFunc data_destroy;
};

static void dlist_destroy_data(DList* thiz, void* data)
{
if(thiz->data_destroy != NULL)
{
thiz->data_destroy(thiz->data_destroy_ctx, data);
}

return;
}

static DListNode* dlist_create_node(DList* thiz, void* data)
{
DListNode* node = malloc(sizeof(DListNode));

if(node != NULL)
{
node->prev = NULL;
node->next = NULL;
node->data = data;
}

return node;
}

static void dlist_destroy_node(DList* thiz, DListNode* node)
{
if(node != NULL)
{
node->next = NULL;
node->prev = NULL;
dlist_destroy_data(thiz, node->data);
free(node);
}

return;
}

DList* dlist_create(DListDataDestroyFunc data_destroy, void* data_destroy_ctx)
{
DList* thiz = malloc(sizeof(DList));

if(thiz != NULL)
{
thiz->first = NULL;
thiz->data_destroy = data_destroy;
thiz->data_destroy_ctx = data_destroy_ctx;
}

return thiz;
}

static DListNode* dlist_get_node(DList* thiz, size_t index, int fail_return_last)
{
DListNode* iter = NULL;

return_val_if_fail(thiz != NULL, NULL);

iter = thiz->first;

while(iter != NULL && iter->next != NULL && index > 0)
{
iter = iter->next;
index--;
}

if(!fail_return_last)
{
iter = index > 0 ? NULL : iter;
}

return iter;
}

DListRet dlist_insert(DList* thiz, size_t index, void* data)
{
DListNode* node = NULL;
DListNode* cursor = NULL;

return_val_if_fail(thiz != NULL, DLIST_RET_INVALID_PARAMS);

if((node = dlist_create_node(thiz, data)) == NULL)
{
return DLIST_RET_OOM;
}

if(thiz->first == NULL)
{
thiz->first = node;

return DLIST_RET_OK;
}

cursor = dlist_get_node(thiz, index, RETURN_LAST_IF_FAIL);

if(index < dlist_length(thiz))
{
if(thiz->first == cursor)
{
thiz->first = node;
}
else
{
cursor->prev->next = node;
node->prev = cursor->prev;
}
node->next = cursor;
cursor->prev = node;
}
else
{
cursor->next = node;
node->prev = cursor;
}

return DLIST_RET_OK;
}

DListRet dlist_prepend(DList* thiz, void* data)
{
return dlist_insert(thiz, 0, data);
}

DListRet dlist_append(DList* thiz, void* data)
{
return dlist_insert(thiz, -1, data);
}

DListRet dlist_delete(DList* thiz, size_t index)
{
DListNode* cursor = dlist_get_node(thiz, index, 0);

return_val_if_fail(cursor != NULL, DLIST_RET_INVALID_PARAMS);

if(cursor != NULL)
{
if(cursor == thiz->first)
{
thiz->first = cursor->next;
}

if(cursor->next != NULL)
{
cursor->next->prev = cursor->prev;
}

if(cursor->prev != NULL)
{
cursor->prev->next = cursor->next;
}

dlist_destroy_node(thiz, cursor);
}

return DLIST_RET_OK;
}

DListRet dlist_get_by_index(DList* thiz, size_t index, void** data)
{
DListNode* cursor = dlist_get_node(thiz, index, 0);

return_val_if_fail(cursor != NULL, DLIST_RET_INVALID_PARAMS);

if(cursor != NULL)
{
*data = cursor->data;
}

return cursor != NULL ? DLIST_RET_OK : DLIST_RET_FAIL;
}

DListRet dlist_set_by_index(DList* thiz, size_t index, void* data)
{
DListNode* cursor = dlist_get_node(thiz, index, 0);

return_val_if_fail(cursor != NULL, DLIST_RET_INVALID_PARAMS);

if(cursor != NULL)
{
cursor->data = data;
}

return cursor != NULL ? DLIST_RET_OK : DLIST_RET_FAIL;
}

size_t   dlist_length(DList* thiz)
{
size_t length = 0;
DListNode* iter = NULL;

return_val_if_fail(thiz != NULL, 0);

iter = thiz->first;

while(iter != NULL)
{
length++;
iter = iter->next;
}

return length;
}

DListRet dlist_foreach(DList* thiz, DListDataVisitFunc visit, void* ctx)
{
DListRet ret = DLIST_RET_OK;
DListNode* iter = NULL;

return_val_if_fail(thiz != NULL && visit != NULL, DLIST_RET_INVALID_PARAMS);

iter = thiz->first;

while(iter != NULL && ret != DLIST_RET_STOP)
{
ret = visit(ctx, iter->data);

iter = iter->next;
}

return ret;
}

int dlist_find(DList* thiz, DListDataCompareFunc cmp, void* ctx)
{
int i = 0;
DListNode* iter = NULL;

return_val_if_fail(thiz != NULL && cmp != NULL, -1);

iter = thiz->first;
while(iter != NULL)
{
if(cmp(ctx, iter->data) == 0)
{
break;
}
i++;
iter = iter->next;
}

return i;
}

void dlist_destroy(DList* thiz)
{
DListNode* iter = NULL;
DListNode* next = NULL;

return_if_fail(thiz != NULL);

iter = thiz->first;
while(iter != NULL)
{
next = iter->next;
dlist_destroy_node(thiz, iter);
iter = next;
}

thiz->first = NULL;
free(thiz);

return;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息