您的位置:首页 > 其它

冒泡排序与快速排序

2015-05-24 16:49 267 查看

快速排序 (通俗易懂的讲解)

关于快排,查了很多网上的资料,大抵都是抽象难懂的表述,有些大牛也许不屑于讲清楚这件事,而大部分是相互抄袭。今天希望能讲这个常用的算法让所有人看明白。

冒泡排序

确定位置,找数字的排序

要说快排,不得不先说冒泡这种排序。仔细回想下冒泡的过程,事实上可以总结成确定位置,找数字的排序。

设排序前的串叫 目标串,排序后的串叫 结束串,从目标串 —->结束串 一共会经历n趟排序。

进行第1趟排序后, 目标串 的第1个位置数,一定就是 结束串 第1个位置的数。这一趟一共要比较n-1次,才能结束。

进行第x趟排序后, 目标串 的第x个位置数,一定就是 结束串 第x个位置的数。这一趟一共要比较n-x次,才能结束。

排序完一共经历了 n-1 + n-2 +…+ n-x+…+1 大于等于 n^2/2,可以确定是O(n^2)数量级;

这里不作过多解释,相信聪明的你,仔细想想就明白了。

快速排序

确定数字,找位置的排序

仔细看,快排 是在目标串 里拿到第一个数,在一趟排序结束后,这个数字在 目标串里的位置就会被调整成 它最后在 结束串 里的位置。例子:

目标串 8 3 1 9 7 19 6

结束串 1 3 6 7 8 9 19

目标串 经历一次排序,变成:

中间串 6 3 1 7 8 19 9

中间串 8的位置和 结束串 8的位置已经达成一致

然后8 就好像一根分割线 把中间串分成

串 6 3 1 7

串 19 9

这两个串继续作为 目标串 进行排序。

好了那么问题就剩下

目标串 8 3 1 9 7 19 6

是如何变成

中间串 6 3 1 7 8 19 9

在这个变化过程中 我们遵循 一个逻辑原则 我希望把8一口气移动到它最后该在的位置上, 如何确定8的位置呢, 我只要保证 8的左边的所有数字都比8小,8右边的数字都比8大,那么8 就在他该在的位置上了。



说明一下上图,短指针就是为了确定8以外的数字,和8之间的位置关系。

如果短指针在长指针的右边,那么我们期望短指针的指的数比8大,

如果成立,那么说明这个数相对于8 的位置没错,那么短指针向长指针靠近来寻找下一个数是不是在正确的相对位置。

如果不成立,交换2个位置的数,让她们相对位置正确。

然后我们可以把问题抽象一下变成:



小 区域表示 确定了比target小得数

大 区域表示 确定了比target大得数

随着 靠近和交换 两种动作的进行,小区域 和 大区域 的面积 不断变大,不确定区域不断变小,直到消失,就完成了这次排序。并且把目标串 分成了两个子目标串(递归对子目标串进行 和目标串 相同的操作)

总结下快排的排序想法:

把选中的数字放到他最后该在的位置,把串分成两部分

最后再来看看时间复杂度:



目标串 会被切成一颗二叉树。

我们先考虑最好的情况,每次切分都是切在中点。这样树的深度最浅(层数最少)

对于第一层来说 ,n个数,最后两个指针能相遇 说明比较了n次,O(n)

对于第二层俩说,左右两个节点相加也是n个数(可能少一两个数),说明也是比较了n次,O(n)

对于每一层我们都大约考虑为O(n),一共logN层,复杂度就是O(n*logN)

再考虑最差情况,每次都砍再边缘 而不是中间,这样树的深度就变成n,相当于每次排序都是为了找最边缘位置上应该有的值(和冒泡的逻辑策略完全一致),自然时间复杂度也退化成了O(n^2)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