数据结构与算法 ——快速排序

快速排序

一、概念

基础概念:快速排序,听这个名字就能想到它排序速度比较快方法,是一种分治思想。
所谓分治,就是指以一个数为基准,将序列中的其他数往它两边“扔”。以从小到大排序为例,比它小的都“扔”到它的左边,比它大的都“扔”到它的右边,然后左右两边再分别重复这个操作,不停地分,直至分到每一个分区的基准数的左边或者右边都只剩一个数为止。这时排序也就完成了。

例子:35,22,17,-20,48,99,46

通俗理解

  1. 选定一个数作为比较数key(基数),比key小的放左边,比key大的放右边。
    选定第一个数:35。 第一趟排序后:-20,22,17,35,48,99,46

  2. 这个时候key的左边都比key小,但还不是有序。就再次对key的左半部分执行1操作
    (下标是:0~3的元素,也就是 -20,22,17 这三个元素,再这三个数中选定一个key,比key小的放左边,比key大的放右边)
    排序后:-20,17,22,35,48,99,46

  3. 35 右边的(48,99,46)三个数,执行相同操作

完成排序:-20,17,22,35,46,48,99

二、代码及过程

/**
*
*快速排序
*Date: 2019/4/12
*
***/
#include <stdio.h>

// 快速排序
void quickSort(int *a, int low, int high){ // low是头指针,high是尾指针
	int i = low;
	int j = high;
	int key = a[low]; // 选定基数
	
	if(low >= high){ //说明已经排序完成
		return ;
	}

	while(low < high){	//这层循环每结束一次,就代表完成了一轮排序
		// 注意:这里的a[high]必须是“大于等于>=”key,否则遇到与基数相等的数将陷入死循环
		while(low < high && a[high] >= key){ // 从最右端开始,找出比key小的值
			--high;
		}

		if(a[high] < key){ // 直接覆盖,不用交换位置
			a[low] = a[high];
			++low;
		}

		while(low < high && a[low] <= key){ // 从最左端开始,找出比key大的值
			++low;
		}

		if(a[low] > key){ // 直接覆盖,不用交换位置
			a[high] = a[low];
			--high;
		}
	}
	a[low] = key;	// 第一轮排序完毕,当前位置就是key的位置(左边都是小于key,右边都是大于key)
	quickSort(a,i,low-1);	//递归调用(排序key左边的子序列)
	quickSort(a,low+1,j);
}

// 遍历数组
void show(int *a,int n){
	for(int i = 0; i < n; i++){
		printf("%5d",a[i]);
	}
}


void main(){
	int a[] = {35,22,17,-20,48,99,46};
	int n = sizeof(a) / sizeof(a[0]);	// 数组长度
	printf("原数组:\n");
	show(a,n);
	quickSort(a,0,n-1);
	printf("\n排序后的数组:\n");
	show(a,n);
	printf("\n");
}

三、复杂度

平均时间复杂度: O(nlogn)
空间复杂度: O(nlogn)

四、分析总结

最优情况:
如果待排序列是“升序有序”,如:1,2,3,4,5,6,7
那么,快速排序为最优情况

最糟糕情况:
如果待排序列是“降序有序”,如:7,6,5,4,3,2,1
那么,快速排序为退化为冒泡排序。

猜你喜欢

转载自blog.csdn.net/weixin_43725997/article/details/89240060