我們之前說過了單鏈表,大家應該都有印象吧,那麼迴圈鍊錶是什麼呢?
迴圈鍊錶就是將單鏈表中終端結點的指標端自空指標改為指向頭結點,就使整個單鏈表形成乙個環,這種頭尾相接的單鏈表稱為單迴圈鍊錶,簡稱迴圈鍊錶 (circular linked list) 。
那麼迴圈鍊錶出現的目的是為什麼呢?
迴圈鍊錶解決如何從當中乙個結點出發,訪問到鍊錶的全部結點。
為了使空鍊錶與非空煉表處理一致,我們通常設乙個頭結點,當然,這並不是說,迴圈鍊錶一定要頭結點,這需要注意。 結構圖如下:
其實迴圈鍊錶與單鏈表主要差異主要體現在迴圈的判斷條件上,單鏈表判斷最後乙個節點的指標域是否為空,而迴圈鍊錶判斷最後乙個節點的指標域是否為頭節點。
操作**可以參考我之前做的單鏈表的**,只是在新增尾節點的時候將尾節點的指標域為空,改為指向頭指標。
終於到了最後乙個鍊錶結構了,雙向鍊錶,那麼雙向鍊錶又是什麼呢?
雙向鍊錶 (double linked list) 是在單鏈表的每個結點中,再設定乙個指向其前驅結點的指標域。所以在雙向鍊錶中的結點都有兩個指標域, 乙個指向直接後繼,另乙個指向直接前驅。
那麼為什麼我們要設定這種鍊錶結構呢?
主要是為了解決單鏈表,查詢下一節點的時間複雜度為o(1),但是查詢上一節點的時間複雜度為o(n)的問題,也就是為了解決單鏈表的單一性查詢的問題。
雙向鍊錶可以是迴圈鍊錶,也可以不是迴圈鍊錶,但是我們一般還是用迴圈雙向鍊錶偏多,畢竟使用起來比較方便。結構圖如下:
雙向鍊錶是單鏈表中擴充套件出來的結構,所以它的很多操作是和單鏈表相同的,比如求長度的 listlength ,查詢元素的 getelem,獲得元素位置的 locateelem 等,這些操作都只要涉及乙個方向的指標即可,另一指標多了也不能提供什麼幫助。
雙向鍊錶既然是比單鏈表多了如可以反向遍歷查詢等資料結構,那麼也就需要付出一些小的代價:在插入和刪除時,需要更改兩個指標變化。
插入操作時其實並不複雜,不過順序很重要,如圖所示:
千萬不要寫反了,如果先執行4,再執行其他的,找不到後繼的位置,那麼插入就會失敗,
刪除節點稍微簡單點,如圖所示:
操作**如下:
public class doublelinklist
} /**
* 新增頭節點
*/public void addheadpoint()
/*** 新增尾節點
*/public void addtail(t data)
/*** 使用頭部插入法新增節點
*/public void insertnode(t data)
if (this.tail == null)
nodenewnode = new node(data);// 建立乙個新的節點
newnode.prev = this.headpoint;// 新節點的前驅域指向頭節點
newnode.next = this.headpoint.next;// 新節點的後繼域指向下乙個節點
headpoint.next.prev = newnode;// 新節點的後繼節點的前驅域指向新節點
headpoint.next = newnode;// 頭節點的後繼域指向新節點
} /**
* 在指定位置新增節點
* * @param index
* @param node
* @throws exception
*/public void insertnodebyindex(int index, nodenode) throws exception
int length = 1;// 定義我們遍歷的長度
nodetemp = headpoint.next;// 從頭節點下乙個節點開始遍歷
while (temp != null)
temp = temp.next;
}} /**
* 根據節點位置刪除節點
* * @param index
* @throws exception
*/public void deletenodebyindex(int index) throws exception
if (index < 0 || index >= length())
int length = 1;// 開始遍歷的位置
nodetemp = headpoint.next;// 迴圈節點
while (temp != null)
temp = temp.next;
}} /**
* 判斷鍊錶是否為空
* * @return
*/public boolean isempty()
/*** 獲取鍊錶的長度
* * @return
*/public int length()
return length;
} /**
* 獲取節點的值
* * @param i
* @return
*/public t getvalue(int i)
return node.data;
} /**
* 測試
* * @param ages
* @throws exception
*/public static void main(string ages) throws exception
system.out.println("原鍊錶資料:");
for (int k = 0; k < list.length(); k++)
list.insertnodebyindex(7, new node(123));
list.deletenodebyindex(5);
system.out.println();
system.out.println("最新鍊錶資料:");
for (int k = 0; k < list.length(); k++)
}}
線性表終於結束了,我們先談了它的定義,線性表是零個或多個具有相同型別的資料元素的有限序列。然後談了線性表的抽象資料型別,如它的一些基本操作。
之後我們就線性表的兩大結構做了講述,先講的是比較容易的順序儲存結構,指的是用一段位址連續的儲存單元依次儲存線性表的資料元素。通常我們都是用陣列來實現這一結構。
後來是我們的重點,由順序儲存結構的插入和刪除操作不方便,引出了鏈式儲存結構。它具有不受固定的儲存空間限制,可以比較快捷的插入和刪除操作的特點。然後我們分別就鏈式儲存結構的不同形式,如單鏈表、迴圈鍊錶和雙向鍊錶做了講解。
總體示意圖如下:
資料結構之線性表 六 迴圈鍊錶
迴圈鍊錶的定義 1.概念與特點 迴圈鍊錶 是一種頭尾相接的鍊錶。表中的最後乙個結點的指標域指向頭結點,整個鍊錶形成環狀結構。優點 從表中任意乙個結點出發均可找到表中其他結點。補充 由於迴圈鍊錶中沒有null指標,所以涉及到遍歷操作時,其終止條件不再像單鏈表那樣判斷p或者p next是否為空,而是判斷...
資料結構(六)線性表(一)
線性表 線性表的定義 零個或多個資料元素的有限序列 若線性表記為 a1,ai 1,ai,an 則表中ai 1領先於ai,ai領先於ai 1,稱ai 1是ai的直接前驅元素,ai 1是ai的直接後繼元素。當i 1,2,3,n 1時,ai有且僅有乙個直接後繼,當i 2,3,n,ai有且僅有乙個直接前驅。...
資料結構線性表 迴圈鍊錶
普通單鏈表 1 表尾的next指標指向null。2 從乙個結點出發只能找到後續的結點。迴圈單鏈表 1 表尾的next指標指向頭指標l。2 從乙個結點出發可以找到其他任何乙個結點。include include typedef struct lnodelnode,linklist 迴圈單鏈表初始化 b...