数据结构之链表
来源:互联网 发布:电商网站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;
}
- 数据结构之链表
- 数据结构之链表
- 数据结构之链表
- 数据结构之链表
- 数据结构之链表
- 数据结构之链表
- 数据结构之链表
- 数据结构之链表
- 数据结构之链表
- 数据结构之链表
- 数据结构之链表
- 数据结构之链表
- 数据结构之链表
- 数据结构之链表
- 数据结构之链表
- 数据结构之链表
- 数据结构之链表
- 数据结构之链表
- 电影节
- 小鑫的城堡
- Android监听耳机按键事件
- BZOJ 1087 (状态压缩DP)
- php 入门基础 三
- 数据结构之链表
- linux 下sort 命令排序
- Avro技术应用_5. 利用 Camus 来将 Avro 数据从 Kafka 拷贝到 HDFS -- 待完善
- Contiki高级程序设计
- 单元测试protected和private函数时的错误记录
- Ubuntu加载本地磁盘报错:Unable to access ""
- 关于struts2上传时报临时文件找不到的问题
- 关于Java中各种修饰符与访问修饰符的说明(转载)
- Avro技术应用_6. Avro Format & Text Format 之间的转换 --待完善