日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Immutable Collections(3)Immutable List实现原理(中)变化中的不变

發(fā)布時間:2023/12/18 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Immutable Collections(3)Immutable List实现原理(中)变化中的不变 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Immutable ?Collections(3)Immutable List實現(xiàn)原理()變化中的不變

/玄魂

前言

在上一篇文章(Immutable Collections2ImmutableList<T>實現(xiàn)原理.(上),分析了)ImmutableList<T>的初始化過程,本篇博客分析除初始化之外的行為,當然概括起來也很簡單——添加、刪除、修改。這些行為的背后,我們會看到不可變集合的不變性是如何保持的,如何在不完全拷貝的情況下返回新的集合等等特性的秘密。

博文中引用的代碼并非是.NET源碼,而是反編譯得來,不正確之處,還望指教。

3.1? ADD

接上篇博文,當初始化一個沒有任何元素的ImmutableList<T>對象之后,對象會獲得一個EmptyNode

下面看看添加一個元素的流程,及數(shù)據(jù)結(jié)構(gòu)的變化。

測試代碼:

?static?void?Main(string[]?args)

????????{

????????????var?fruitBasket?=?ImmutableList.Create<string>();

??????????var?ass??=?fruitBasket.Add("ddd");}

?

如上圖,在Add方法內(nèi)部,會調(diào)用Node類型的Add方法,返回一個新的的Node實例。Add方法源碼如下:

??????????????????? internal?ImmutableList<T>.Node?Add(T?key)

??????????????????? {

?????????????????????????? return?this.Insert(this.count,?key);

??????????????????? }

Add方法又調(diào)用了Insert方法,此時count=0key=”ddd”。在Insert內(nèi)部先判斷了左子樹是否為空,如果為空則創(chuàng)建新的Node,調(diào)用具有四個輸入?yún)?shù)的構(gòu)造函數(shù)。

????? if?(this.IsEmpty)//

?????????????????????????? {

????????????????????????????????? return?new?ImmutableList<T>.Node(key,?this,?this,?false);

?????????????????????????? }

這一步很巧妙的完成了樹的構(gòu)造,代碼如下:

private?Node(T?key,?ImmutableList<T>.Node?left,?ImmutableList<T>.Node?right,?bool?frozen?=?false)

??????????????????? {

?????????????????????????? Requires.NotNull<ImmutableList<T>.Node>(left,?"left");

?????????????????????????? Requires.NotNull<ImmutableList<T>.Node>(right,?"right");

?????????????????????????? this.key?=?key;

?????????????????????????? this.left?=?left;

?????????????????????????? this.right?=?right;

?????????????????????????? this.height?=?1?+?Math.Max(left.height,?right.height);

?????????????????????????? this.count?=?1?+?left.count?+?right.count;

?????????????????????????? this.frozen?=?frozen;

??????????????????? }

原來的rootempty node)這里變成新Node的左右子節(jié)點,新節(jié)點key字段(即value)被賦值“ddd”,heightcount都等于1,此時frozen=false。需要注意的細節(jié)是,調(diào)用Node(T key, ImmutableList<T>.Node left, ImmutableList<T>.Node right, bool frozen = false)之前傳入的this指針和函數(shù)內(nèi)部的this指針指向的是不同的內(nèi)存區(qū)域。

注意,傳入的Node對象沒有做任何修改,返回的是新NewNode

當前創(chuàng)建的Node對象的結(jié)構(gòu)如下:

?

繼續(xù)運行,從Node類里出來,回到ImmutableList<T>Add方法:

????? public?ImmutableList<T>?Add(T?value)

???????????? {

??????????????????? ImmutableList<T>.Node?node?=?this.root.Add(value);

??????????????????? return?this.Wrap(node);

???????????? }

在得到新的的Node后,會執(zhí)行Wrap方法。

?

同理,內(nèi)部的Node完成了樹形結(jié)構(gòu)的轉(zhuǎn)換,外部的ImmutableList<T>也要完成這一轉(zhuǎn)換,返回新的ImmutableList<T>對象,將新的Node賦值到自己的root字段上,并初始化相關(guān)字段。

????? private?ImmutableList(ImmutableList<T>.Node?root,?IEqualityComparer<T>?valueComparer)

???????????? {

??????????????????? Requires.NotNull<ImmutableList<T>.Node>(root,?"root");

Requires.NotNull<IEqualityComparer<T>>(valueComparer,?"valueComparer");

??????????????????? root.Freeze();

??????????????????? this.root?=?root;

??????????????????? this.valueComparer?=?valueComparer;

???????????? }

OK,終于又回到了Main函數(shù)中,完成了一次輪回:

?

ImmutableList<T>通過更新樹結(jié)構(gòu),新建ImmutableList<T>對象同時更新對Node的引用創(chuàng)建新的集合。樹結(jié)構(gòu)雖然發(fā)生了變化,但是原來的集合對節(jié)點的引用并沒有發(fā)生變化,從而保證了集合的不變性。

繼續(xù)修改Main函數(shù)的代碼:

??static?void?Main(string[]?args)

????????{

????????????var?fruitBasket?=?ImmutableList.Create<string>();

??????????var?a2??=?fruitBasket.Add("ddd");

??????????var?a3?=?a2.Add("ccc");

????????}

我們觀察執(zhí)行var a3 = a2.Add("ccc")時的行為變化。

?

當前代碼沿著上圖所示的路徑再次來到Node類的Insert方法。

?

第一次執(zhí)行Add時的情景上面分析過了,當Node的左右子樹不為空時,首先要判斷元素應(yīng)該添加左還是右,判斷邏輯很簡單,判斷當前準備添加元素的索引是否小于等于左子樹元素的個數(shù)。由于當前左子樹只有一個Empty節(jié)點,所以元素會被添加到右子樹上去。可以設(shè)想一下,如果再次執(zhí)行添加操作,元素還是會被添加到右子樹上去,左邊會一直為空。所以在每次添加操作執(zhí)行完畢之后,會調(diào)用MakeBalanced方法來使左右平衡。如果您熟悉紅黑樹的話,對保持樹的平衡時使用的扭轉(zhuǎn)算法應(yīng)該不會陌生。這里我不想深入解釋ImmutableList 的“平衡扭轉(zhuǎn)”算法,我覺得單獨拿出來一篇博文來講解會更好。

下一篇博客中,我們繼續(xù)分析ImmutableList的其他行為的原理。

轉(zhuǎn)載于:https://www.cnblogs.com/xuanhun/p/3159823.html

總結(jié)

以上是生活随笔為你收集整理的Immutable Collections(3)Immutable List实现原理(中)变化中的不变的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。