人生算法之“快速排序”

Posted 荻确如此

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了人生算法之“快速排序”相关的知识,希望对你有一定的参考价值。

欢迎转载,甚至无需保留以上声明



上次我们介绍了数据结构中的堆栈问题,今天来介绍一下算法。世界上有没有“最好的”算法呢?在评价“最好”之前,还是要加一些限制条件,比如是一般条件下最好,还是恶劣条件下最好。


在南京三牌楼,如果要去南京站,一般情况下是要从玄武湖隧道通过的,但是如果那里发生了一些意外,基本上动都动不了的。如果选择从玄武湖公园穿过去(东西不多的话),可以在这极端情况下赶上火车。所以,世界上没有绝对的好。


讲到排序,目前世界上通常情况下最好的算法是一种叫做“快速排序”的算法。由英国计算机科学家托尼霍尔想到的。那么为啥这么快呢?因为它强调少做事情。


首先,对于一大堆无序的数字,从中随机挑选一个数字,比如是33,这个被随机选上的数字被称为是枢值,接下来,将所有要排序的数字分成两部分,第一部分是大于等于33的,第二部分是小于枢值33的,在第一步完成后,一大堆无序的数字就变得稍微有序一点了。 
(小于33的数)33(大于33的数)


第二步,从上面得到的两堆数字,分别采用第一步的方法各自再找一个枢值。对于第一堆,由于所有数字都比33大,至少也等于33,因此,第二次随机挑选的枢值肯定也是一个大于33的数字,比如70;类似的,对于第二堆,由于所有的数字都小于33,因此第二次随机挑选的枢值都肯定小于他,比如6。接下来,再把两队数字各自分成大于等于相应枢值的数字序列,以及小于枢值的数字序列。这样,原来的一大堆数就变成了4小堆。 

(小于6的)6(大于6小于33的)33(大于33小于70的)70(大于70的)


在接下来,用同样的方法,四堆变八堆,八堆变十六堆,很快所有的数字就排好序了。


这种算法通常情况下复杂度是Nlog(N),比选择排序,冒泡排序快的多。


假如有一个学区,里面有20000名高中学生,如果让大家到一个超级大的学校上大课,再从中挑出学生中的尖子,效率肯定低。如果事先划出几个分数线,根据个人成绩的高低把20000名学生分到十所学校,第一所学校里的学生成绩最好,第十所最差,再找出尖子生,就容易了,这就是快速排序的原理。


以下是我们对10,5,2,3,41,38,96进行排序的代码:

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,41,38,96]))

快速排序是通常情况下最好的算法,但是,在极端情况下,他的复杂度是N平方,和冒泡排序一样糟糕,世上没有绝对的好。


把快速排序带入到我们日常生活中来,可以帮助我们有效地辨别事情的轻重缓急,学做减法。把事情依照“重要/不重要”和“紧急/不紧急”两个维度,划分成四个象限,这是很多时间管理的书籍会提供的工具。然而我们需要把每件事情从头考量,评断后再分类,就又浪费了很多时间在规划上。


更有效的办法就是我们的快速排序。


首先找到一个显而易见的待办事项(枢纽),接着综合考虑急迫性和重要性,分成两拨。


再给两拨事情找枢纽,就把所有的工作依照评分分成4份了。


在接下来,快速检查后两部分的事情,将不必要的事做减法删除,将重要但不急迫的事情先预定计划。然后专注完成前两部分的事情,通过排序和减法,一天要完成的工作就剩下了一半。


枢纽这个节点,帮我们树立了参考点,事情一件件单看,很难取舍;但是有了参考,一比较就能掂量差别,我们就可以勇敢做减法了。


参考:《谷歌方法论》《算法图解》


禅定时刻

计算机算法对你的实际生活有没有帮助呢?还是你已经习惯了这种做事情的方法了呢?欢迎留言与我分享~

zengdiqing


以上是关于人生算法之“快速排序”的主要内容,如果未能解决你的问题,请参考以下文章

经典排序算法之——06 快速排序

你应该知道的常用排序算法之插入排序

重学数据结构和算法之归并排序快速排序

常用算法的简洁代码实现之快速排序归并排序

排序算法之快速排序

排序算法之快速排序