在寫這個**的實現之前我們先來了解下相關的知識。
首先,帶頭結點帶環的雙向鍊錶的特點:
帶頭節點:建立乙個結點表示空鍊錶,這個節點就是頭結點,並且頭結點中的資料不具有實際的意義。但是我們一般不關心頭結點中的元素,只起「帶頭」作用。雙向要求每個結點中都有乙個next指標指向下乙個,乙個prev指標指向下乙個。
雙向的帶頭結點的帶環的鍊錶有三個成員,乙個是資料,乙個是指標next指向的是當前節點的下乙個結點,還有乙個是指標prev指向的是當前節點的前乙個節點,即每個結點都有乙個直接的前驅,乙個直接的後繼。
typedef
char dlinktype;
typedef
struct dlinknode dlinknode;
雙向鍊錶的初始化就是用乙個傀儡結點代表其為空,這裡將頭結點的資料初始化為0,注意,雙向鍊錶當中沒有沒有空指標,所以將雙向鍊錶的頭結點的next指向的是它自己,將雙向鍊錶的prev指向的也是自己,即判斷乙個雙向帶頭結點的鍊錶是否為空的條件就是head->next==head;head->prev==head.
dlinknode* creatnode(dlinktype value)
newnode->
data
= value;
newnode->prev =
null;
newnode->next =
null;
}void dlinklistinit(dlinknode** head)
*head = creatnode(0);
(*head)->prev =
*head;
(*head)->next =
*head;
}
既然我們要對鍊錶進行插入資料,那便需要對其建立乙個指定資料的節點,然後我們再將其插入鍊錶當中。建立節點就是先對其進行分配空間,再將節點對應資料改為我們需要的目標資料。
dlinknode* creatnode(dlinktype value)
newnode->
data
= value;
newnode->prev =
null;
newnode->next =
null;
}
也是採用的是先建立乙個新的結點,然後定義乙個prev指標指向頭結點的下乙個結點,然後我們去修改prev和新建立的新節點的指向。
dlinknode* dlinklistpushback(dlinknode* head, dlinktype value)
dlinknode* newnode = creatnode(value);
dlinknode* tail = head->prev;
//head和newnode
head->prev = newnode;
newnode->next = head;
//tail和newnode
tail->next = newnode;
newnode->prev = tail;
}
void dlinklistpopback(dlinknode* head)
56if(head->next==head ||head->prev==head)
60 dlinknode* to_delete=head->prev;
61 dlinknode* cur=to_delete->prev;
62 cur->next=head;
63 head->prev=cur;
64 dlinklistdestroy(to_delete);
65 }
66
void dlinklistpushfront(dlinknode* head, dlinktype value)
69 73 dlinknode* newnode=creatnode(value);
7475 dlinknode* cur=head->next;
76//head和newnode
77 head->next=newnode;
78 newnode->prev=head;
79//new和cur
80 newnode->next=cur;
81 cur->prev=newnode;
82 }
83
83
84void dlinklistpopfront(dlinknode* head)
85 89if(head->next== head || head->prev==head)
93 dlinknode* to_delete=head->next;
94 dlinknode*tmp=to_delete->next;
95 head->next=tmp;
96 tmp->prev=head;
97 dlinklistdestroy(to_delete);
98 }
dlinknode* dlinklistfind(dlinknode* head, dlinktype to_find)
dlinknode* cur = head->next;
for (; cur != head; cur = cur->next)
}return
null;
}
//往指定位置之前插入乙個元素
void dlinklistinsert(dlinknode* head, dlinknode* pos, dlinktype value)
dlinknode* cur = pos->prev;
dlinknode* newnode = creatnode(value);
//pos->prev和newnode
cur->next = newnode;
newnode->prev = cur;
//newnode和pos
newnode->next = pos;
pos->prev = newnode;
}
//往指定位置之後插入乙個元素
void dlinklistinsertafter(dlinknode* head, dlinknode* pos, dlinktype value)
dlinknode* cur = pos->next;
dlinknode* newnode = creatnode(value);
//pos->next和newnode
cur->prev = newnode;
newnode->next = cur;
//newnode和pos
pos->next = newnode;
newnode->prev = pos;
}
void dlinklisterase(dlinknode* head, dlinknode* to_delete)
dlinknode* pro = to_delete->prev;
dlinknode* pre = to_delete->next;
pro->next = pre;
pre->prev = pro;
dlinklistdestroy(to_delete);
}
void dlinklistremove(dlinknode* head, dlinktype to_delete)
//刪除指定值元素
if (head->next == head)
dlinknode* ret = dlinklistfind(head, to_delete);
dlinklisterase(head, ret);//這裡只是刪除,而不是進行銷毀結點
}
void dlinklistremoveall(dlinknode* head, dlinktype to_delete)
if (head->next == head)
while (1)
dlinklisterase(head,ret );}}
size_t dlinklistsize(dlinknode* head)
dlinknode* cur = head->next;
int i = 0;
while (cur!= head)
return i;
}
int dlinklistempty(dlinknode* head)
if (head->next!= head)
return
0;}
實現帶頭結點的雙向迴圈鍊錶
dlist.h 帶頭節點的雙向迴圈鍊錶 為什麼要帶頭 原因是因為如果不帶頭的話,那麼頭插或者頭刪會比較麻煩 而且不帶頭的話需要傳遞二級指標,帶頭的話,只需要傳遞一級指標 為什麼給成雙向的?有乙個理由是可以逆向列印鍊錶 也就是對有些操作會簡單一些 pragma once 保證標頭檔案不會被重複包含 i...
雙向帶環帶頭節點的鍊錶
建立乙個雙向鍊錶的節點 class listnode 關於頭插 如何將鍊錶列印出來 public void display system.out.println system.out.println 反向 system.out.print for listnode cur head.prev cur...
單向不帶頭結點不帶環的鍊錶實現
鍊錶有很多種類,單向,雙向,不帶頭,帶頭,不帶環,帶環,結合起來一共可以有八種鍊錶形式 今天我們來實現一種名字叫 單向不帶頭不帶環的鍊錶 下面就是每一部分的 實現 首先我們要做的就是函式的宣告,結構體的定義,標頭檔案的引用 pragma once define header printf n s n...