雙鏈表就是在單鏈表結點上增添了一個指針域,指向當前結點的前驅。這樣就能夠方便的由其後繼來找到其前驅,而實現輸出終端結點到開始結點的數據序列。node
一樣,雙鏈表也分爲帶頭結點的雙鏈表和不帶頭結點的雙鏈表,狀況相似於單鏈表。帶頭結點的雙鏈表 head->next 爲null的時候鏈表爲空。不帶頭結點的雙鏈表head爲null的時候鏈表爲空。算法
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; }
在雙鏈表中查找第一個結點值爲x的結點。從第一個結點開始,邊掃描邊比較,若找到這樣的結點,則返回結點指針,不然返回NULL。算法代碼以下:spa
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而結束) //所以這一句能夠將題幹中要求的兩種返回值的種狀況統一。 }
假設在雙鏈表中p所指的結點以後插入一個結點s,其操做語句描述爲:指針
s->next = p->next; s->prior = p; p->next = s; s->next->prior = s;
指針變化過程如圖:code
若是按照上面的順序來插入,能夠當作是一個萬能的插入方式。先將要插入的結點兩邊連接好,能夠保證不會發生鏈斷以後找不到結點的狀況。ip
設要刪除雙鏈表中p結點的後繼結點,其操做的語句爲:io
q= p->next; p->next= q->next; q->next->prior= p; free(q);
指針變化過程如圖所示:class
只要將單鏈表的最後一個指針域(空指針)指向鏈表中第一個結點便可(這裏之因此說第一個結點而不說是頭結點是由於,若是循環單鏈表是帶頭結點的則最後一個結點的指針域要指向頭結點;若是循環單鏈表不帶頭結點,則最後一個指針域要指向開始結點)。cli
帶頭結點的循環單鏈表當head等於head->next時鏈表爲空;
不帶頭結點的循環單鏈表當head等於null時鏈表爲空。循環
循環雙鏈表的構造源自雙鏈表,即將終端結點的nnext指針指向鏈表中第一個結點,將鏈表中第一個結點的prior指針指向終端結點。
帶頭結點的循環雙鏈表當head->next和heaad->prior兩個指針都等於head時鏈表爲空。
不帶頭結點的循環雙鏈表當head等於null的時候爲空。
循環單鏈表和循環雙鏈表由對應的單鏈表和雙鏈表改造而來,只需在終端結點和頭結點間創建聯繫便可。
循環單鏈表終端結點的next結點指針指向表頭結點;循環雙鏈表終端結點的next指針指向表頭結點,頭結點的prior指針指向表尾結點。
若是p指針沿着循環鏈表行走,判斷p走到表尾結點的條件是p->next == head
。循環鏈表的各類操做均與非循環鏈表相似。