DList双向链表


//
//  DList.h
//  Algorithms&Data_structures
//
//  Created by TTc on 15-2-2.
//  Copyright (c) 2015年 TTc. All rights reserved.
//

#ifndef __Algorithms_Data_structures__DList__
#define __Algorithms_Data_structures__DList__

#include <stdlib.h>

/* define  a  structure for doubly_linked list */
typedef struct DlistElmt_{
    void *data;
    struct DlistElmt_ *prev;
    struct DlistElmt_ *next;
}DlistElmt;

typedef struct Dlist_{
    int size;
    int(*match)(void *key1,void *key2);
    void(*destroy)(void *data);
    DlistElmt *head;
    DlistElmt *tail;
}Dlist;


/* public Interfaces*/

void dlist_init(Dlist *dlist,void(*destroy)(void *data));

void dlist_destroy(Dlist *dlist);

int dlist_ins_next(Dlist *dlist,DlistElmt *element,const void *data);

int dlist_ins_prev(Dlist *dlist,DlistElmt *element,const void *data);

int dlist_remove(Dlist *dlist,DlistElmt *element, void **data);


#define dlist_size(dlist)  ((dlist)->size)
#define dlist_head(dlist)  ((dlist) ->head)
#define dlist_tail(dlist)  ((dlist) ->tail)

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


#define dlist_data(dlist)  ((dlist) ->data)
#define dlist_next(dlist)  ((dlist) ->next)
#define dlist_prev(dlist)  ((dlist) ->prev)

#endif /* defined(__Algorithms_Data_structures__DList__) */
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
//
//  DList.c
//  Algorithms&Data_structures
//
//  Created by TTc on 15-2-2.
//  Copyright (c) 2015年 TTc. All rights reserved.
//

#include "dlist.h"
#include <stdlib.h>
#include <string.h>


void
dlist_init(Dlist *dlist,void(*destroy)(void *data)){
    dlist->size = 0;
    dlist->head = NULL;
    dlist->tail = NULL;
    dlist->destroy = destroy;
}

void
dlist_destroy(Dlist *dlist){
    void *data;
    /*remove each  element*/
    while (dlist_size(dlist) > 0) {
        if((dlist_remove(dlist, dlist_tail(dlist), (void**) &data) == 0)
                && dlist->destroy != NULL){
            dlist->destroy(data);
        }
    }
    //清空dlist 结构体
    memset(dlist, 0, sizeof(Dlist));
}

/*1:  将新元素插入到双链表中 由参数element所指向的元素 之后
  2: 同单链表最大的区别在于:除了要管理next
 指针外,还必须管理prev指针,以保证链表的 反向链接关系 正确
 */
/* 插入成功返回0 ,反之返回 -1 */
/* O(1)*/
int
dlist_ins_next(Dlist *dlist,DlistElmt *element,const void *data){
    DlistElmt *new_element;
    //do not allow a NULL unless the list is empty
    if(element == NULL && dlist_size(dlist) != 0){
        return -1;
    }
    if((new_element = (DlistElmt*)malloc(sizeof(DlistElmt))) == NULL){
        return -1;
    }
    //fill the data to the element
    new_element->data = (void*)data;
    //如果当前链表为 空表,再插入新元素 的情况
    if(dlist_size(dlist) == 0){
        new_element->prev = NULL; //链表的头元素 的 前驱指针 指向NULL
        new_element->next = NULL; //链表的头元素 的 后驱指针 指向NULL(当前情况 链表中只要这一个元素)
        dlist->head = new_element;
        dlist->tail = new_element;//链表的尾指针也指向 当前元素
    } else {
        //如果当前链表为 非空表,再插入新元素 的情况

        if(element->next == NULL){
            dlist->tail = new_element;
        } else{
            //否则 将当前目标元素的 后一位置的元素 的 前驱指针 指向 要插入的元素
            element->next->prev = new_element;
        }

        new_element->next = element->next; //要插入的元素的 next指针 指向 当前目标元素 后一位置 元素
        new_element->prev = element;//要插入元素的 前驱函数 指向 当前目标元素
        //如果 当前目标元素的 是当前链表的 尾元素,则 将 链表的尾元素 置为 新插入的元素(把链表的尾指针 tail 指向 要插入的元素)
        //当前目标元素 的后驱指针 指向 要初入的元素
        element->next = new_element;
    }
    dlist->size ++;
    return 0;
}

