C#函数式编程入门之快速排序

threenewbee 2013-09-19 03:36:37
加精
之前有人提出C#实现Currying太难看,也有人提出了F#。于是我又用F#写了下之前的那几个例子程序
第一个
    let add x y = x + y
let mutable i = add 3 4
printfn "%d" i


第二个
    let addTen x = add 10 x
let mutable i = add 3 4
let mutable j = addTen i
printfn "%d" j


第三个
    let eval x y z = y x z
let add x y = x + y
let mutable i = eval 3 add 5
printfn "%d" i


第四个
    let eval x y z = y x z
let sub x y = x - y
let mutable i = eval 8 sub 1
printfn "%d" i


最后一个
    let outputArray = Array.iter (fun x -> printfn "%d" x)
outputArray [| 1; 2; 3; 4; 5 |]


和C#的版本一比较,真是太优雅了!

好了,开始正题:

之前我在论坛贴了一个神奇的程序,用Lisp进行的快速排序
quicksort [] = []
quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)
where
lesser = filter (< p) xs
greater = filter (>= p) xs


有人表示看天书一样,为了解释原理,我用C#改写了一个,代码稍微猥琐了点,但是还是很简洁的:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Func<Func<int, int, bool>, Func<int[], int[]>> filter =
x => new Func<int[], int[]>(y => y.Skip(1).Where(z => x(y[0], z)).ToArray());
Func<int[], int[]> qsort = x => x;
Func<int[], int[]> lesser = dt => filter((x, y) => y < x)(dt);
Func<int[], int[]> greater = dt => filter((x, y) => y >= x)(dt);
qsort = dt => dt.Length > 1
? qsort(lesser(dt)).Concat(new int[] { dt[0] }).Concat(qsort(greater(dt))).ToArray()
: dt;
int[] data = { 4, 3, 1, 4, 6, 7, 5, 9, 3, 11, 1, 2, 11 };
var result = qsort(data);
foreach (int x in result) Console.WriteLine(x);
}
}
}


运行:

1
1
2
3
3
4
4
5
6
7
9
11
11
Press any key to continue . . .

简单解释下,其实这个不用我废话,如果快速排序的原理你没有忘记的话。
快速排序的思路就是根据某个元素(我这里用第一个元素)为参照,把数据分成两堆,小的一堆在左边,大的在右边,参照数据在中间,然后分别对左右两堆递归整理,直到某一堆只有一个元素为止,此时,数据就是排好序的了。

说说程序猥琐在什么地方,复杂的类型声明这个不用提,也不用提数组的连接,因为除非使用代码块,没办法在Lambda表达式内再嵌套定义Lambda表达式,只好让lesser和greater后面跟着难看的(dt)。

最后用F#实现一次:
[<EntryPoint>]
let main argv =
let lesser (x: int array) = Array.filter (fun i -> i < x.[0]) x.[1..]
let greater (x: int array) = Array.filter (fun i -> i >= x.[0]) x.[1..]
let rec qsort (p: int array) =
match p.GetLength(0) with
| 0 | 1 -> p
| _ -> Array.concat [ (qsort(lesser p)); [| p.[0] |]; (qsort (greater p)) ]
let data = [| 4; 3; 1; 4; 6; 7; 5; 9; 3; 11; 1; 2; 11 |]
printfn "%A" (qsort data)
0


[|1; 1; 2; 3; 3; 4; 4; 5; 6; 7; 9; 11; 11|]
Press any key to continue . . .
...全文
5522 101 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
101 条回复
切换为时间正序
请发表友善的回复…
发表回复
csharpSun 2014-05-07
  • 打赏
  • 举报
回复
不是很明白的路过。
Mars_lyc 2013-10-16
  • 打赏
  • 举报
回复
谢谢分享,好人一生平安~
anguspt 2013-10-09
  • 打赏
  • 举报
回复
还是看不懂啊
nimalagebb 2013-10-08
  • 打赏
  • 举报
回复
引用 17 楼 sp1234 的回复:
[quote=引用 13 楼 spawn888 的回复:] 版主最好分享一个非递归的写法和讲解,因为非递归的做法才能让我们这些菜鸟对分治法有更好的理解,很多人根本就不知道递归调用过程中,栈的操作方式。
不知道计算机的堆栈,就不会写函数递归了吗?我们从小学时就学过解数学方程式了,就学会递归地代入变量值进行求解了,也没有听说什么计算机堆栈。 递归是基本的数学函数概念的体现,跟什么堆栈没有关系。[/quote] 这个sp1234真TM的是个SB, 回复永远是这种拽上天的,似是而非的SB言论。看不惯初学者你TM的别来回呀, 一条人家还以为你是高手,成千上万条都是这种长篇大论的人生哲理论, 你TM的算个屁啊,不帮别人就别成天JJYY一大堆这种哲理论,你TM算老几啊,轮得到你教育别人吗?S B一个!
fengxing 2013-10-07
  • 打赏
  • 举报
回复
感谢分享
ljf8791 2013-10-07
  • 打赏
  • 举报
回复
初学者真看不懂
  • 打赏
  • 举报
回复
我是真心看不懂啊!感谢分享!
adamsun 2013-10-03
  • 打赏
  • 举报
回复
健者天行 2013-10-02
  • 打赏
  • 举报
回复
看不懂.......
drafire2013 2013-09-29
  • 打赏
  • 举报
回复
学习了。。。
mbugaifc 2013-09-28
  • 打赏
  • 举报
回复
yanlingshuai 2013-09-28
  • 打赏
  • 举报
回复
看不懂啊啊啊
yanqi200878 2013-09-28
  • 打赏
  • 举报
回复
谢谢分享啊 看不懂
u012273352 2013-09-28
  • 打赏
  • 举报
回复
真心想学~~
  • 打赏
  • 举报
回复
顶…………………………………很好………………………
mbugaifc 2013-09-27
  • 打赏
  • 举报
回复
尹家伟 2013-09-26
  • 打赏
  • 举报
回复
learnning
尹家伟 2013-09-26
  • 打赏
  • 举报
回复
learnning
shuangchidadiao 2013-09-25
  • 打赏
  • 举报
回复
说的确实好啊
524774633 2013-09-24
  • 打赏
  • 举报
回复
谢,虽然还是看不懂
加载更多回复(67)

111,088

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