單鏈表與List究竟哪個遍歷速度快?

2021-08-25 12:12:36 字數 1886 閱讀 9630

單鏈表與list究竟哪個遍歷速度快?

firelong雄文又起,不過說實話,可能是這篇文章寫的太簡單了,其中的理由和結論都聽得不是很明白。當然有一段話的意思很清楚(原話):「c#事件的背後是乙個委託鍊錶(單鏈表),單鏈表的遍歷呼叫效能遠低於陣列鍊錶(list

)」。這句話讓我比較納悶,因為從我的直覺來說,兩種做法之間即使效能有差距,也不該是「遠高於」啊。不過我提出這個疑問之後,firelong回應到(還是原話)「間接指標移動,和i++哪個快慢很難辨析嗎?」於是我想,還是做個試驗吧。試驗**很簡單:

public class 

node

public class

item

class

program;}

return root;

}static

list

getlist(int length)

).tolist();

}static void main(string args)

}console.writeline(" (node list)", watch1.elapsed);

gc.collect();

var list = getlist(length);

var watch2 = stopwatch.startnew();

for (int t = 0; t < iteration; t++)

}console.writeline(" (list)", watch2.elapsed);

}}

使用release模式編譯,並且保證vs不會attach debugger之後,執行幾遍結果如下:

00:00:02.0731861 (node list)

00:00:02.4602990 (list)

00:00:02.3176291 (node list)

00:00:02.2912638 (list)

00:00:02.1539642 (node list)

00:00:02.4635390 (list)

我的直覺是這樣的:如果使用list來遍歷,除了i++操作以外,還需要計算偏移量,根據list內部的陣列來找到下乙個物件的位址,再根據這個位址去訪問下乙個物件,而單向鍊錶的遍歷做的事情會少一些,只要乙個接乙個的訪問就行了。從結果上看,總體說來差別不大,並沒有出現firelong所說的「單向鍊錶遍歷性能遠低於list」的情況出現。而且事實上,這點效能真的有關係嗎?這裡累計遍歷了10億個元素,才產生了零點幾秒的差距,而對於乙個事件來說,您會為它新增多少個handler,又會呼叫多少次呢?

這篇文章寫的比較匆忙,也沒有什麼太可取的內容,便先簡單試試看這趟水有多深吧。

補充說明三點:

有朋友提出,陣列裡的物件在記憶體裡的分布是連續的,單向鍊錶不連續,因此考慮到如果換頁,快取等關係,基於陣列的效率會比較高。我的看法是:如果您遍歷的是int,那麼每個int值的在記憶體裡自然是連續的,但是這裡訪問的是item這樣的引用元素的陣列,連續分布的只是物件的位址,而要獲得最終物件,還得再根據位址去訪問某個記憶體,它就不能保證連續性了。同樣道理,有朋友說,真實情況下node這樣的物件不是連續訪問的,我認為這個差別也不會偏袒向其中任何一方。也有朋友認為,不管怎麼說陣列裡的位址是連續的,區域性性還是更好。不過我認為,對於單向鍊錶來說,如訪問node的value時,next也會一併載入到快取裡去,同乙個物件的字段是緊挨著的也是.net出於區域性性的考慮。

還有朋友指出,陣列訪問它不會傻傻得i++再去訪問下標,它會優化。這沒錯,如果您用item來代替list就會發現效能的確有提高(但同樣相差不大)。但是,firelong同學說的是list,它不是陣列,而是基於陣列的容器。由於list是可變的,因此jit是否真會對其進行優化還是個未知數,我傾向於理解為「不是」。不過現在,我只是通過小實驗來看看究竟相差如何。

單鏈表與list究竟哪個遍歷速度快?

12 單鏈表的遍歷與優化

提供一組遍歷相關的函式,以線性的時間複雜度遍歷鍊錶 函式功能說明 move 將游標定位到目標位置 next 移動游標 current 獲取游標所指向的資料元素 end 游標是否到達尾部 bool move int i,int step 1 bool end t current bool next i...

十 單鏈表的遍歷與優化

遍歷單鏈表中的每個一資料元素 linklistlist for int i 0 i 5 i o n 這裡的遍歷方法效率很低 for int i 0 i list.length i o n 2 遍歷鍊錶的時間複雜度不是線性的,插入元素是線性,遍歷就不是了。不能以線性的時間複雜度完成單鏈表的遍歷 設計思...

java 單鏈表list 轉置(反轉) 普通與遞迴

單鏈表的轉置 反轉 普通方法 通過迴圈與臨時變數來轉置 優點是節省記憶體開銷 public void commonreverse 解析 當list a1 a2 a3 a4 時 運算方式 第一輪 curr a1 temp a1 curr a2 a1.next null reve a1 第二輪 curr...