您的位置:首页 > 编程语言 > C语言/C++

「算法精解_C语言描述」 链表_双向链表的实现与分析

2017-11-07 20:50 671 查看

双向链表的实现与分析

*关于双向链表的接口定义,请参阅前篇文章:双向链表的接口定义



双向链表的组成 :1、数据成员;2、指向下一个元素的next指针;3、指向前一个元素的prev指针。

数据结构DListElmt:代表双向链表中的单个元素(节点)。

数据结构DList:代表双向链表数据结构,该结构的成员同前面介绍的单链表相似。

示例1:双向链表抽象数据类型的头文件

/*dlist.h*/
#ifndef  DLIST_H
#define  DLIST_H

/*定义双向链表中的元素*/
typedef struct DListLemt_
{
void *data;
struct DListElmt_ *prev;
struct DlistElmt_ *next;
}DListElmt;

/*定义双向链表*/
typedef struct DList_
{
int size;
int (*match)(const void *key1,const void *key2);
void (*destroy)(void *data);
DListElmt *head;
DlistElmt *tail;
}DList;

/*公共接口*/
void dlist_init(DList *list,void (*destroy)(void *data)) ;
void dlist_destroy(DList *list);
int dlist_ins_next(DList *list,DListElmt *element,const void *data);
int dlist_ins_prev(Dlist *list,DListElmt *element,const void *data);
int dlist_remove(DList *list,DlistElmt *element,void **data);

#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_next(element)((element)->next)
#define dlist_prev(element)((element)->prev)

#endif


示例2: 双向链表抽象数据类型的实现

/*dlist.c*/
#include <stdio.h>
#include <string.h>

#include "dlist.h"

/*dlist_init    初始化双向链表*/
void dlist_init(DList *list,void(*destroy)(void *data))
{
list->size = 0;
list->destroy = destroy;
list->head = NULL;
list->tail = NULL;

return ;
}

/*dlist_destroy  销毁双向链表*/
void dlist_destroy(DList *list)
{
void *data;

/*移除每一个元素*/
while(dlist_size(list)>0)
{
if(dlist_remove(list,dlist_tail(list),(void **)&data)==0
&& list->destroy != NULL)
{
/*调用一个用户自定义函数释放动态分配的数据*/
list->destroy(data);
}
}

/*不再允许其他操作,清除链表结构*/
memset(list,0,sizeof(DList));
return;
}

/*dlist_ins_next  将元素插入指定元素之后*/
int dlist_ins_next(DList *list,DListElmt *element,const void *data)
{
DListElmt *new_element;

/*除非链表为空,否则不允许使用null元素。*/
if(element == NULL && dlist_size(list) != 0)
return -1;
/*为元素分配空间*/
if((new_element=(DListElmt*)malloc(sizeof(DListElmt)))==NULL)
return -1;

/*将新元素插入链表*/
new_element->data = (void*)data;

if(dlist_size(list)==0)
{
/*链表为空时*/
list->head = new_element;
list->head->prev = NULL;
list->head->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;
}
/*dlist_ins_prev*/
int dlist_ins_prev(DList *list,DListElmt *element,const void *data)
{
DListElmt *new_element;

/*除非链表为空,否则不允许element为null*/
if(element == NULL && dlist_size(list)!=0)
return -1;

/*为新元素分配存储*/
if((new_element=(DlistElmt *)malloc(sizeof(DListElmt))==NULL)
return -1;

/*insert the new element into the list*/
new_element->data=(void *data);
if(dlist_size(list)==0)
{
/*链表为空*/
list->head = new_element;
list->head->prev = NULL;
list->tail->tail = NULL;
list->tail = new_element;
}
else
{
/*链表非空*/
new_element_next = element;
new_element_prev = element_prev;

if(element->prev == NULL)
list->head = new_element;
else
element->prev->next = new_element;

element->prev = new_element;
}
/*改变链表中结点数量*/
list->size++;
return 0;
}

/*dlist_remove*/
int dlist_remove(Dlist *list,DList_Elmt *element,void **data)
{
/*不允许移除一个空元素或者从一个空链表中移除元素.*/
if(element == NULL || dlist_size(list)==0)
return -1;
/*移除元素*/
*data = element->data;

if(element == list->head)
{
/*从链表的头部移除操作*/
list->head = element->next;

if(list->head == NULL)
list->tail = NULL;
else
element->next->prev = NULL;
}
else
{
/*从链表其他位置移除元素操作*/
element->prev->next = element->next;

if(element->next == NULL)
list->tail = element->prev;
else
element->next->prev = element->prev;
}

/*释放空间*/
free(element);
/*改变链表中结点数量*/
list->size--;
return 0;
}


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