交换排序-快速排序

快速排序

这个系列是回顾之前所学,是用python商量着完成的。

路过的大佬就当看个乐,实现算法的方式不一,也有讨巧的做法。

我只讲讲我的思路,希望大家浏览的时候能多多提建议,共同学习共同进步。

--------------------------------------------------------------------------------------------------------

快速排序是非常经典也是面试常问的算法,如果这六个算法中只记住一个,我推荐快排。

快速排序的基本思路:

  快排采用的是分治法,其基本思路是将原问题分解成若干个规模更小的但结构与原问题相似的子问题。通过递归地解决这些子问题,然后再将这些子问题的解组合成原问题的解。

  快速排序通常包括两个步骤:

   1.在无序数组中找到一个基点,将小于基点的元素放在基点的左边,将大于基点的元素放在基点的右边

   2.然后在小的部分和大的部分中再去用同样的方法去排序,直到最后每个分组个数为1时,排序结束

  在实现快排的过程中使用了递归的方法:

先举个例子:

[3, 4, 2, 5 ,1]

这里选择3为基点pivot,low指针指向index=0,high指针指向index=4:

[3, 4, 2, 5 ,1] 3

1跟3比,list[high] < pivot,赋值,然后从low开始:

[1, 4, 2, 5, 1] 3

4跟3比,list[low] > pivot,赋值,然后从high开始:

[1, 4, 2, 5, 4] 3

5跟3比,list[hgih] > pivot,high减1:

不动

2跟3比,list[high]< pivot,赋值:

[1, 2, 2, 5, 4] 3

此时指针low = 指针high,插入基点3,这个时候左边的都小于3,右边的都大于3,开始下一次递归。

以下是具体实现:

 1 def quick_sort(list, head, tail):
 2     # 9.那整个排序什么时候终止呢? 应该是分组只有一个数,即head=tail的时候,就可以停止了,这里直接在开头用一个if判断满足条件就直接return list
 3     if head >= tail:
 4         return list
 5     # 1.首先是确定头和尾,将基点的值一般设置为无序数组的头,这里为什么不用0? 虽然方法是分治,但整体还是一个数组,操作还是在整体中完成的,用0显然不合适
 6     pivot = list[head]
 7     # 2.high和low是后面确定pivot插入时机的依据,当它们相等时证明这次排序完成,为什么有了head和tail还要high和low? head和tail的作用是定位下一次递归的首尾
 8     high = tail
 9     low = head
10     # 6.从第5步之后,可能还没有得到想要的结果,可能情况是2比基点3小,但是在2之前还有个1,那我们需要接着执行3-5步的操作
11     while low != high:
12         # 3.先从high往左边走,将其值与基点比较,如果比基点大,就减1,继续比较
13         # 那么有个问题来了,如果一直都没有找到都比基点大,high减成-1是out of range的,所以需要一个启停条件,low<high
14         while low < high and list[high] >= pivot:
15             high -= 1
16         # 4.直到找到比基点小的,将它的值赋值给low
17         list[low] = list[high]
18         # 5.开始从low往右边走,思路和第3步一致
19         while low < high and list[low] <= pivot:
20             low += 1
21         list[high] = list[low]
22     # 7.那什么时候停止呢? 应该是low和high都指向同一个下标的时候,这意味着左边小于基点右边大于基点,正是插入基点的时机
23     list[high] = pivot
24     # 8.递归执行如下,第一个quick是小于基点的部分,第二个quick是大于基点的部分
25     quick_sort(list, head, high-1)
26     quick_sort(list, high+1, tail)
27     return list

这里有一点补充,在调试代码的时候,发现如果传入的数组中包含重复的元素时,无法输出结果,修改的地方在第二和第三个循环加了一个等号解决。

原文地址:https://www.cnblogs.com/PurpleRain98/p/13587823.html