数据结构之链表

来源:互联网 发布:电商网站php 编辑:程序博客网 时间:2024/06/06 03:39

我们在数据结构中链表包括三种:单链表、双向链表、循环链表。在日常开发中链表的应用包括:邮件列表、滚动列表、内存管理、多项式计算、文件链式分配,其他的想队列、栈、集合、哈希表和图中也都依赖了链表。

单链表:链表中最简单的链表,元素由一个单独的指针连接,允许我们从第一个元素遍历到最后一个元素。

链表结构体:(头部)->key1->key2->key3->(尾部)->null,这样看来我们的链表元素都是连续存在的,但是由于链表的存储空间是动态获取的,所以个元素在内存是散列存在的,各个元素又是通过指针连接到一起的。链表的抽象数据类型如下:

typedef struct ListElmt_

{

void* data;

struct ListElmt_  next;

}ListElmt;

typedef struct List{

int size;

int (match*)(const void *key1,const void *key2);

void(destroy)(void *data);

ListElmt *head;

ListElmt *tail;

}List;

#define list_size(list)((list)->size)

#define list_head(list)((list)->head)

#define list_tail(list)((list)->tail)

#define list_is_head(list,element)((element) == list->head?1:0)

#define list_is_tail(list,element)((element) == list->tail?1:0)

#define list_data(element)((element) ->data)

#define list_next(element)((element)->next)

链表的公共接口函数:

void list_init(List *list,void *destroy(void *data))

{

list->size = 0;

list->destroy = destroy;

list->head = NULL;

list->tail = NULL;

return;

}

void list_destroy(List *list)

{

void *data;

while(list->size > 0)

{

if(list_rem_next(list,NULL,(void **)data) == 0 && list->destroy != NULL)

{

list->destroy(data);

}

}

memset(list,0,sizeof(list);

return;

}

/*在链表上进行插入操作有两种情况:一种是element不存在直接再链表头插入,一种是在element的next插入*/

int list_ins_next(List *list,ListElmt *element,const void* data)

{

ListElmt * new_element;

if((new_element = (ListElmt*)malloc(sizeof(ListElmt))) == NULL)

return -1;


new_element->data = (void *)data;

if(element == NULL)

{

if(list->size == 0)

list->tail = new_element;

new_element->next = list->head;

list->head = new_element;

]

else

{

if(element->next == NULL)

list->tail = new_element;

new_element->next = element->next;

element->next = new_element;

}

list->size ++;

return 0;

}

/*链表的删除操作分为两种情况:一种是element节点不存在则移除头节点,另一种是删除element节点的下一个元素*/

int list_rem_next(List *list,ListElmt* element,void **data)

{

ListElmt* old_element;


if(list_size(list) == 0)

return  -1;

if(element == NULL)

{

*data = list->head->data;

old_element = list->head;

list->head = list->head->next;


if(list_size(list) == 1)

list->tail = NULL;

}else{

if(elment->next == NULL)

return -1;

*data = element->next->data;

old_element = element->next;

element->next = element->next->next;


if(element->next == NULL)

list->tail = element;

}

free(old_element);

list->size--;

return 0;

}

双向循环链表:链表中的元素通过两个指针连接,链表可以正向遍历,也可以反向遍历。

结构体定义:

typedef struct DListElmt_

{

void * data;

struct DListElmt_ *prev;

struct DListElmt_ *next;

}DListelElmt;

typedef struct DList_

{

int size;

int (*match)(const void *key1,const void *key2);

int (*destroy)(void * data);

DListElmt *head;

DListElmt *tail;

}DList;

#define dlist_size(list)((list)->size)

#define dlist_head(list)((list)->head)

#define dlist_tail(list)((list)->tail)

#define dlist_is_head(element)((element)->prev == NULL?1:0)

#define dlist_is_tail(element)((element)->next == NULL?1:0)

#define dlist_data(element)(element->data)

#define dlist_prev(element)(element->prev)

#define dlist_next(element)(element->next)


void dlist_init(DList *list,void(*destroy)(void *data))

{

list->size = 0;

list->destroy = destroy;

list->head = NULL;

list->tail = NULL;

return;

}


void dlist_destroy(DList *list)

{

void *data;

while(list->size > 0)

{

if(dlist_remove(list,dlist_tail(list),(void**)&data) == 0 && list->destroy != NULL)

list->destroy(list);

}

memset(list,0,sizeof(DList));

return;

]

/**/

int dlist_ins_next(DList *list,DListElmt *element,const void*data)

{

DListElmt * new_element;

if(element == NULL && dlist_size(list) != 0)

return -1;

new_element = (DListElmt*)malloc(sizeof(DListElmt));

new_element->data = (void*)data;

if(dlist_size(list) == 0)

{

list->head = new_element;

list->prev = NULL;

list->next = NULL;

list->tail = new_element;

}

else{

new_element->next = element->next;

new_element->prev = element;


if(element->next == NULL)

list->tail = new_element;

else

element->next->prev = new_element;


element->next = new_element;

}

list->size++;

return 0;

}


int dlist_ins_prve(DList *list,DListElmt *element,const void*data))

