美文网首页
可能是最容易理解的快速排序原理讲解

可能是最容易理解的快速排序原理讲解

作者: BlindingDark | 来源:发表于2016-10-26 01:21 被阅读7366次

Clojure 快速排序 快排


快速排序(Quicksort)是一种优秀的排序算法,这个就不多介绍了。
本文用最通俗的语言讲解快速排序的原理,以及如何使用 Clojure 实现快速排序。


首先快速排序的原理很简单,不要被那些专业名词吓傻了。什么分治法,什么分析时间复杂度,又搞什么两个指针一会儿这边移动一会儿交换一会儿那边移动。这些对你理解快排的原理毫无帮助,反而会阻碍你理解快排的本质。

快排的本质就一句话:

从需要排序的数里面随便找出一个,然后,把比这个数小的放在这个数左边,比这个数大的放在这个数右边,一样大的和这个数放在一起,最后,左右两边各自重复上述过程,直到左边或右边只剩下一个数(或零个数)无法继续为止。

我们可以明显的看出这是一个递归定义。

先看灵魂画手的示意图:


假如我们要给这五个数字排序,首先我们先从中随意选取一个数字,比如 4。
按照规则,比 4 大的数字都放在右面,比 4 小的数字都放在左面。所以一次过后变成了这样。

按照规则,左右两面各自重复上述步骤,直到数量为一个以下无法继续。右面已经只有一个了,所以不用重复了。左面重复上述步骤。
还是随机从中选取数字,这次我们选择 2。把大于 2 的放在右面,小于 2 的放在左面。

左右两边都已经是一个,不用继续了,排序结束。


那在 Clojure 中如何实现这种算法呢?
我们直接看代码:

(defn quick-sort
  [nums]
  (if (< (count nums) 2)
    nums
    (concat
     (quick-sort (filter #(< % (first nums)) nums))
     (filter #(= % (first nums)) nums)
     (quick-sort (filter #(> % (first nums)) nums)))))

这段代码十分浅显易懂。首先定义一个函数,名叫 quick-sort,它接受一个数字集合。
如果集合中元素的数量小于 2,那么直接返回这个集合。这符合快排的定义。
如果元素数量大于等于 2,我们选取集合的第一个元素作为分割的标准(定义中是随机选取,所以在这里可以根据你的喜好和需要进行选取),使用 filter 函数筛选出小于、大于、等于,三种情况,最后使用 concat 函数进行连接。

一切都是这么自然。


我们来看一下实际运行情况。

首先要生成一些随机数以供排序。这个我们写一个函数来产生:

(defn rand-n-m [n m]
  "从 1 到 m 范围内,随机产生 n 个数字"
   (repeatedly n #(+ 1 (rand-int m))))

生成 1 到 100 内的随机数 10 个:

=> (println (rand-n-m 10 100))
(25 42 4 34 8 35 93 47 58 16)

还不错,我们来看看排序算法工作如何:

=> (println (quick-sort (rand-n-m 10 100)))
(10 16 18 35 41 47 57 83 86 90)

刷的一下就出来了。
不过就 10 个数字显露不出我们快排的威力,这次我们上多点数字。并在外侧套上 time 统计运行时间。

=> (time (quick-sort (rand-n-m 10000 100000)))
"Elapsed time: 144.926382 msecs"

旁边的冒泡排序依然在吭哧吭哧算着呢...


P.S..
为啥 C 、Java 等一批语言写快排怎么搞了一个数组两个指针循环过来循环过去?
这个你们自己思考,声明式编程和命令式编程的区别。

相关文章

  • 可能是最容易理解的快速排序原理讲解

    Clojure 快速排序 快排 快速排序(Quicksort)是一种优秀的排序算法,这个就不多介绍了。本文用最通俗...

  • 快速排序就这么简单

    快速排序就这么简单 从前面已经讲解了冒泡排序、选择排序、插入排序了,本章主要讲解的是快速排序,希望大家看完能够理解...

  • 插入排序

    插入排序 插入排序的代码实现虽然没有冒泡排序和选择排序那么简单粗暴,但它的原理应该是最容易理解的了,因为只要打过扑...

  • 排序-插入排序(交换类型-循环嵌套)

    插入排序 插入排序的代码实现虽然没有冒泡排序和选择排序那么简单粗暴,但它的原理应该是最容易理解的了,因为只要打过扑...

  • 【003】Swift经典排序算法-插入排序

    插入排序 插入排序的代码实现虽然没有冒泡排序和选择排序那么简单粗暴,但它的原理应该是最容易理解的了,因为只要打过扑...

  • 玩扑克牌中插扑克牌手法就是不一样,C语言经典算法之插入排序

    插入排序 插入排序的代码实现虽然没有冒泡排序和选择排序那么简单粗暴,但它的原理应该是最容易理解的了,因为只要打过扑...

  • 排序算法③——插入排序

    插入排序 插入排序的代码实现虽然没有冒泡排序和选择排序那么简单粗暴,但它的原理应该是最容易理解的了,因为只要打过扑...

  • 算法与数据结构-插入排序

    一、概念 插入排序的代码实现虽然没有冒泡排序和选择排序那么简单粗暴,但它的原理应该是最容易理解的了,因为只要打过扑...

  • 插入排序

    1. 基本定义 插入排序的代码实现虽然没有冒泡排序和选择排序那么简单粗暴,但它的原理应该是最容易理解的了,因为只要...

  • 1.3 插入排序

    插入排序的代码实现虽然没有冒泡排序和选择排序那么简单粗暴,但它的原理应该是最容易理解的了,因为只要打过扑克牌的人都...

网友评论

      本文标题:可能是最容易理解的快速排序原理讲解

      本文链接:https://www.haomeiwen.com/subject/crlduttx.html