成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

C#快速排序的趣味實現:從Haskell說起

開發 后端
C#中缺少一些基礎的數據結構,因此無法直接實現向Haskell里面那樣的函數式快速排序。本文介紹一個C#快速排序的實現方法。

C#快速排序不好實現?

前一段時間有朋友問我,以下這段Haskell快速排序的代碼,是否可以轉化成C#中等價的Lambda表達式實現:

  1. qsort [] = []  
  2. qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs) 

我當時回答,C#中缺少一些基礎的數據結構,因此不行。經過補充之后,就沒有任何問題了。后來,我覺得這個問題挺有意思,難度適中,也挺考察“基礎編程”能力的,于是就自己寫了一個。如果您感興趣的話,也不妨一試。

這段代碼是經典的,常用的體現“函數式編程”省時省力的例子,用短短兩行代碼實現了一個快速排序的確了不起。您可能不了解Haskell,那么我在這里先解釋一下。

首先,這里用到了函數式編程語言中最常用的一種數據結構:不可變的鏈表。這個數據結構事實上是一個單向鏈表,并且是“不可變”的。這種數據結構在F#中也有存在,它的結構用大致是這樣的:

不可變的鏈表 

可見,這是一種遞歸的數據結構。如果我們把這種數據結構叫做是ImmutableList的話,那么每個ImmutableList對象就會包含一個元素的“值”,以及另一個ImmutableList對象(在上圖中,每個框就是一個ImmutableList對象)。對于每個ImmutableList對象來說,這個“值”便是它的“頭(Head)”,而內部的ImmutableList對象則是它的“尾(Tail)”。如果用C#來表示的話,ImmutableList在C#中的定義可能就是這樣的:

  1. public class ImmutableList<T> : IEnumerable<T>  
  2. {  
  3.     public readonly static ImmutableList<T> Empty = new ImmutableList<T>(default(T));  
  4.  
  5.     private ImmutableList(T head, ImmutableList<T> tail)  
  6.     {  
  7.         this.Head = head;  
  8.         this.Tail = tail;  
  9.     }  
  10.  
  11.     public T Head { getprivate set; }  
  12.  
  13.     public ImmutableList<T> Tail { getprivate set; }  
  14.  
  15.     ...  
  16. }  

您一定意識到了,ImmutableList是一個不可變的鏈表數據結構,一旦構造之后就再也沒有辦法修改它的Head與Tail。此外,這里使用Empty來表示一個空鏈表1。因此,我們使用一個ImmutableList對象便可以代表整個鏈表,并可以通過Tail來遍歷鏈表上所有的元素:

  1. public class ImmutableList<T> : IEnumerable<T>  
  2. {  
  3.     ...  
  4.  
  5.     #region IEnumerable<T> Members  
  6.  
  7.     public IEnumerator<T> GetEnumerator()  
  8.     {  
  9.         var current = this;  
  10.         while (current != Empty)  
  11.         {  
  12.             yield return current.Head;  
  13.             current = current.Tail;  
  14.         }  
  15.     }  
  16.  
  17.     #endregion  
  18.  
  19.     #region IEnumerable Members  
  20.  
  21.     IEnumerator IEnumerable.GetEnumerator()  
  22.     {  
  23.         return this.GetEnumerator();  
  24.     }  
  25.  
  26.     #endregion  
  27. }  

我們再來觀察Haskell代碼,這段代碼分為兩行:

  1. qsort [] = []  
  2. qsort (x:xs) = ... 

這兩行都定義了qsort函數,不過參數不同。這種做法在Haskell里被稱為“模式匹配”,qsort后面的參數即是“模式”。***行代碼的參數“指明”是一個空鏈表,因此只有為qsort傳入一個空的鏈表才會執行等號后的邏輯。如果為qsort函數傳入的鏈表不為空,那么它即可被匹配為head和tail兩部分,這在Haskell中表示為(head:tail)。因此,在調用第二行的qsort函數時,x會自動綁定為head元素,而xs會自動綁定為tail——結合之前的解釋,我們可以知道x是“元素”類型,而xs是另一個鏈表(可能為空)。

C#快速排序的實現

