《算法》学习——快速排序

前言

提前说明一下吧。
这篇文章只是记录自己学习《算法》——快速排序的过程,只会记录自己对算法实现过程的基本理解并不会对算法的时间成本等做详细的讨论。

快速排序简介

排序算法可能是应用最广泛的算法了,它的特点是简单、适用于不同的输入数据并且在一般的应用中比其他的排序算法要快。快速排序采用的也是分治思想,但是与归并排序不同的是快速排序是原地排序并不需要使用辅助数组能节省更多的内存资源。

基本算法

快速排序是将一个数组分成两个子数组,并将两个子数组独立的排序。数组的切分与归并排序有很大的不同,快速排序是找出一个元素作为基准,然后确定这个基准元素在数组中的位置,在这个过程中使基准左边的元素都不大于它右边的元素都不小于它。快速排序就是递归的调用切分的方法来完成排序的。

实现切分的方法

一般的策略是随意的去a[lo]作为切分的基准元素,然后从数组的左端开始向右扫描直到找到一个大于等于它的元素,再从数组的右端向左扫描直到找到一个小于等于它的元素。这两个元素即为没有排定的,交换他们的位置然后继续扫描。直到左右两个扫描的指针相遇。这时我们只需要将a[lo]与左边子数组最后的元素a[j]交换 j 即为切分的位置。

快排切分图.png

切分的代码实现

※注 exch为交换数组指定位置的元素,不再实现了

func partition(a:inout[Int],lo:Int,hi:Int) -> Int {
    var i = lo///左指针
    var j = hi+1///右指针
    let v = a[lo]///切分的基准元素
    while true {
        i = i + 1
        /**向右移动 i 指针直到a[i]大于等于v(基准元素)*/
        while a[i]<v {
            if i == hi {///防止越界
                break
            }
            i = i + 1
        }
        j = j - 1
        /**向左移动 j 指针 直到a[j]小于等于v*/
        while a[j]>v {
            if j == lo {///防止越界
                break
            }
            j = j - 1
        }
        /**i >= j 即是两个指针已经相遇了*/
        if i>=j {
            break
        }
      /**交换 i 与 j 使i左边的元素都小于基准元素,
          j右边的元素都大于基准元素 */
        exch(a: &a, i: i, j: j);
    }
    /**将基准元素与 j 交换位置,此时 基准元素a[lo]的位置排定
        j 即为切分位置*/
    exch(a: &a, i: lo, j: j);
    return j
}

排序算法的实现

切分的方法实现之后 我们就可以递归的调用切分方法来实现排序了。

func quickSort(a:inout[Int],lo:Int,hi:Int) -> Void {
    if lo>=hi {
        return
    }
    /**
    获取数组切分的位置,在切分过程中将切分基准元素的位置排定
    */
    let j = partition(a: &a, lo: lo, hi: hi);
    quickSort(a: &a, lo: lo, hi: j)
    quickSort(a: &a, lo: j+1, hi: hi)
}

现在就可以使用我们Swift版的快速排序来对数组进行排序了。

let N = 100
var a = [Int]()
for i in 0..<N {
    a.append(i)
}
a = a.shuffle()
quickSort(a: &a, lo: 0, hi: N-1)
print(a);

关于保持随机性

在上面的排序代码中,我们在调用快排方法quickSort之前数组a调用了自身的shuffle方法,这个方法的作用是将数组元素的顺序打乱。然而Swift中并没有为我们提供这样一个方法,下面贴上本人百度的方法。感兴趣的童鞋可以去学习下简书-Swift - Array 扩展 shuffle(),随机排序

extension Array {

    public func shuffle() -> Array {
        var list = self
        for index in 0..<list.count {
            let newIndex = Int(arc4random_uniform(UInt32(list.count-index))) + index
            if index != newIndex {
                swap(&list[index], &list[newIndex])
            }
        }
        return list
    }
    
}

※保持随机的重要性
快速排序最好的情况是每次都能将数组对半分。但是在切分不平衡时排序过程可能会变的极为低效。例如,第一次从最小的元素切分,第二次从第二小的元素切分。这就导致一个大子数组需要切分很多次。我们在快速排序之前将数组随机排序的原因就是要避免这种情况。

To be continued

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容

  • 最近在读< >时,了解到了很多常用的排序算法,故写一篇读书笔记记录下这些排序算法的思路和实现. 冒泡排序 冒泡排序...
    SylvanasSun阅读 672评论 0 0
  • 背景介绍:又称划分交换排序(partition-exchange sort),一种排序算法,最早由东尼·霍尔提出。...
    DreamFish阅读 225评论 0 1
  • 概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    蚁前阅读 5,149评论 0 52
  • 概述:排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    每天刷两次牙阅读 3,723评论 0 15
  • 数据结构与算法——快速排序 快速排序,顾名思义,它速度很快,针对一般应用中各种不同的输入都要比其他排序算法快很多,...
    sunhaiyu阅读 3,232评论 0 3