陣列優缺點:根據下標直接查詢和修改,增刪需要移動後續資料,效率低。
單向鍊錶的缺點:增刪快速,查詢需要從頭遍歷,效率低。
雙線鍊錶可以向前或向後查詢。
單向鍊錶查詢的方向只能是乙個方向(雙向鍊錶可以向前向後查詢),且不能自我刪除,需要靠輔助節點,而雙向鍊錶,則可以自我刪除,所以前面我們單鏈表刪除節點時,總是找到temp的下乙個節點來刪除的(就是指temp.next.data == data,因為要對該節點的前乙個節點及後乙個節點操作。)
雙向鍊錶節點包含資料域data、前驅指標域prev、後繼指標域next。
分析雙向鍊錶可以實現的功能:
(1)遍歷:和單鏈表一樣,只是可以向前向後查詢。
(2)新增:舉例新增node到鍊錶的最後,rear.next = node;node.prev = rear;rear = node;
(3)修改:和單鏈表一樣
(4)刪除:舉例刪除node,node.prev.next = node.next;node.next.prev = node.prev;
**實現:
應用場景:約瑟夫問題---在羅馬人占領喬塔帕特後,39 個猶太人與josephus及他的朋友躲到乙個洞中,39個猶太人決定寧願死也不要被敵人抓到,於是決定了乙個自殺方式,41個人排成乙個圓圈,由第1個人開始報數,每報數到第3人該人就必須自殺,然後再由下乙個重新報數,直到所有人都自殺身亡為止。然而josephus 和他的朋友並不想遵從。首先從乙個人開始,越過k-2個人(因為第乙個人已經被越過),並殺掉第k個人。接著,再越過k-1個人,並殺掉第k個人。這個過程沿著圓圈一直進行,直到最終只剩下乙個人留下,這個人就可以繼續活著。問題是,給定了和,一開始要站在什麼地方才能避免被處決。josephus要他的朋友先假裝遵從,他將朋友與自己安排在第16個與第31個位置,於是逃過了這場死亡遊戲。// 定義雙向鍊錶
class doublielinkedlist
// 遍歷雙向鍊錶
public void show()
}// 尾插法新增節點到單向鍊錶
public void addrear(linkednode node)
rear.next = node;
node.prev = rear;
}// 修改節點資訊,根據編號修改。
/*說明根據node的id來修改
*/public void update(linkednode node)
if(temp.id == node.id)
temp = temp.next;
}if(flag)else system.out.println("沒有找到該編號英雄!");
}// 刪除節點
public void deletenode(linkednode node)
if (temp.id == node.id)
temp = temp.next;
}if(flag)else
}}// 定義linkednode節點,定義linkednode節點
class linkednode
// 顯示方便,重寫tostring方法
@override
public string tostring() ';
}}
簡單理解:設編號為1,2,...,n的n個人圍坐一圈,約定編號為k(1<=k<=n)的人從1開始報數,數到m的那個人出列,它的下一位又從1開始報數,直到所有人出列為止,由此產生乙個出隊編號的序列。
建立單向環形鍊錶思路:
1.先建立第乙個節點,讓first指向該節點,並形成環形。
2.後面當我們每建立乙個新的節點,就把該節點加入到已有的環形鍊錶中即可。
遍歷環形鍊錶:
輔助指標指向first。
根據使用者的輸入,生成乙個小孩出圈的順序:public class singlecircularlinkedlist else}}// 遍歷當前環形鍊錶
public void show()
}}class node2
// 顯示方便,重寫tostring方法
@override
public string tostring() ';
}}
1.需要建立乙個輔助指標prev,初始化遍歷指向環形列表的最後這個節點。(即每次出圈節點的前乙個節點)
2.根據從第幾個數開始,讓out和prev指標一起移動到指定開始節點位置。
3.報數時,讓prev和out指標同時移動m-1(自己也要報,所以-1)次。
3.這時就可以讓out指向的節點出圈,讓prev連上後乙個點。繼續轉,直到prev == out只剩乙個節點,就停止。
注意當乙個節點沒有任何引用時就會被**。
public class singlecircularlinkedlist else}}// 根據使用者的輸入,計算出出圈順序
public void outline(int startid,int countnum,int nums)
// 報數前準備,讓prev指標和out指標一起移動,prev少移動一次
// 類似於快慢指標
node2 out = first;
node2 prev = first;
while(prev.next != first)
// 然後一起移動到起點位置
for (int i = 1; i < startid; i++)
system.out.println("prev:" + prev.id);
system.out.println("out:" + out.id);
// 迴圈操作,直到只剩乙個節點
while(true)
// 當報數開始,兩個指標一起移動countnum - 1次
for (int i = 1; i < countnum; i++)
system.out.println("出圈的是:" + out.id); // 格式化
// out指標出圈,去引用
prev.next = out.next;
out = out.next;
}system.out.println("最後留下的是:" + out.id);
}// 遍歷當前環形鍊錶
public void show()
}}class node2
}
public class josepfu}
鍊錶(單向鍊錶,雙向鍊錶)
首先鍊錶是以節點的方式儲存資料的,每個節點包含資料域 data 節點域 next 鍊錶的每個節點在計算機中儲存的位置是不連續的和隨機的,優點就是資料的插入和刪除比較好,而查詢資料效率不是太好 因為鍊錶無法像靜態資料一樣隨機讀取資料,必須按照順序找到對應的資料為止 單向鍊錶就像是火車,所有的節點串聯成...
單向鍊錶和雙向鍊錶區別 雙向鍊錶
一開始確實被這個雙向鍊錶整暈了,node裡面不停套node,簡直無限套娃,讓人不知道該怎麼下手。後來看了資料結構與演算法分析這本書的 才算整明白。我把鍊錶分成了三個部分 第一部分是node.node是乙個由兩根指標,以及我們需要儲存的資料構成的結構體。這個node就是無限套娃的起源,也是鍊錶用於儲存...
單向鍊錶和雙向鍊錶
1.單向鍊錶 單向鍊錶只可向乙個方向遍歷。查詢乙個節點的時候需要從第乙個節點開始每次訪問下乙個節點,一直訪問到需要的位置。也可以提前把乙個節點的位置另外儲存起來,然後直接訪問。2.雙向鍊錶 可以從任何乙個節點訪問前乙個節點,也可以訪問後乙個節點,以至整個鍊錶。一般是在需要大批量的另外儲存資料在鍊錶中...