由于C#沒有Haskell的模式匹配方式,因此只能在方法內部使用if(或三元運算符?:)進行邏輯控制:

  1. public static class ImmutableListExtensions  
  2. {  
  3.     public static ImmutableList<T> QuickSort<T>(this ImmutableList<T> list, Func<T, T, int> compare)  
  4.     {  
  5.         if (list == nullthrow new ArgumentNullException("list");  
  6.         if (compare == nullthrow new ArgumentNullException("compare");  
  7.  
  8.         if (list == ImmutableList<T>.Empty)  
  9.         {  
  10.             ...  
  11.         }  
  12.         else 
  13.         {   
  14.             ...  
  15.         }  
  16.     }  
  17. }  

我們將QuickSort定義為ImmutableList的擴展方法,接受一個比較函數,最終則返回一個排序后的新的鏈表——因為ImmutableList是不可變的。

然后,我們再回到Haskell的代碼,我們可以看出,***行qsort函數由于接受了一個空鏈表,因此排序后的結果自然也是一個空鏈表。而第二行qsort則是一個較為標準的快速排序實現(快速排序的原理大致是:取一個元素作為pivot,先把那些比pivot小的元素放到pivot之前,再把比pivot大的放到pivot之后,然后對pivot的前后兩部分分別采取快速排序。遞歸至***,則整個鏈表排序完成):

  1. qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs) 

在上面這行代碼中,filter高階函數的作用是對一個鏈表進行過濾,并返回一個新的鏈表。它的***個參數為過濾條件(如(< x)或(>= x),它們都是匿名函數),而第二個參數則是被過濾的目標。(這里即為xs,它是qsort參數的tail)。“++”運算符在Haskell中的含義是連接兩個鏈表,并返回連接的結果。

因此,這行代碼的含義為:把小于x的元素使用qsort函數排序,連接上x元素,再連接上大于等于x的元素排序后的結果。于是,***的結果便是一個排好序的鏈表。

值得注意的是,由于鏈表是種不可變的數據結構,因此無論是qsort函數,filter函數,還是++運算符,它們都會返回一個新的鏈表,而不會對原有鏈表作任何修改。這點是和我們傳統所做的“數組排序”相比有所不同的地方。

現在,您就來嘗試實現那個QuickSort方法吧。您可以為ImmutableList補充所需的成員,只要保持ImmutableList的各種特性不變,并實現快速排序便可以了。

以上就實現了C#快速排序。本文來自老趙點滴:《趣味編程:函數式鏈表的快速排序》

【編輯推薦】

  1. 理解C# String類型:特殊的引用類型
  2. 關于interface繼承來源的討論
  3. C#顯式實現接口原理淺析
  4. C# interface學習經驗淺談
  5. C# interface使用實例分析
責任編輯:yangsai 來源: 老趙點滴
相關推薦

2011-04-13 17:31:16

C#.NET

2009-09-10 16:30:11

C#排序函數

2024-06-28 09:25:51

2009-08-17 16:56:46

C#自定義泛型類

2009-09-03 14:55:56

C#實現DataGri

2011-05-25 11:25:23

快速排序Javascript

2009-08-13 10:35:05

Scala數組排序

2021-10-13 14:03:23

C++EasyC基礎

2010-09-16 10:46:47

2014-12-24 09:41:05

x86C#

2009-08-10 16:19:37

C#冒泡排序

2009-08-03 17:38:12

排序算法C#數據結構

2009-09-14 18:11:23

C#排序方法

2009-09-04 17:34:11

C#CC++

2009-09-01 18:29:10

C#繼承C#多態

2009-08-26 09:54:45

C#打印預覽C#打印

2009-08-03 16:35:30

C#日期比較

2009-08-04 09:22:26

C#工廠模式

2015-06-25 11:21:33

C++Objective-C

2018-02-27 12:41:21

Serverless邊緣計算存儲
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 1级毛片| 欧美电影一区 | 国产精品视频一二三区 | 中文在线a在线 | 国产日产精品一区二区三区四区 | 精品一区二区三区免费视频 | 久久久久国产一区二区三区 | 亚洲精美视频 | 日韩一区精品 | 国产精品欧美一区二区三区不卡 | 99热精品国产 | 午夜合集 | 亚洲免费网 | 国产精品久久久久一区二区三区 | 亚洲精品一级 | 欧美第一区 | 91精品久久久久久久久久 | 欧美日韩国产精品一区二区 | 久久久99国产精品免费 | 91精品国产综合久久久久久首页 | 久久久精品视频一区二区三区 | av网站在线免费观看 | 日本黄视频在线观看 | 欧美视频一区 | 久久五月婷| 亚洲第一视频 | 欧美成人精品一区 | 久久国产免费看 | 久久久精品一区二区三区 | 欧美一区二区免费 | 婷婷开心激情综合五月天 | 精品一区二区三区四区五区 | 日韩一区二区三区在线视频 | 国产亚洲精品久久yy50 | 亚洲一二三视频 | 免费一区二区三区 | 中文字幕高清av | 国产91久久久久蜜臀青青天草二 | 久久久久久91香蕉国产 | 亚洲黄色高清视频 | 亚洲一区二区精品视频 |