zoukankan      html  css  js  c++  java
  • 不一样的快速排序

    快速排序是一个从程序设计基础开始,到数据结构,到算法都会提到的经典例子,常见的做法是取开头元素作为主元,将不大于它的元素放在前面,比它大的放在后面,而前面和后面再次递归调用。

    在scheme当中是这个样子的:

     1 #lang racket
     2 (define (smaller x l) 
     3     (cond 
     4         [(null? l) null]
     5            
     6         [(>= x (car l)) (cons (car l) (smaller x (cdr l)))]
     7         [else (smaller x (cdr l))]))
     8 
     9 (define (bigger x l) 
    10     (cond   [(null? l)         '()]
    11             [(< x (car l)) (cons (car l) (bigger x (cdr l)))]
    12             [else             (bigger x (cdr l))]  ))
    13 
    14 
    15 (define (quicksort l)  
    16     
    17        (cond   [(null? l) '()]
    18                [(not (pair? l)) l]
    19                [else 
    20                 (let (
    21                        [small (quicksort (smaller (car l) (cdr l)))]
    22                        [big   (quicksort (bigger  (car l) (cdr l)))]
    23                      )
    24                (append small (cons (car l) big)) )]
    25         ))
    26 
    27 (define l (list 8 3 2 1 5 4 6 9 9 7))
    28 (display ( quicksort l))

    简单的解释一下,先写了两个辅助性的函数:smaller  bigger,接受参数为一个参考主元值和一个列表,返回的是那个列表中比参考值小的所有元素的值构成的列表,实际上是一个filter,完全可以用filter来直接做。 注意的一点是,bigger 和 smaller当中的某一个需要包含相等的情况。

    quicksort 函数体很简单,如果列表是空的,返回空列表;

    如果参数并不是一个列表,而只是一个数,返回这个数;

    如果是一个列表,递归定义small 和 big ,然后 执行append small (cons (car l) big) ,也就是先构造  cons (car l) big,将当前主元值和big连接起来,在把它整体接在small的后面。

    程序看起来是不是比之前用C++ 写的话简洁很多~

    使用filter 的scheme版本:

     1 #lang racket
     2 (define (quicksort l)  
     3        (cond   [(null? l) '()]
     4                [(not (pair? l)) l]
     5                [else 
     6                 (let ( [small (quicksort (filter (lambda (y) (>= (car l) y)) (cdr l) ))]
     7                        [big   (quicksort (filter  (lambda (y) (< (car l) y)) (cdr l) ))])
     8                (append small (cons (car l) big)) )]))
     9 
    10 (define l (list 8 3 2 1 5 4 6 9 9 7))
    11 (display ( quicksort l))

    比之前看起来简单很多了吧~

    如果用haskell 来写的话:

    1 myquicksort :: (Ord a) => [a] -> [a]
    2 myquicksort [] = []
    3 myquicksort (x:xs) = 
    4     let small = myquicksort [a | a <-xs,a <= x]
    5         large = myquicksort [a | a <-xs,a > x ]
    6     in small ++ [x] ++ large

    哇,看起来不错~

    简单解释一下,第一行是一个类型声明,可以作为排序函数的参数的元素必须是可以比较的,也就是属于Ord类型的

    后面是一个简单的分类:

    1. 参数是[] ,返回[]

    2. 参数是list,用模式匹配分解 x:xs,同样利用filter来实现small 和 large ,这里用了列表推导式。(同样注意,等于的情况要并在小于或者大于之中)

    最后将三部分拼接起来。

    函数式编程还是比较有魅力的,但其实不只是上面展示的这种简洁,更舒服的是自定义很多语法糖,并且元语法很少,可以快速有效的掌握,而更多的语法糖不仅可以学会使用,还可以知道是如何构造出来的!

  • 相关阅读:
    [转] Chrome
    阿里安全潘多拉实验室首先完美越狱苹果iOS 11.2
    【阿里聚安全·安全周刊】阿里双11技术十二讲直播预约|AWS S3配置错误曝光NSA陆军机密文件
    卡巴斯基发布安全公告:2018年威胁预测
    【阿里聚安全·安全周刊】双十一背后的“霸下-七层流量清洗”系统| 大疆 VS “白帽子”,到底谁威胁了谁?
    分享一个白帽交流灵感的社区——先知技术安全社区
    WiFi网络WPA2 KRACK漏洞分析报告
    #云栖大会# 移动安全专场——APP渠道推广作弊攻防那些事儿(演讲速记)
    #云栖大会# 移动安全专场——APP加固新方向(演讲速记)
    Java安全编码:糟糕的在线建议和令人困惑的APIs
  • 原文地址:https://www.cnblogs.com/gaoduan/p/4162294.html
Copyright © 2011-2022 走看看