每天学习一点儿算法--快速排序


快速排序是一种常用的优雅的排序算法,它使用分而治之的策略。

那么分而治之(D&C)是一种怎样的策略呢?

分而治之

分而治之(D&C)的要点只有两个:

  • 找出简单的基线问题

  • 确定如何缩小问题的规模,使其符合基线条件

D&C不是一种解决问题的算法,而是一种解决问题的思路。比如看下面这个例子:

这是一个数字数组:

你需要将这些数字相加,并返回结果。使用循环可以很轻松地解决这个问题:

def sum(arr):
    """一个数组元素相加的循环"""
    total = 0
    for i in arr:
        total += i
    return total

print(sum([2, 4, 6])) 

但是如何使用递归函数来完成这种任务呢?

  • 第一步:找出基线条件。如何一个数组只包含一个或者零个元素,那计算总和将会非常容易:

这就是基线条件

  • 第二步:缩小问题规模,使其符合基线条件。如果递归调用都使其里空数组更近了一步,那么这就缩小了问题规模。

下面用代码实现这个过程:

def sum(arr):
    """计算列表的各元素总和"""
    if arr == []:
        return 0
    else:
        return arr[0] + sum(arr[1:])

s = sum([2, 4, 6]) 
print(s) 

说了这么多,却好像还是在说递归的知识,这和快速排序有什么关系呢?

快速排序

对于排序算法来说,最简单的数组是什么样的?对,没错,最简单的数组就是不需要排序的数组:

因此,在涉及多个元素的数组进行排序的时候,我们可以利用分而治之策略:将数组分解,直到满足基线条件为止。

简要叙述一下快速排序的基本思想:

  • 首先,从数组中选取一个元素,这个元素被称为基准值

  • 将数组分为两个子数组:小于基准值的元素和大于基准值的元素

  • 对这两个子数组进行快速排序

可能有小伙伴到这里又懵了,这不还是没有说清楚快速排序到底是怎么排的嘛。

客官别急,下面来说快速排序的具体实现步骤:

  • 设置两个变量i、j,排序开始的时候:i=0,j=N-1

  • 以第一个数组元素作为关键数据,赋值给key,即key=A[0]

  • 从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]和A[i]互换

  • 从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换

  • 重复第3、4步,直到i=j

用一个例子来说明:

下面用代码实现快速排序:

def quicksort(array):
    """快速排序"""
    if len(array) < 2:
        return array  # 基线条件:为空或者只包含一个元素的数组是有序的
    else:
        pivot = array[0]  # 递归条件
        less = [i for i in array[1:] if i <= pivot]  # 由所有小于或等于基准值的元素组成的子数组   

        greater = [i for i in array[1:] if i > pivot]  # 由所有大于基准值的元素组成的子数组   

        return quicksort(less) + [pivot] + quicksort(greater)

print(quicksort([10, 5, 2, 3]))

再谈大O表示法

快速排序的独特之处在于,其速度取决于选择的基准值。这也就产生了最佳情况和最糟情况之分。

在最佳情况下,快速排序的运行时间为O(n ㏒n)。

在最糟情况下,快速排序的运行时间为O(n²)。

说明:最佳情况也是平均情况。

我们一般使用大O表示法都是指的算法的平均情况,所以我们一般认为快速排序的运行时间为O(n ㏒n)。至于何为最佳情况和最糟情况,这里不再过多阐述了。

小结

  • 大O表示法指的是算法的平均时间

  • 大O表示法省略了常数

  • 快速排序的平均运行时间为O(n ㏒n)

  • 使用D&C处理列表时,基线条件一般是空数组或只包含一个元素的数组

每天学习一点点,每天进步一点点。

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