您的位置 首页 java

尚学堂百战程序员之快速排序

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

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

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

首先,对于一大堆无序的数字,从中随机挑选一个数字,比如是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份了。

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

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

后记: 对于大部分转行的人来说,找机会把自己的基础知识补齐,边工作边补基础知识,真心很重要。

我们相信人人都可以成为一个IT大神,现在开始,选择一条阳光大道,助你入门,学习的路上不再迷茫。这里是北京尚学堂,初学者转行到IT行业的聚集地。”

文章来源:智云一二三科技

文章标题:尚学堂百战程序员之快速排序

文章地址:https://www.zhihuclub.com/189405.shtml

关于作者: 智云科技

热门文章

网站地图