雙鏈表定義

雙鏈表就是在單鏈表結點上增添了一個指針域,指向當前結點的前驅。這樣就可以方便的由其后繼來找到其前驅,而實現輸出終端結點到開始結點的數據序列。
同樣,雙鏈表也分為帶頭結點的雙鏈表和不帶頭結點的雙鏈表,情況類似於單鏈表。帶頭結點的雙鏈表 head->next 為null的時候鏈表為空。不帶頭結點的雙鏈表head為null的時候鏈表為空。
1.采用尾插法建立雙鏈表
void CreateDlistR (DLNode *&L, int a[], int n){ DLNode*s,*r; inti; L = (DLNode*)malloc(sizeof(DLNode)); L->next = NULL; //和單鏈表一樣r始終指向終端結點,開始頭結點也是尾結點 r = L; for(i = 1; i< = n; i++){ //創建新結點s->data = a[i]; s = (DLNode*)malloc(sizeof(DLNode)); /*下邊3句將s插入在L的尾部並且r指向s,s->prior = r;這一句是和建立單鏈表不同的地方。 */ r->next = s; s->prior = r; r = s; } r->next = NULL; }
2.查找結點的算法
在雙鏈表中查找第一個結點值為x的結點。從第一個結點開始,邊掃描邊比較,若找到這樣的結點,則返回結點指針,否則返回NULL。算法代碼如下:
DLNode* Finfnode(DLNode *C, int x){
DLNode *p = C->next;
while(p != NULL){ if(p->data == x) { break; } p = p->next; } return p; //如果找到則p中內容是結點地址(循環因break結束), //沒找到 p中內容是NULL(循環因p等於NULL而結束) //因此這一句可以將題干中要求的兩種返回值的種情況統一。 }
3.插入結點的算法
假設在雙鏈表中p所指的結點之后插入一個結點s,其操作語句描述為:
s->next = p->next;
s->prior = p;
p->next = s;
s->next->prior = s;
指針變化過程如圖:

如果按照上面的順序來插入,可以看成是一個萬能的插入方式。先將要插入的結點兩邊鏈接好,可以保證不會發生鏈斷之后找不到結點的情況。
4.刪除結點的算法
設要刪除雙鏈表中p結點的后繼結點,其操作的語句為:
q= p->next;
p->next= q->next;
q->next->prior= p;
free(q);
指針變化過程如圖所示:

循環單鏈表

只要將單鏈表的最后一個指針域(空指針)指向鏈表中第一個結點即可(這里之所以說第一個結點而不說是頭結點是因為,如果循環單鏈表是帶頭結點的則最后一個結點的指針域要指向頭結點;如果循環單鏈表不帶頭結點,則最后一個指針域要指向開始結點)。
帶頭結點的循環單鏈表當head等於head->next時鏈表為空;
不帶頭結點的循環單鏈表當head等於null時鏈表為空。
循環雙鏈表

循環雙鏈表的構造源自雙鏈表,即將終端結點的nnext指針指向鏈表中第一個結點,將鏈表中第一個結點的prior指針指向終端結點。
帶頭結點的循環雙鏈表當head->next和heaad->prior兩個指針都等於head時鏈表為空。
不帶頭結點的循環雙鏈表當head等於null的時候為空。
循環鏈表的算法操作
循環單鏈表和循環雙鏈表由對應的單鏈表和雙鏈表改造而來,只需在終端結點和頭結點間建立聯系即可。
循環單鏈表終端結點的next結點指針指向表頭結點;循環雙鏈表終端結點的next指針指向表頭結點,頭結點的prior指針指向表尾結點。
如果p指針沿着循環鏈表行走,判斷p走到表尾結點的條件是p->next == head。循環鏈表的各種操作均與非循環鏈表類似。