{

DListElmt * new_element;

if(element == NULL && dlist_size(list) != 0)

return -1;

new_element = (DListElmt*)malloc(sizeof(DListElmt));

new_element->data = (void*)data;

if(dlist_size(list) == 0)

{

list->head = new_element;

list->prev = NULL;

list->next = NULL;

list->tail = new_element;

}

else{

new_element->next = element->next;

new_element->prev = element;

if(element->prve == NULL)

list->head = new_element;

else

element->prve->next = new_element;

element->prve = new_element;

}

list->size++;

return 0;

}

int dlist_remove(DList *list,DListElmt*element,void **data)

{

if((element == NULL) || (list->size == 0))

return -1;


*data = element->data;

if(element == list->head)

{

list->head = element->next;

if(list->head == NULL)

list->tail = NULL;

else

element->next->prve = NULL;

}else{

element->prve->next = element->next;

if(elsement->next == NULL)

list->tail = element->prve;

else

element->next->prve = element->prve;

}

free(element);

list->size--;

return 0;

}

循环链表:这种链表为元素的指针是指向头元素的,而不是设置为NULL,这种元素是可以循环遍历的。循环链表可以使单链表也可以是双向链表,判断一个链表是否为循环链表,只需要判断链表是否有为元素即可。

循环链表结构体:

typedef struct CListElmt_

{

void *data;

struct CListElmt_ * next

}CListElmt;

typedef struct CList_

{

int size;

int (*match)(const void *key1,const void*key2);

void (*destroy)(void *data);

ClistElmt *head;

}CList;

#define clist_size(list)((list)->size)

#define clist_head(list)((list)->head)

#define clist_data(element) ((element)->data)

#define clist_next(element)((element)->next)


void clist_init(CList *list,void (*destroy)(void * data))

{

list->size = 0;

list->destroy = destroy;

list->head = NULL;


return;

}


void clist_destroy(CList *list)

{

void *data;


while(clist_size(list) > 0)

{

if(clist_rem_next(list,list->head,(void **)&data) == 0 && list->destroy != NULL)

{

list_destroy(data);

}

}

memset(list,0,sizeof(list));

return;

}


int clist_ins_next(CList *list,CListElmt *element,const void *data)

{

CListElmt *new_element;


if((new_element = (CListElmt*)malloc(sizeof(CListElmt))) == NULL)

return -1;

new_element->data = data;

if(clist_size(list) == 0)

{

new_element->next = new_element;

list->head = new_element;

}else{

new_element->next=element->next;

element->next = new_element;

}

list_size++;

return 0;

}


int clist_rem_next(CList *list,CListElmt *element,const void *data)

{

CListElmt *old_element;


if(list_size(list) == 0)

return -1;

*data = element->data;

if(element->next == element)

{

old_element = element->next;

list->head = NULL;

}else{

old_element = element->next;

element->next = element->next->next;

if(old_element ==clist_head(list))

list->head = old_element->next;

}

free(old_element);

list->size--;

return 0;

}

0 0