排序算法-----快速排序(递归)

目录

前言

快速排序

 步骤原理

大致思路

流程

动态图

代码实现

算法分析

空间复杂度

时间复杂度

扫描二维码关注公众号,回复: 16666002 查看本文章

稳定性


前言

        今天我们开始学习排序算法中的快速排序算法,既然叫快速排序,那肯定是体现在快这方面,相较于前面所学习过的排序算法,快速排序是比这些算法的速度要快的,将来很多时候我们都会用到快速排序来去做排序的,下面就一起来学习吧!

快速排序

        快速排序(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指向的数字的位置,左边的都比这个数字要小,右边的都比这个数字要大,于是我们就可以去进入到递归,分别对左边和右边的数字进行以上步骤的递归,最后两边的数字都会被排好序。

动态图

 

代码实现

#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(nlog2​n)

稳定性

 俗话说得好:有得必有失。快速排序虽然排序速度快了很多,但是其缺牺牲了稳定性,当出现相同大小元素的时候,相同大小元素的相对位置会发生改变,每次递归都会发生变化,这就导致了快速排序的稳定性不好,这是因为快速排序改变了交换的规则,使用跳跃式交换,没有进行数字大小的一一比较,故快速排序是不稳定的,所以选择排序算法的时候要慎重选择,充分考虑到稳定性

好了,以上就是今天的全部内容了,我们下一期再见! 

分享一张壁纸: 

猜你喜欢

转载自blog.csdn.net/m0_73633088/article/details/132889441
今日推荐