雙向鍊錶和環形鍊錶(單向和雙向)約瑟夫環例項

2021-10-21 03:38:19 字數 3320 閱讀 4353

陣列優缺點:根據下標直接查詢和修改,增刪需要移動後續資料,效率低。

單向鍊錶的缺點:增刪快速,查詢需要從頭遍歷,效率低。

雙線鍊錶可以向前或向後查詢。

單向鍊錶查詢的方向只能是乙個方向(雙向鍊錶可以向前向後查詢),且不能自我刪除,需要靠輔助節點,而雙向鍊錶,則可以自我刪除,所以前面我們單鏈表刪除節點時,總是找到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;

**實現:

// 定義雙向鍊錶

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() ';

}}

應用場景:約瑟夫問題---在羅馬人占領喬塔帕特後,39 個猶太人與josephus及他的朋友躲到乙個洞中,39個猶太人決定寧願死也不要被敵人抓到,於是決定了乙個自殺方式,41個人排成乙個圓圈,由第1個人開始報數,每報數到第3人該人就必須自殺,然後再由下乙個重新報數,直到所有人都自殺身亡為止。然而josephus 和他的朋友並不想遵從。首先從乙個人開始,越過k-2個人(因為第乙個人已經被越過),並殺掉第k個人。接著,再越過k-1個人,並殺掉第k個人。這個過程沿著圓圈一直進行,直到最終只剩下乙個人留下,這個人就可以繼續活著。問題是,給定了和,一開始要站在什麼地方才能避免被處決。josephus要他的朋友先假裝遵從,他將朋友與自己安排在第16個與第31個位置,於是逃過了這場死亡遊戲。

簡單理解:設編號為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.雙向鍊錶 可以從任何乙個節點訪問前乙個節點,也可以訪問後乙個節點,以至整個鍊錶。一般是在需要大批量的另外儲存資料在鍊錶中...