面试之快速排序

Posted 每日一算法

tags:

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

1
题目


通过代码实现快速排序算法。



2
解答



首先来介绍一下什么是快速排序。


快速排序(Quicksort)是对冒泡排序的一种改进,是由C. A. R. Hoare在1960年提出的,它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列


快速排序和冒泡排序一样,也属于交换排序,通过元素之间的比较和交换位置来达到排序的目的。

不同的是,冒泡排序在每一轮只把一个元素冒泡到数列的一端,而快速排序在每一轮挑选一个基准元素,并让其它比它大的元素移动到基准元素的一边,比它小的元素移动到它的另一边,从而把数列分解成两个部分。这种思路就叫做分治法。

那么每次把数列分成两部分,究竟有什么好处呢?我们可以打个比方,

假如给定6个元素的数列,通过上节的学习可以知道,一般情况下冒泡排序需要比较6轮,每轮把一个元素移动到数列一端,时间复杂度是O(n^2)。

在分治法的思想下,原数列在每一轮被拆分成两部分,每一部分在下一轮比较后又分别被拆分成两部分,直到不可再分为止。

这样一共需要多少轮呢?因为每次都分为二分之一,平均情况下需要logn轮,因此快速排序算法的平均时间复杂度是 O(nlogn)。

使用分治法,需要选定一个基准元素,以此为中心,把其他元素移动到基准元素的左右两边。

那么基准元素如何选择呢?最简单的方式是选择数组的第一个元素。

例如有数组{49,38,65,97,76,13,27,78,34,12},要求从小到大排序。我们该怎么办呢?

首先,我们选定基准元素49,并记住这个位置index。同时设置两个指针left和right,指向数组的最左和最右两个元素,

49   38   65   97   76   13  27   78   34   12

left                                                          right

当前left指向49,right指向12,我们从右边开始,把指针所指向的元素12和基准元素49比较,

因为49>12,所以用12替换原来49的位置,指针left向右移动一位,数组变成了

12   38   65   97   76   13  27   78   34   12

      left                                                   right

从这里可以初步得出,随着left指针的右移,left指针左边的都是小于基准元素的数字,大于right指针的都是大于基准元素的数字。

替换49的位置为12,同时left指针右移过后,我们开始比较当前left指针指向的元素38,

因为38<49,所以不移动,left再次向右移动一位,此时数组变成了

12   38   65   97   76   13  27   78   34   12

              left                                            right

因为49<65,所以我们把65替换掉right指针所在的位置的元素12,并且把right指针的位置向左移动一位。数组变成了

12   38   65   97   76   13  27   78   34   65

              left                                     right

right指针移动过后,比较right指针所在的元素34和基准元素的大小,因为34<49,所以用34替换left指针65所在的位置,left指针右移一步,数组变成了

12   38   34   97   76   13  27   78   34   65

                     left                            right

left指针移动过后,比较left指针所在元素97和基准元素的大小,因为97>49,所以需要移动,用97替代right指针所在的位置,right指针左移一位,数组变成了

12   38   34   97   76   13  27   78   97   65

                     left                     right

right指针左移之后,比较right指针所在的元素78,因为78>49,所以元素不需要移动,right指针向左移动一位,数组变成了

12   38   34   97   76   13  27   78   97   65

                  left             right

right指针向左移动了一位之后,比较right指针所在的元素27和基准元素的大小,27<49,所以需要用27替换left指针所在的位置97,并把left指针向右移动一位,数组变成了

12   38   34   27   76   13  27   78   97   65

                        left      right

left指针向右移动一位之后,比较left所在的元素76和基准元素的大小,76>49,所以需要移动位置,用76替换right指针所指的元素27,并使right指针向左移动一位,数组变成了

12   38   34   27   76   13  76   78   97   65

                        left right

right指针向左移动一位之后,比较right指针所在的元素13和基准元素的大小,因为13<49,所以需要替换,并且left指针右移。数组变成了

12   38   34   27   13     13      76   78   97   65

                             left(right)

此时left和right指针重合,我们这时候把基准元素放在当前两个指针的位置,也就是数组变成了

12   38   34   27   13   49   76   78   97   65   

一轮比较完成之后,此时可以观察到所有小于49的元素都在49的左边,大于49的元素都在49的右边。

再对49左边和右边的位置的元素分成2组,进行和上面同样的操作,最后就能组成一个有序的数组。

这种选择在绝大多数情况是没有问题的。但是,假如有一个原本逆序的数列,期望排序成顺序数列, 这是快速排序最差的情况,时间复杂度退成了 O(n^2)。                                                      

讲了这么多,如果有错的话,记得指出哦,希望你们能够理解,好的话请关注一下吧~~~


3
代码


https://github.com/1260380285/suanfa/blob/928986578ba1c9ea09481d1b9832212f3cd444de/src/com/test/KuaiSuPaixun.java



你的关注是我最大的动力

如果你想要跟大家分享你的文章,欢迎留言投稿~

如果你喜欢,请留下你的赞哦


以上是关于面试之快速排序的主要内容,如果未能解决你的问题,请参考以下文章

程序员面试必备之排序算法汇总(上)

面试常用算法之排序

《糊涂算法》之八大排序——快速排序

经典排序算法之快速排序详解

白话经典算法系列之六 快速排序 快速搞定 转

快速排序之种种:参考必须简化,评判必须单纯