遞迴小記
來自實際遇到的一個問題,需要查詢出根節點的下的所有子節點,首先想到的就是遞迴了,用JS寫過,C#之前寫了一次沒寫對,這次專門用心看了一下的,發現和ref關鍵字有關,寫貼上原始碼:
public static void InsertCmsTypeName(int typeid, ref List<string> cacheNameList) { string name = string.Empty; List<TB_CMSType> cts = CMS.GetCmsTypeForParentID(typeid); if (cts != null && cts.Count > 0) { foreach (TB_CMSType item in cts) { name = "GetSpecialProducts" + item.ID + Config.SiteID; cacheNameList.Add(name); InsertCmsTypeName(item.ID, ref cacheNameList); } } }
typeid是節點id,第一次是根節點,往後就是當前節點下的子節點了。cacheNameList是儲存資料的集合,型別名稱前面用了ref修飾。
為什麼呢,這裡就涉及到一個概念了,值傳遞!InsertCmsTypeName方法裡每次對集合做add操作的時候,cacheNameList的陣列個數都會新增。
List<string> cacheNameList = new List<string>(); Base.InsertCmsTypeName(4106, ref cacheNameList);
可以很明顯的看到,InsertCmsTypeName方法是沒有返回值的, 那麼如何保持遞迴方法裡cacheNameList的值呢,ref 就出來了,ref使引數的傳遞方式變成了值傳遞,每次引數指向的是記憶體裡的首地址,這樣每次修改這個值的時候,它本身就修改了。一般的引數傳遞是引用傳遞,就是說在傳遞引數的時候,引數的本身不會被修改,而通過ref修飾過的引數,傳遞方式變成值傳遞,每次方法內部修改這個引數的時候,引數的本身也會被修改,所以,InsertCmsTypeName無需返回值。
之前用C#寫遞迴的時候就是沒注意到這個,導致遞迴方法執行了,最後的結果還是沒有 (*/ω\*) 這裡記下筆記還是有必要的。
另,演算法真的很重要鴨,要是不會寫遞迴,這種通過根節點找出所有子節點的問題,怕是要寫for迴圈了,而且就算是for迴圈也不能根本性解決問題,只能預測最多有多少層,然後寫多少個for,麻煩的不行。當然,用遞迴也不能瞎用,要控制好進行遞迴的條件,不然很容易導致死迴圈的出現(這可是會卡死程式的,所以用的時候要慎用)。
相關文章
- 演算法小專欄:遞迴與尾遞迴演算法遞迴
- 【遞迴】小q的數列遞迴
- 遞迴和尾遞迴遞迴
- 快速排序【遞迴】【非遞迴】排序遞迴
- 遞迴遞迴
- 小心遞迴中記憶體洩漏遞迴記憶體
- Nodejs事件迴圈小記NodeJS事件
- 什麼是遞迴?遞迴和迴圈的異同遞迴
- go 遞迴Go遞迴
- JavaScript遞迴JavaScript遞迴
- 理解遞迴遞迴
- 分而治之-遞迴遞迴
- 遍歷二叉樹-------遞迴&非遞迴二叉樹遞迴
- 遞迴和遞推總結遞迴
- 迭代與遞迴--你被遞迴搞暈過嗎?遞迴
- C++ 學習筆記(2):String、遞迴、排序C++筆記遞迴排序
- 遞迴呼叫 VS 迴圈呼叫遞迴
- 遞迴總結遞迴
- SQL 遞迴思想SQL遞迴
- 遞迴函式遞迴函式
- 談談遞迴遞迴
- 遞迴問題遞迴
- 遞迴加回溯遞迴
- 遞迴-*快速排序遞迴排序
- 理解遞迴 Recurtion遞迴
- C#遞迴C#遞迴
- sql server遞迴SQLServer遞迴
- Vue元件遞迴Vue元件遞迴
- 【C++】翻轉二叉樹(遞迴、非遞迴)C++二叉樹遞迴
- kingbase SQL最佳化案例 ( union遞迴 改 cte遞迴 )SQL遞迴
- 快速排序(遞迴及非遞迴演算法原始碼)排序遞迴演算法原始碼
- 徹底理解遞迴,從遞迴的本質說起!遞迴
- ?30 秒瞭解尾遞迴和尾遞迴優化遞迴優化
- 記錄一次遞迴查詢的運用遞迴
- Vue3.0的遞迴監聽和非遞迴監聽Vue遞迴
- python-動態規劃的遞迴、非遞迴實現Python動態規劃遞迴
- 揹包問題的遞迴與非遞迴演算法遞迴演算法
- 【Java資料結構與演算法筆記(二)】樹的四種遍歷方式(遞迴&非遞迴)Java資料結構演算法筆記遞迴