目录
前言
今天我们开始学习排序算法中的快速排序算法,既然叫快速排序,那肯定是体现在快这方面,相较于前面所学习过的排序算法,快速排序是比这些算法的速度要快的,将来很多时候我们都会用到快速排序来去做排序的,下面就一起来学习吧!
快速排序
快速排序(Quicksort),计算机科学词汇,适用领域Pascal,C++等语言,是对冒泡排序算法的一种改进。
快速排序采用的是分治思想,即在一个无序的序列中选取一个任意的基准元素pivot,利用pivot将待排序的序列分成两部分,前面部分元素均小于或等于基准元素,后面部分均大于或等于基准元素,然后采用递归的方法分别对前后两部分重复上述操作,直到将无序序列排列成有序序列。
步骤原理
大致思路
快速排序算法通过多次比较和交换来实现排序,其排序流程如下:
1、首先设定一个分界值,通过该分界值将数组分成左右两部分。
2、将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于分界值,而右边部分中各元素都大于或等于分界值。
3、然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
4、重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。
流程
现在给定一个数组初始 [25,24,6,65,11,43,22,51],然后进行快速排序
第一步,先选取一个参考数字temp,一般选取第一个即temp=25,然后标记最左边和最右边数字的位置分别为i, j
25 24 6 64 11 43 22 51
i j
temp
第二步,先去向左移动j 的位置,当j指向的数字小于temp时候,就停止移动,然后开始向右移动i
当i 移动到比temp要大的数字时,停止移动,此时将i 和 j 指向的数字进行交换,如下所示:
25 24 6 64 11 43 22 51
temp i j
交换后:
25 24 6 22 11 43 65 51
temp i j
第三步,此时,开始接着移动 j,当j 移动到比temp要小的数字的时候,停止移动, 如下所示:
25 24 6 22 11 43 65 51
temp i j
然后开始移动i ,当i 移动到与j 相遇的位置时,i停止移动(如果i 移动到比temp要大的数字的时候就执行上面的第二步,i与j 进行数字交换)
25 24 6 22 11 43 65 51
temp i,j
第四步,此时,i与j指向的数字与temp指向的数字进行数字交换
11 24 6 22 25 43 65 51
temp i,j
这时候我们会发现,此时i和j指向的数字的位置,左边的都比这个数字要小,右边的都比这个数字要大,于是我们就可以去进入到递归,分别对左边和右边的数字进行以上步骤的递归,最后两边的数字都会被排好序。
动态图
代码实现
cpp
#include<stdio.h>
//快速排序---递归实现
void quick_sort(int* n, int left,int right) {
int i, j, temp;
i = left;
j = right;
if (i > j) {
return;
}
else {
temp = n[left];
while (i != j) {
while (n[j] >= temp && i < j)//先向左移动j
j--;
while (n[i] <= temp && i < j) //再向右移动i
i++;
if (i < j) {//此时对i和j指向的数字进行数字交换
int num = n[i];
n[i] = n[j];
n[j] = num;
}
}//当i和j相遇的时候就结束循环
//此时i与j相遇,就与temp交换
int new_temp = n[i];
n[i] = n[left];
n[left] = new_temp;
}
//最后左右边依次进入到递归
quick_sort(n, left, i - 1); //左边的数字都比temp要小
quick_sort(n, i + 1, right); //右边的数字都比temp要大
}
int main() {
int array[8] = { 25,24,6,65,11,43,22,51 };
printf("排序前:");
for (int i = 0; i < sizeof(array) / sizeof(int); i++) {
printf("%d ", array[i]);
}
printf("\n排序后:");
quick_sort(array, 0, sizeof(array) / sizeof(int)-1);
for (int i = 0; i < sizeof(array) / sizeof(int); i++) {
printf("%d ", array[i]);
}
}
//排序前:25 24 6 65 11 43 22 51
//排序后:6 11 22 24 25 43 51 65
算法分析
空间复杂度
快速排序算法没有涉及到空间的开辟,使用的空间是原数组空间,空间复杂度为O(1)
时间复杂度
快速排序之所以比较快,是因为与冒泡排序相比,每次的交换时跳跃式的,每次排序的时候设置一个基准点,将小于等于基准点的数全部放到基准点的左边,将大于等于基准点的数全部放到基准点的右边。这样整体交换次数和比较次数就少很多, 故排序速度就提高了许多,当然如果是最坏的情况下时间复杂度还是为O(n^2),其平均的时间复杂度为O(nlog2n)
稳定性
俗话说得好:有得必有失。快速排序虽然排序速度快了很多,但是其缺牺牲了稳定性,当出现相同大小元素的时候,相同大小元素的相对位置会发生改变,每次递归都会发生变化,这就导致了快速排序的稳定性不好,这是因为快速排序改变了交换的规则,使用跳跃式交换,没有进行数字大小的一一比较,故快速排序是不稳定的,所以选择排序算法的时候要慎重选择,充分考虑到稳定性
好了,以上就是今天的全部内容了,我们下一期再见!
分享一张壁纸: