1、双链表定义
typedef struct DListElement_t_{
void *data;
struct DListElement_t *prev;
struct DListElement_t *next;
} DListElement_t
typedef struct DList_t_{
int size;
int (*match)( const void *key1, const void *key2);
int (*destroy)(void *data);
DListElement_t *head;
DListElement_t *tail;
} DList_t;
typedef struct DListElement_t_{
void *data;
struct DListElement_t *prev;
struct DListElement_t *next;
} DListElement_t
typedef struct DList_t_{
int size;
int (*match)( const void *key1, const void *key2);
int (*destroy)(void *data);
DListElement_t *head;
DListElement_t *tail;
} DList_t;
2、初始化
int dlist_init( DList_t *dlist, int (*match)( const void *key1, const void *key2), int (*destroy)(void *data ))
{
dlist->size = 0;
dlist->match = match;
dlist->destory = destory;
dlist->head = NULL;
dlist->tail = NULL;
return 0;
}
int dlist_init( DList_t *dlist, int (*match)( const void *key1, const void *key2), int (*destroy)(void *data ))
{
dlist->size = 0;
dlist->match = match;
dlist->destory = destory;
dlist->head = NULL;
dlist->tail = NULL;
return 0;
}
3、插入---在给定节点后面插入:
给定元素element,在其后插入数据data;
异常情况考虑:
(1)超过链表容量:
if( dlist_is_full( dlist))
return OVERFLOW;
(2)节点空间申请不成功
if( new_element = (DListElement_t *)malloc( DListElement))) == NULL )
return ALLOCA_ERROR;
需要考虑的情况为:
(1)如果element为NULL,则在头结点插入:
链表为空时:
if( dlist_is_empty( dlist) )
dlist->head = dlist->tail = new_element;
链表不为空:
new_element->prev = dlist->head->prev;
new_element->next = dlist->head;
dlist->head->prev = new_element;
dlist->head = new_element;
(2)如果element不为NULL,则在element之后插入:
首先是将待插入节点的前后指针分别指向对应位置:
new_element->prev = element;
new_element->next = element->next;
下面就是考虑element的后指针和它下一个节点的前指针
需要考虑element是否为尾节点:
if( dlist_is_tail(element)
dlist->tail = new_element;
else
element->next->prev = new_element;
element->next = new_element;
int dlist_insert_next( DList_t *dlist, DListElement_t *element, const void *data){
DListElement_t *new_element = NULL;
if( (new_element = ( DListElement_t *)malloc( sizeof( DListElement_t ))) == NULL )
return ALLOCA_ERROR;
new_element->data = data;
new_element->prev = NULL;
new_element->next = NULL;
if( element == NULL ){
if ( dlist_is_empty(dlist)){
dlist->head = new_element;
dlist->tail = new_element;
} else {
new_element->next = dlist->head;
dlist->head->prev = new_element;
dlist->head = new_element;
}
}else{
new_element->prev = element;
new_element->next = element->next;
if( dlist_is_tail ( element ) )
dlist->tail = new_element;
else
element->next->prev = new_element;
element->next = new_element;
}
dlist->size++;
return 0;
}
int dlist_insert_next( DList_t *dlist, DListElement_t *element, const void *data){
DListElement_t *new_element = NULL;
if( (new_element = ( DListElement_t *)malloc( sizeof( DListElement_t ))) == NULL )
return ALLOCA_ERROR;
new_element->data = data;
new_element->prev = NULL;
new_element->next = NULL;
if( element == NULL ){
if ( dlist_is_empty(dlist)){
dlist->head = new_element;
dlist->tail = new_element;
} else {
new_element->next = dlist->head;
dlist->head->prev = new_element;
dlist->head = new_element;
}
}else{
new_element->prev = element;
new_element->next = element->next;
if( dlist_is_tail ( element ) )
dlist->tail = new_element;
else
element->next->prev = new_element;
element->next = new_element;
}
dlist->size++;
return 0;
}
4、插入----在给定节点之前插入
异常情况考虑:
(1)是否溢出,超出链表容量
if( dlist_is_full( dlist))
return OVERFLOW;
(2)节点空间申请是否成功
if(( new_element = (DListElement_t *)malloc( sizeof( DListElement_t ) )) == NULL )
return -1;
需要考虑的情况包括:
(1)如果element为NULL,或者element为头节点,则在头结点之前插入,需要维护头指针:
如果此时链表为空,则需要同时维护头指针和尾指针:
if( dlist_size (dlist) == 0 )
{
dlist->head = new_element;
dlist->tail = new_element;
}else{
new_element->next = dlist->head;
dlist->head->prev = new_element;
dlist->head = new_element;
}
(2)如果element不为NULL, 则在element之前插入
new_element->next = element;
new_element->prev = element->prev;
element->prev->next = new_element;
element->next = new_element;
int dlist_insert_prev( DList_t *dlist, DListElement_t *element, const void *data){
DListElement_t *new_element = NULL;
if( ( new_element = ( DListElement_t *)malloc( sizeof( DListElement_t ))) == NULL )
return ALLOCA_ERROR;
new_element->data = data;
new_element->prev = NULL;
new_element->next = NULL;
if( (element == NULL) || (dlist_is_head(element)){
if( dlist_is_empty( dlist)){
dlist->head = new_element;
dlist->tail = new_element;
} else {
new_element->next = dlist->head;
dlist->head->prev = new_element;
dlist->head = new_element;
}
} else {
new_element->next = element;
new_element->prev = element->prev;
element->prev->next = new_element;
element->next = new_element;
}
dlist->size++;
return 0;
}
int dlist_insert_prev( DList_t *dlist, DListElement_t *element, const void *data){
DListElement_t *new_element = NULL;
if( ( new_element = ( DListElement_t *)malloc( sizeof( DListElement_t ))) == NULL )
return ALLOCA_ERROR;
new_element->data = data;
new_element->prev = NULL;
new_element->next = NULL;
if( (element == NULL) || (dlist_is_head(element)){
if( dlist_is_empty( dlist)){
dlist->head = new_element;
dlist->tail = new_element;
} else {
new_element->next = dlist->head;
dlist->head->prev = new_element;
dlist->head = new_element;
}
} else {
new_element->next = element;
new_element->prev = element->prev;
element->prev->next = new_element;
element->next = new_element;
}
dlist->size++;
return 0;
}
5、删除
删除指定元素element
异常情况:
链表为空,无法删除
if(dlist_is_empty( dlist) )
return -1;
常规情况:
(1)若是element为NULL或者element为头结点,则删除头结点
需要考虑链表长度为1时,需要维护头尾指针;否则需要维护第二个节点的前指针
if( (element == NULL ) || ( dlist_is_head(element)){
*data = dlist->head->data;
del_element = dlist->head;
if( dlist_size(dlist) == 1 ){
dlist->head = NULL;
dlist->tail = NULL;
} else {
dlist->head = dlist->head->next;
dlist->head->prev = NULL;
}
}
(2)如果element为其他节点
需要考虑删除尾节点时,维护尾指针
*data = element->data;
del_element = element;
if ( dlist_is_tail( element)){
dlist->tail = element->prev;
dlist->tail->next = NULL;
} else {
element->prev->next = element->next;
element->next->prev = element->prev;
}
int dlist_remove( DList_t *dlist, DListElement_t *element, void **data){
if( dlist_is_empty( dlist) )
return -1;
DListElement_t *del_element = NULL;
if( (element == NULL) || (dlist_is_head( element )){
*data = dlist->head->data;
del_element = dlist->head;
if( dlist_size(dlist) == 1 )
{
dlist->head = NULL;
dlist->tail = NULL;
} else {
dlist->head = dlist->head->next;
dlist->head->prev = NULL;
}
} else {
*data = element->data;
del_element = element;
if ( dlist_is_tail ( del_element) )
{
dlist->tail = element->prev;
dlist->tail->next = NULL;
} else {
element->prev->next = element->next;
element->next->prev = element->prev;
}
}
<p> free( del_element);</p><p> del_element = NULL;</p><p> dlist->size--;
</p><p> return 0;
</p><p>}</p><p>
</p>
dlist->size--;
return 0;
}
int dlist_remove( DList_t *dlist, DListElement_t *element, void **data){
if( dlist_is_empty( dlist) )
return -1;
DListElement_t *del_element = NULL;
if( (element == NULL) || (dlist_is_head( element )){
*data = dlist->head->data;
del_element = dlist->head;
if( dlist_size(dlist) == 1 )
{
dlist->head = NULL;
dlist->tail = NULL;
} else {
dlist->head = dlist->head->next;
dlist->head->prev = NULL;
}
} else {
*data = element->data;
del_element = element;
if ( dlist_is_tail ( del_element) )
{
dlist->tail = element->prev;
dlist->tail->next = NULL;
} else {
element->prev->next = element->next;
element->next->prev = element->prev;
}
}
dlist->size--;
return 0;
}
6、销毁列表
int dlist_destroy( DList_t *dlist)
{
void *data;
while( dlist_size( dlist) > 0 ){
if ( dlist_remove( dlist, NULL, (void **)&data) == 0 && dlist->destory != NULL )
dlist->destory( data );
}
return 0;
}
int dlist_destroy( DList_t *dlist)
{
void *data;
while( dlist_size( dlist) > 0 ){
if ( dlist_remove( dlist, NULL, (void **)&data) == 0 && dlist->destory != NULL )
dlist->destory( data );
}
return 0;
}
其他相关题目下面以超链接形式给出:
1、单链表基本操作
2、双链表基本操作
4、反转单链表
6、倒序打印链表
7、查找链表中间节点
9、判断链表是否有环
10、判断两个单链表是否相交
14、合并两个有序单链表
15、给定链表中间某节点,不遍历链表,将带插入节点插入给定节点之前
16、删除链表重复元素