迴圈鍊錶是另一種形式的鏈式儲存結構,其特點是單鏈表的最後乙個結點的指標不為空,而是指向頭結點(帶頭結點的鍊錶)或第乙個結點(不帶頭結點的鍊錶),整個鍊錶形成乙個環。這樣從鍊錶任何乙個位置出發,均可以找到表中的其他結點。迴圈鍊錶根據指標域是乙個還是多個,可以分為單迴圈鍊錶和多重迴圈鍊錶。
對於單迴圈鍊錶而言,判斷鍊錶是否為空不再是panda頭結點的指標是否為空,而是判斷頭結點的指標是否指向自身,如上圖所示。迴圈鍊錶基本操作的演算法和單鏈表沒什麼區別,只是迴圈結束條件(表尾)不再是判斷指標p
或p->next
是否為空,而是判斷他們是否等於頭結點。
有些時候,迴圈鍊錶中設乙個指向表尾的尾指針對某些應用更加方便。這樣,尾指標訪問頭結點和尾結點都非常方便,相當於既指向了頭結點,又指向了尾結點。如把由尾指標指引的單迴圈鍊錶表示的線性表a和b進行合併(即將a和b合併成乙個鍊錶),實現起來非常方便。只需要修改兩個指標即可,其運算時間為o(1)。**如下:
q = b->next; // q指向b的頭結點
b->next = a->next; // b的指標指向a的頭結點
a->next = q->next; // a的為節點指標指向b的第乙個結點,b鏈結到a上
a = b; // a指向b,作為合併後鍊錶的尾指標
free(q); // 釋放b的頭結點
在單鏈表中,對於任何乙個結點通過其指向後繼的指標,就可以直接訪問其後繼結點,其時間複雜度為o(1)。顯然,在單鏈表中訪問其前驅結點,必須要從表頭結點順鏈查詢,其時間複雜度為o(n)。顯然,在單鏈表中訪問某個元素的前驅十分不便。如果在鍊錶的結點結構中同時包含分別指向其前驅和後繼結點的兩個指標域,就很容易解決單鏈表中訪問前驅困難的問題,這種鍊錶稱作雙向鍊錶。
如圖(a)所示,雙向鍊錶的結點結構除了資料域之外,還包含兩個指標域(用於指向前驅結點的前驅指標域和用於指向後繼結點的後繼指標域)。其結點結構定義如下:
typedef
struct dnodedlistnode,*dlinklist;
如圖(b) (c)所示,對於帶有頭結點的雙向鍊錶,其頭結點prior
域為空,尾結點的next
域為空;顯然對於乙個空的雙向鍊錶,兩個指標域均為空。
雙向鍊錶也可以是迴圈鍊錶,雙向迴圈鍊錶的頭結點的前去指標prior指向表尾結點,尾結點的後繼指標next
指向頭結點;對於乙個空表,頭結點的兩個指標均指向頭結點自身。
在雙向鍊錶中,諸如計算表的長度定位元素和獲取元素等操作,僅涉及乙個方向的指標,這些操作與單鏈表的操作相同。由於需要修改兩個方向上的指標,在雙向鍊錶中進行插入和刪除等操作與單鏈表有較大的差異。
1.在雙向鍊錶中插入元素
基本過如下:
找到第i個結點(插入位置),將指標p指向該結點,包含資料元素e的結點將鏈結到此結點的前驅和後繼節點之間。注意,如果是在第i+1個位置上插入元素,則p指向頭結點。
產生乙個新結點s,並將資料元素e存放到該結點的資料域中
對指標進行操作,具體如**所示
status insertlist(dlinklist h, int i, elemtype e)
if(j>i || (p==h&&jreturn err_illegalpos;
s = (dlistnode*)malloc(sizeof(dlistnode));
if(!s)
return err_memory;
s->data = e;
s->prior = p->prior; // 將新結點s的前驅指標指向p的前驅結點
p->prior->next = s; // 將p的前驅的後繼指標指向s
s->next = p; // 將s的後繼指標指向p
p->prior = s; // 將p的前驅指標指向s
return ok;
}
注意,**中對於指標的更新涉及到四步,前兩步必須先更新插入結點s的前驅指標與p先驅結點的後繼指標。因為如果先進行下兩步的操作,將p的前驅指標指向s,則此時無法通過p的前驅指標得到p的前驅元素,從而無法將s鏈結到鍊錶中。2. 在雙向鍊錶中刪除元素
與單鏈表相同,對於雙向鍊錶,刪除線性表知道位置的資料元素,只需把指定位置的結點從雙向鍊錶中刪除,並釋放該結點空間即可。
演算法基本過程如下:
status deletelist(dlinklist h, int i, elemtype *e)
if(p==h || j>i)
return err_illegalpos;
*e = p->data;
p->prior->next = p->next; // 將p的前驅結點的後繼指標指向p的後繼結點
p->next->prior = p->prior; // 將p的後繼結點的前去指標指向p的前驅
free(p);
return ok;
}
注意,對指標的更新涉及到的兩步順序可以不同
資料結構 雙向鍊錶,迴圈鍊錶
也許是自己太小看資料結構,練習了幾天還在第二章徘徊,可自己覺得基礎還是要打牢的好 總結一下 第乙個是雙向鍊錶,include include typedef struct node node,linklist void creat linklist l else int insert linklis...
資料結構之雙向迴圈鍊錶
寫文目的 為了更深入的了解鍊錶,於是在這裡寫出單向鍊錶的公升級版雙向迴圈鍊錶!鍊錶介紹 1.建立鍊錶 首先需要定義乙個結構,一般雙向迴圈鍊錶的結構用於存放儲存在該節點的值,乙個prev指標指向前乙個節點,乙個rnext指標指向下乙個節點,對用結構 如下 typedef struct node nod...
資料結構 雙向迴圈鍊錶
近期我在學習資料結構,於是我自己整理了單鏈表 迴圈單鏈表 雙向鍊錶 雙向迴圈鍊錶的相關 以鞏固這段時間的學習,也希望能夠幫助初學者,希望大家在閱讀以下 時發現問題糾正於我,一起 cycdoublelist.h ifndef cycdoublelish h define cycdoublelish h...