C實現通用資料結構 雙向鍊錶

2021-09-23 21:50:02 字數 4368 閱讀 6884

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

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

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_  dlistelmt;

typedef struct dlist_ 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))
**雙向鍊錶:

void dlist_destroy(dlist *list) }//

現在沒有操作了,釋放結構體作為預防措施

memset(list, 0, sizeof(dlist));

return;

}

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

//插入指定元素的後繼

int dlist_ins_next(dlist *list, dlistelmt *element, const

void *data) else

//調整鍊錶長度

list->size++;

return

0;}

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

//

插入指定元素的前驅

int dlist_ins_prev(dlist *list, dlistelmt *element, const

void *data) else

//調整鍊錶長度

list->size++;

return

0;}

刪除指定結點:

//

刪除指定結點

int dlist_remove(dlist *list, dlistelmt *element, void **data) else

//釋放已經分配的結點

free(element);

//調整表長

list->size--;

return

0;}

資料結構 鍊錶 雙向通用鍊錶

目錄參考 節點 非通用鍊錶自理解概念 節點攜帶資訊 襪子 掛在到鉤子的東西 通用鍊錶自理解概念 資訊攜帶節點 襪子 擺到晾衣架圓形框的一截上,使得節點成為襪子的乙個成員指標變數 通用鍊錶與非通用鍊錶的區別 通用鍊錶節點被放到資訊結構體中,通過偏移找到所在的結構體 即是通過偏移找到襪子頭 而非通用鍊錶...

資料結構雙向鍊錶 C

博主 牆角黑貓 1 原理解釋 雙向鍊錶的理解是在每個節點之間存在雙向的連線,例如和單鏈表對比 單鏈表是 a b c d 每個節點是單向連線的,a只能指向b,從b無法直接到a。而雙向鍊錶是 a b c d 這樣就實現了a和b的完全互通。大家可以結合下圖理解一下!2 部分 include include...

C 資料結構 雙向鍊錶

鍊錶的概念以及鍊錶與陣列的差異不做過多的敘述,相信大家都耳熟能詳,這裡以c 語言實現簡單的雙向鍊錶,作為備用,記錄下 否則逆序查詢 var prenode head.prev for int i 0 i count 1 index i prenode prenode.prev return pren...