雙向鍊錶也叫雙鏈表,是鍊錶的一種,它的每個資料結點中都有兩個指標,分別 指向直接後繼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描述:將元素插入到由list指定的雙鏈表中element元素之後,當鍊表為空的時候,element為null,新的元素包含乙個指向data的指標,如果插入成功返回1,否則返回-1void *data);
複雜度:o(1)
4、dlist_ins_prev
int dlist_ins_prev(dlist *list, dlistelmt *element, const描述:將元素插入到由list指定的雙鏈表中element元素的前面,當鍊表為空的時候,element為null,新的元素包含乙個指向data的指標,如果插入成功返回0,否則返回-1void *data);
複雜度: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...