C實現通用資料結構--雙向鏈表

來源:互聯網
上載者:User

標籤:des   style   blog   http   color   ar   使用   strong   sp   

雙向鏈表概述

雙向鏈表也叫雙鏈表,是鏈表的一種,它的每個資料結點中都有兩個指標,分別指向直接後繼next和直接前驅prev。所以,從雙向鏈表中的任意一個結點開始,都可以很方便地訪問它的前驅結點和後繼結點。為了標識鏈表的頭和尾,將第一個元素的prev指標和最後一個元素的next指標設定為NULL

要反向遍曆整個雙向鏈表,使用prev指標從尾到頭的順序訪問各個元素,因此為每個元素增加了一個指標的代價,換來的是雙向鏈表更加靈活的訪問。

本文地址:http://www.cnblogs.com/archimedes/p/c-datastruct-dlinklist.html,轉載請註明源地址。

雙向鏈表介面的定義

1、dlist_init

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

描述:初始化由list指定的雙向鏈表,該操作應該在其他動作之前進行。當調用dlist_destory時,這裡傳入的參數提供了一種釋放動態分配空間的方法

複雜度:O(n)

2、dlist_destroy

void dlist_destroy(DList *list);

描述:銷毀由list指定的雙向鏈表,該操作之後其他動作不能進行。除非重新調用dlist_init

複雜度:O(n)

3、dlist_ins_next

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

描述:將元素插入到由list指定的雙鏈表中element元素之後,當鏈表為空白的時候,element為NULL,新的元素包含一個指向data的指標,如果插入成功返回1,否則返回-1

複雜度:O(1)

4、dlist_ins_prev

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

描述:將元素插入到由list指定的雙鏈表中element元素的前面,當鏈表為空白的時候,element為NULL,新的元素包含一個指向data的指標,如果插入成功返回0,否則返回-1

複雜度:O(1)

5、dlist_remove

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

描述:移除由list指定的雙鏈表中element元素,移除操作成功返回0,否則返回-1

複雜度:O(1)

6、dlist_size

int dlist_size(const DList *list);

描述:這是一個宏,用來計算雙鏈表中元素的個數

複雜度:O(1)

7、dlist_head

DListElmt *dlist_head(const DList *list);

描述:這是一個宏,用來返回由list指定的雙鏈表的頭結點

複雜度:O(1)

8、dlist_tail

DListElmt dlist_tail(const DList *list);

描述:這是一個宏,用來返回由list指定的雙鏈表的尾結點

複雜度:O(1)

9、dlist_is_head

int dlist_is_head(const DListElmt *element);

描述:這是一個宏,用來判斷由element元素指定的元素是否為頭結點,如果是返回1,否則返回0

複雜度:O(1)

10、dlist_is_tail

int dlist_is_tail(const DListElmt *element);

描述:這是一個宏,用來判斷由element元素指定的元素是否為尾結點,如果是返回0,否則返回-1

複雜度:O(1)

11、dlist_data

void *dlist_data(const DListElmt *element);

描述:這是一個宏,用來返回由element元素指定的元素的資料域

複雜度:O(1)

12、dlist_next

DListElemt *dlist_next(const DListElmt *element);

描述:這是一個宏,用來返回由element元素指定的元素的後繼結點,如果是返回0,否則返回-1

複雜度:O(1)

13、dlist_prev

DListElemt *dlist_prev(const DListElmt *element);

描述:這是一個宏,用來返回由element元素指定的元素的前驅結點,如果是返回0,否則返回-1

複雜度:O(1)

雙向鏈表的實現和分析

抽象資料類型的標頭檔(list.h):

typedef struct DListElmt_ {  //為雙鏈表結點建立結構    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

初始化雙向鏈表:

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

回收雙向鏈表:

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;}

插入新節點作為指定結點的直接後繼結點:

參考如下:

//插入指定元素的後繼int dlist_ins_next(DList *list, DListElmt *element, const void *data) {    DListElmt *new_element;    //不允許element元素為NULL,除非list為空白.                         if (element == NULL && dlist_size(list) != 0)       return -1;                                                                            //為element分配空間    if ((new_element = (DListElmt *)malloc(sizeof(DListElmt))) == NULL)       return -1;    //向鏈表中插入元素    new_element->data = (void *)data;    if (dlist_size(list) == 0) {           //當鏈表為NULL的時候,插入到頭結點                                       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;}

插入新節點作為指定結點的直接前驅結點:

//插入指定元素的前驅int dlist_ins_prev(DList *list, DListElmt *element, const void *data) {    DListElmt *new_element;     if (element == NULL && dlist_size(list) != 0)   //不允許element元素為NULL,除非list為空白.               return -1;     if ((new_element = (DListElmt *)malloc(sizeof(DListElmt))) == NULL)   //為element分配空間        return -1;    //向鏈表中插入元素    new_element->data = (void *)data;    if (dlist_size(list) == 0) {        //當鏈表為NULL的時候,插入到頭結點               list->head = new_element;        list->head->prev = NULL;         list->head->next = 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;}

刪除指定結點:

//刪除指定結點int dlist_remove(DList *list, DListElmt *element, void **data) {    //不允許刪除NULL元素或從空表中刪除元素    if (element == NULL || dlist_size(list) == 0)        return -1;    //從表中刪除元素    *data = element->data;    if (element == list->head) {       //刪除表頭結點         list->head = element->next;        if (list->head == NULL)  //如果element元素是尾結點            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;}

 

C實現通用資料結構--雙向鏈表

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.