面试之快速排序
Posted 每日一算法
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面试之快速排序相关的知识,希望对你有一定的参考价值。
通过代码实现快速排序算法。
首先来介绍一下什么是快速排序。
快速排序(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)。
讲了这么多,如果有错的话,记得指出哦,希望你们能够理解,好的话请关注一下吧~~~
https://github.com/1260380285/suanfa/blob/928986578ba1c9ea09481d1b9832212f3cd444de/src/com/test/KuaiSuPaixun.java
你的关注是我最大的动力
如果你想要跟大家分享你的文章,欢迎留言投稿~
如果你喜欢,请留下你的赞哦
以上是关于面试之快速排序的主要内容,如果未能解决你的问题,请参考以下文章