排序算法——快速排序
Posted myworld7
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排序算法——快速排序相关的知识,希望对你有一定的参考价值。
算法思想
快速排序的主要思想就是:分治+快速排序
分治思想
将原问题分解成若干规模更小但是结构和原问题相同的子问题。递归求解子问题,然后解出原问题。
快排算法思想
- 选择数组中第一个数作为基数,然后设置下标i=first,j=last
- 从数组后面找出比基数小的数调换到前面
- 然后从数组前面找出比基数大的数调换到后面
- 如此循环2-3步,直到i==j
结果为以基数分界,左边的数比全部比基数小,右边的数比基数大。结束这次排序。
然后,下次分别排序[first,i-1]和[i+1,last],使序列左边有序和右边有序
这是一个递归的过程,直到first > i-1或者i+1 > last 返回
这样就将原问题划分成两个与原问题相同的子问题,再次对这两个区间进行快速排序。
算法演示
还是以序列3,2,5,6,4,7,1为例
开始的时候以第一个数3为基数,3所处的位置就相当于一个坑,空出来
base = 3;i = 0;j = 6;
2 | 5 | 6 | 4 | 7 | 1 | |
---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 | 6 |
i | j |
从后往前找小于基数的的数,找到最后一个数1,于是将1填在位置0,位置6就被空出来了, i++向中间移位
1 | 2 | 5 | 6 | 4 | 7 | |
---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 | 6 |
i | j |
从前往后找大于基数的数,找到5,于是将5填在位置6,位置2就被空出,j--向中间移位
1 | 2 | 6 | 4 | 7 | 5 | |
---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 | 6 |
i | j |
然后又从后往前找,找小于基数的数,当j==i时,结束本次排序。
最后基数插入空出的位置2
1 | 2 | 3 | 6 | 4 | 7 | 5 |
---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 | 6 |
i?j |
可以发现,基数左边的数都小于基数,右边的数都大于基数。以基数分界,下次排序就分别排序列[first,i-1]和[i+1,last]即序列[1,2]和[6,4,7,5]
排序序列[1,2]
基数为0
i=0;j=1;
从后往前找,因为只有一个数且大于1,因此在i==j后,1仍旧插入位置0
本次排序结束
因为i-1=-1 小于本次排序中的first 0,所以本序列不在进行划分排序
排序序列[6,4,7,5]
base = 6; i = first ; j=last;
即i=3,j=6
4 | 7 | 5 | |
---|---|---|---|
3 | 4 | 5 | 6 |
i | j |
从后往前找小于6的数,找到5,将其填入位置0,位置6就空出来了。然后i++,向中间移位
5 | 4 | 7 | |
---|---|---|---|
3 | 4 | 5 | 6 |
i | j |
从前往后找大于6的数,找到7,于是将7填入位置6,位置5就空出,然后j--,向中间移位
5 | 4 | 7 | |
---|---|---|---|
3 | 4 | 5 | 6 |
i j |
因为i==j,所以结束本次排序,将6插入i所指的位置。
5 | 4 | 6 | 7 |
---|---|---|---|
3 | 4 | 5 | 6 |
i j |
此次继续排序[first,i-1]和[i+1,last]即[5,4]和[7]
因为i+1 == last 所以不在进行排序
排序[5,4]类似于排序前面的序列[1,2],只不过序列[5,4]排序后为[4,5]
最终序列变得有序
算法代码实现
//分治
void QuickSort(int a[],int first,int last)
{
if(first < last)
{
int i = AdjustArray(a,first,last);//以基数分界,对基数左边快排,对基数右边快排
QuickSort(a,first,i-1);
QuickSort(a,i+1,last);
}
}
//快速排序的代码(可以理解为挖坑填数)
int AdjustArray(int a[],int first,int last)
{
int i = first,j = last;
int m = a[first];//以第一个数为基数
while(i<j)
{
while(i<j && a[j] >= m)//从后往前找小于基数的数
j--;
if(i<j)
{
a[i] = a[j];//将a[j]填到a[i],a[j]变成一个坑
i++;
}
while(i<j && a[i] < m)//从前往后找比基数大的数
i++;
if(i<j)
{
a[j] = a[i];//将a[i]填到a[j],a[i]变成一个坑
j--;
}
}
a[i] = m;//退出时,i=j,将基数填入坑中
return i;
}
以上是关于排序算法——快速排序的主要内容,如果未能解决你的问题,请参考以下文章