/*1:  将新元素插入到双链表中 由参数element所指向的元素 之前
  2: 同单链表最大的区别在于:除了要管理next
     指针外,还必须管理prev指针,以保证链表的 反向链接关系 正确
 3: 若element = NULL, 则双向链表应该为空,否则退出并返-1;
 若element != NULL,则需要在element->prev位置插入元素,插入的新元素的数据域为第三个参数data.另外还需要考虑当element为head结点时的情况。
 */
/* 插入成功返回0 ,反之返回 -1 */
/* O(1)*/
int
dlist_ins_prev(Dlist *dlist,DlistElmt *element,const void *data){
    DlistElmt *new_element;
      //Do not allow a NULL unless the list is empty
    if(element == NULL && dlist_size(dlist) != 0){
        return -1;
    }
    if((new_element = (DlistElmt*)malloc(sizeof(DlistElmt))) == NULL){
        return -1;
    }
    new_element->data = (void*)data;
    //如果当前链表为 空表,再插入新元素 的情况
    if(dlist_size(dlist) == 0){
        dlist->head = new_element;
        dlist->tail = new_element;//链表的尾指针也指向 当前元素
        new_element->prev = NULL; //链表的头元素 的 前驱指针 指向NULL
        new_element->next = NULL;//链表的头元素 的 后驱指针 指向NULL(当前情况 链表中只要这一个元素)
    } else {
        new_element->next = element;
        new_element->prev = element->prev;
        if(element->prev == NULL){
            dlist->head = new_element;
        }
        else{
            element->prev->next = new_element;
        }
        element->prev = new_element;
    }

    dlist->size++;

    return 0;
}

/* 1: remove操作将指定得元素从 双链表中删除;同单链表最大的区别在于:除了要管理next
       指针外,还必须管理prev指针,以保证链表的 反向链接关系 正确
   2: 对于双链表还有一个不同于 单链表 的地方在于 :该接口 移除当前指定的元素,而不是移除指定元素之后的那个元素,因为每个元素都有一个指向其前驱的指针

  3: element代表 目标节点, 删除操作针对 element节点
 */
/* 删除成功返回0 ,反之返回 -1 */
/* O(1)*/
int dlist_remove(Dlist *dlist,DlistElmt *element, void **data){
    /*  Don't allow a NULL element or  removal from an empty  dlist */
    if(element == NULL || dlist_size(dlist) == 0){
        return -1;
    }
    *data = element->data;
    /*  handle  removal from the head of the dlist */
    // 若为 删除节点为 链表的 头节点
    if(element == dlist->head){
        //将链表头节点的 指针 指向 目标元素的 next指针(目标元素的下一个位置 元素)
        dlist->head = element->next;
        //若链表的head指针 指向NULL 则 tail 也必须指向NULL,删除元素后,可能为空表
        if(dlist->head == NULL){
            dlist->tail = NULL;
        } else{
            //若 head 指针 不为NULL ,则将必须将 目标元素的 前驱指针的 prev指向NULL(其实这个时候 element->next 就是 链表的 第一个元素 ,这个时候 第一元素的 前驱指针必须置为 NULL)
            element->next->prev = NULL;
        }
    } else {
        /*  handle  removal from other than the head of the dlist */
        //将 当前要删除的元素的 前一个位置的元素 的 next指针 指向 当前元素的 next指针(也就是当前位置元素 的后一个位置的 元素)
        element->prev->next = element->next;
        //
        if(element->next == NULL){
            dlist->tail = element->prev;
        }else{
            //将 当前位置要删除元素的 后一个位置的元素 的前驱指针prev 指向 当前元素的前驱指针(也就是当前元素的 前一个位置的元素)
            element->next->prev = element->prev;
        }
    }
    free(element);
    dlist->size --;
    return 0;
}





  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
