首页 > 编程知识 正文

快速排序的过程,堆排序过程图解

时间:2023-05-03 09:14:05 阅读:21429 作者:4434

注意:本文为转载文章,原文地址为: http://www.cn blogs.com/a halei/p/3568434.html原作者:哈磊

这是我见过的说明最快排序的文章,共享如下。 如果我们的计算机一秒钟可以运行10亿次,那么排序一亿个,水桶排序只需要0.1秒钟。 泡沫排序需要1千万秒,也需要115天。 你害怕吗? 有没有算法可以在不浪费空间的情况下快速排序一点? 那是“快速排序”! 光是听到这个名字你就觉得高端吗? 假设现在对“612 79345 108”这10个数进行了排序。 首先,在这个序列中适当地找数量作为基准数。 (请不要被这个名词吓到。 是为了参照的数量。 我知道以后有什么用。 为了方便,以最初的数6为基准数吧。 然后,必须将此序列中大于基准数的所有数置于6的右侧,将小于基准数的数置于6的左侧。 如下排列。 312 5469 7108在初始状态下,数字6位于序列的第一位。 我们的目标是假设这个位置是k,将6移动到序列中间的某个位置。 我现在需要找这个k。 并且,以第k个为边界点,左边的数都在6以下,右边的数都在6以上。 想想看。 你有办法做那个吗? 给你个提示吧。 请记住泡沫排序是如何通过“交换”一步一步地返回数量的。 这时也可以用“交换”的方法达到目的。 具体怎么一步一步地交换? 怎么交换方便省时间? 请先不要着急往下看,拿出钢笔,试着在纸上画画。 高中时代第一次学习泡沫排序算法时,我觉得泡沫排序很浪费时间。 每次只能比较相邻的两个数。 这显然是不合理的。 所以我想了一个方法。 后来我知道这是“快速排序”。 请让我小不点自恋(^o^ )。 方法很简单。 分别从初始排列“612 79345 108”的两端进行“探测”。 先从右向左找小于6的数,然后从左向右找大于6的数,交换他们。 其中,两个变量I和j可以分别指向序列的最左侧和最右侧。 我们给这两个变量取个好名字“哨兵I”和“哨兵j”。 fzdll使哨兵I指向序列的最左边(即i=1),指向数字6。 使哨兵j指向序列的最右边(即j=10 ),指向数字8。

首先哨兵j开始出动了。 这里设定的基准数是最左边的数,所以哨兵j需要先出动是非常重要的(请自己想想为什么)。 哨兵j一步一步向左移动,直到找到不足6的数量为止。 然后哨兵I再向右移动一步,直到找到数量大于6的数字(即I )。 最后哨兵j停在数字5之前,哨兵I停在数字7之前。

现在交换哨兵I和哨兵j所指要素的值。 更换后的顺序如下。

61259 347108至此,第一次交换结束。 接下来哨兵j继续向左移动。 (友情提醒,每次哨兵j必须先出发。 他发现4 (小于标准数6,满足要求)就停下来了。 哨兵I也继续向右移动,他发现9 (大于标准数6,符合要求)就停下来了。 此时再次进行更换,更换后的顺序如下。 612第54397 108次交换结束,“探测”继续。 哨兵j继续向左移动,他发现3 (小于标准数6,符合要求)又停下来了。 哨兵I继续向右移动,很辛苦! 哨兵I和哨兵j相遇时,哨兵I和哨兵j都走到3前面。 表示“探测”在此时结束。 交换基准数6和3。 更换后的顺序如下。 31 25469 7108第一次“勘探”真的结束了。 此时,以基准数6为边界点,将6的左侧的

数都小于等于6,6右边的数都大于等于6。回顾一下刚才的过程,其实哨兵j的使命就是要找小于基准数的数,而哨兵i的使命就是要找大于基准数的数,直到i和j碰头为止。           OK,解释完毕。现在基准数6已经归位,它正好处在序列的第6位。此时我们已经将原来的序列,以6为分界点拆分成了两个序列,左边的序列是“3  1 2  5  4”,右边的序列是“9  7  10  8”。接下来还需要分别处理这两个序列。因为6左边和右边的序列目前都还是很混乱的。不过不要紧,我们已经掌握了方法,接下来只要模拟刚才的方法分别处理6左边和右边的序列即可。现在先来处理6左边的序列现吧。           左边的序列是“3  1  2 5  4”。请将这个序列以3为基准数进行调整,使得3左边的数都小于等于3,3右边的数都大于等于3。好了开始动笔吧。           如果你模拟的没有错,调整完毕之后的序列的顺序应该是。         2  1  3  5  4           OK,现在3已经归位。接下来需要处理3左边的序列“2 1”和右边的序列“5 4”。对序列“2 1”以2为基准数进行调整,处理完毕之后的序列为“1 2”,到此2已经归位。序列“1”只有一个数,也不需要进行任何处理。至此我们对序列“2 1”已全部处理完毕,得到序列是“1 2”。序列“5 4”的处理也仿照此方法,最后得到的序列如下。         1  2  3 4  5  6 9  7  10  8           对于序列“9  7  10  8”也模拟刚才的过程,直到不可拆分出新的子序列为止。最终将会得到这样的序列,如下。         1  2  3 4  5  6  7  8 9  10           到此,排序完全结束。细心的同学可能已经发现,快速排序的每一轮处理其实就是将这一轮的基准数归位,直到所有的数都归位为止,排序就结束了。下面上个霸气的图来描述下整个算法的处理过程。  
          快速排序之所比较快,因为相比冒泡排序,每次交换是跳跃式的。每次排序的时候设置一个基准点,将小于等于基准点的数全部放到基准点的左边,将大于等于基准点的数全部放到基准点的右边。这样在每次交换的时候就不会像冒泡排序一样每次只能在相邻的数之间进行交换,交换的距离就大的多了。因此总的比较和交换次数就少了,速度自然就提高了。当然在最坏的情况下,仍可能是相邻的两个数进行了交换。因此快速排序的最差时间复杂度和冒泡排序是一样的都是O(N2),它的平均时间复杂度为O(NlogN)。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。