快速排序(Quick Sort)简介和代码实现

算法复杂度

时间复杂度:O(nlogn)
空间复杂度:T(n)

算法策略

分而治之

基本逻辑

取数组内任意一数,将数组内所有小于它的数移到左边,所有大于它的数移到右边,将左右两边分别视为新的数组。
对新的两个数组,分别重复上一步骤,直到新的数组只含1个元素,整个数组变得有序。

图解

取数组中第一个数为基准。
从右往左找到第一个小于基准的数(此处第一步找到的是6)。
从左往右找到第一个大于基准的数(9)。
在这里插入图片描述
交换6和9。
在这里插入图片描述
继续从刚才的两个位置,向中间找到第二组数,交换位置,直到i=j。
在这里插入图片描述
此时,i和j都会停在小于基准的数中,最右边的那一个数的位置。(如果在从两边向中间找数的这一步,先从左找大数、再从右找小数,则会停在大于基准的数中最左边的那一个数的位置,即19这个位置。具体由代码的写法决定。)
在这里插入图片描述
这时,只需要交换自始自终留在第一位的基准数,和停止位置的数(7和5),即可完成本轮划分。
在这里插入图片描述
之后,持续对左侧和右侧分别进行新的划分即可。

代码实现

void quick_sort(int arr[], int len) {
	int beginAddress = 0;
	int endAddress = len - 1;
	devide_arr_quick(arr, beginAddress, endAddress);

	for (int i = 0; i < 9; i++) {
		std::cout << arr[i] << " ";
	}
	std::cout << std::endl;
}

void devide_arr_quick(int arr[], int beginAddress, int endAddress) {
	if (beginAddress >= endAddress) {
		return;
	}
	int left = beginAddress;
	int right = endAddress;
	int middle = arr[beginAddress];

	while (left < right) {
		while (arr[right] >= middle && left < right) {
			//从右到左,跳过大于/等于middle的数字,找到第一个小于middle的
			//middle本身还留在第一位
			//注意,要保证left小于right,一是防止内存溢出,二是减少运算量
			right--;
		}
		//要先找右边再找左边,这样最后left和right都会停在小于middlle的最右边那个数上,
		//与一直在最左边的middle数交换位置,即可结束本轮排序。
		//如果先左再右,则会停在大于middle的最左边的数上,
		//此时,则需要将middle与(left-1)交换
		while (arr[left] <= middle && left < right) {
			//从左到右,跳过小于/等于middle的数字,找到第一个大于middle的
			left++;
		}
		//交换left和right位置上的数
		int temp = arr[left];
		arr[left] = arr[right];
		arr[right] = temp;

		//不需要手动加减left和right,直接进入下一轮循环
		//left++; (X)
		//right--; (X)
	}
	//左右划分完毕,交换放在最左边的middle和小于middle的数中位于最右边的那个
	arr[beginAddress] = arr[left];
	arr[left] = middle;

	//对左右两边分别进行新的划分
	devide_arr_quick(arr, beginAddress, left - 1);
	devide_arr_quick(arr, left + 1, endAddress);

}

参考资料

快速排序详解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值