//
//  test_dlist_main.c
//  
//
//  Created by TTc on 16/5/25.
//
//
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#include "dlist.h"

typedef struct Cuboid_
{
    int length;
    int width;
    int height;
}Cuboid;

Cuboid *cube_instance(const int length, const int width, const int height)
{
    Cuboid *cb_ptr;
    cb_ptr = (Cuboid *)malloc(sizeof(Cuboid));
    if( cb_ptr == NULL )
        return NULL;

    cb_ptr->length = length;
    cb_ptr->width = width;
    cb_ptr->height = height;

    return cb_ptr;
}

/*destroy */
void destroy(void *data)
{
    free(data);
    return;
}


/* main */
int main(int argc, char **argv)
{
    int i;
    Dlist dlist_exp;
    DlistElmt *p = NULL;
    Cuboid *cb1_ptr, *cb2_ptr, *cb3_ptr, *cb4_ptr, *cb5_ptr;
    Cuboid *cb_ptr;

    //cb1_ptr ~ cb5_ptr are the data of the 5 elements.
    cb1_ptr = cube_instance(1,2,3);
    cb2_ptr = cube_instance(6,10,8);
    cb3_ptr = cube_instance(5,20,30);
    cb4_ptr = cube_instance(17,100,25);
    cb5_ptr = cube_instance(3,6,9);

    //init the double linked list.
    dlist_init(&dlist_exp, destroy);

    //insert the 5 elements into the dlist
    dlist_ins_next(&dlist_exp, NULL, (void *)cb1_ptr );  //insert data:cb1
    p = dlist_head(&dlist_exp); //get the address of the first element
    dlist_ins_next(&dlist_exp, p , (void *)cb2_ptr );   //insert data:cb2    cb1- cb2
    p = dlist_next(p);          //pointer to the element containing the data cb2.
    dlist_ins_prev(&dlist_exp, p, (void *)cb3_ptr );    //insert data:cb3   cb1- cb3- cb2
    dlist_ins_prev(&dlist_exp, p, (void *)cb4_ptr );    //insert data:cb4   cb1- cb3- cb4- cb2
    p = dlist_prev(p);          //pointer to the element conatining the data cb4.
    dlist_ins_prev(&dlist_exp, p, (void *)cb5_ptr );      //insert data:cb5   cb1- cb3- cb5- cb4- cb2

    //now the sequence is: head->cb1->cb3->cb5->cb4->cb2
    printf("traverse and print:\n");
    p = dlist_head(&dlist_exp); //get the head element;
    for( i = 0; i < dlist_size(&dlist_exp); i++ )
    {
        cb_ptr = (Cuboid *)dlist_data(p); //get the element's data, every data is a Cuboid's pointer.
        printf("i = %d: ",i);
        printf("length = %d, width = %d, height = %d\n",
               cb_ptr->length,
               cb_ptr->width,
               cb_ptr->height);
        p = dlist_next(p); //pointer to next element;
    }

    //we'll remove the third element:that's containing the data of cb5(3,6,9)
    p = dlist_head(&dlist_exp);
    p = dlist_next(p);
    p = dlist_next(p);
    dlist_remove(&dlist_exp, p, (void **)&cb_ptr);
    printf("the data of the third element: length = %d, width = %d, height = %d\n",
           cb_ptr->length,
           cb_ptr->width,
           cb_ptr->height);
    destroy(cb_ptr); //free the memory

    //now we'll show you the remained elements,the sequence is :(head)cb1->cb3->cb4->cb2(tail)
    printf("after remove the third elements:\n");
    p = dlist_head(&dlist_exp);
    for(i = 0; i < dlist_size(&dlist_exp); i++ )
    {
        cb_ptr = (Cuboid *)dlist_data(p);
        printf("i = %d: ",i);
        printf("length = %d, width = %d, height = %d\n",
               cb_ptr->length,
               cb_ptr->width,
               cb_ptr->height);
        p = dlist_next(p);
    }

    //destroy the double linked list
    dlist_destroy(&dlist_exp);
    printf("after destroy the list,its size = %d\n", dlist_size(&dlist_exp));
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值