快速排序小结

一.hoare划分法

根据基准值,将数组划分成前后两部分,前面的部分值小于基准值,后面的值大于基准值。先从后往前找到第一个小于基准值的元素,然后从前向后找到第一个大于基准值的元素,交换这两个元素。如此进行下去,用start和end标记起始位置和结束位置,在遍历的时候更新start和end。划分结束之后start和end相等,都指向最后一个小于等于基准值的元素。因此最后一步需要将基准值和该元素交换,则完成了一次划分。
二.挖坑划分法

先保存基准值,从后往前找第一个小于基准值的元素,将其直接放入原先start处,然后从start往后找第一个大于基准值的元素,找到之后将其放入end处。这样start之前的元素始终小于等于基准值,end之后的元素始终大于等于基准值。当start等于end时,循环结束,此时start和end指向的时候最后一个小于等于基准值的元素。因此最后直接将基准值放入start或end中,划分完成。
三.前后指针划分法

定义一个pre指针始终指向最后一个小于等于基准值的元素,另一个指针cur遍历数组。当遇到小于等于基准值的元素时,需要更新++pre,且要交换pre和cur指向的元素。原因是cur和pre之间可能存在大于基准值的元素。最后交换最后一个小于等于基准值的元素和基准值,划分完成。
四.具体代码*

//三数取中法
int getMid(int* arr, int start, int end) {
	int mid = (start + end) / 2;
	if (arr[start] > arr[mid]) {
		int tmp = start;
		start = mid;
		mid = tmp;
	}
	if (arr[mid] > arr[end]) {
		int tmp = mid;
		mid = end;
		end = tmp;
	}

	return arr[start] < arr[mid] ? mid : start;
}


//hoare划分方法
int partion1(int* arr, int start, int end) {
	//取中间值作为基准值
	int mid = getMid(arr, start, end);
	//交换 mid 和 start
	Swap(arr, mid, start);
	//选取基准值
	int key = arr[start], keyPos = start;

	while (start < end) {
		//从后向前找第一个小于key的位置
		while (start < end && arr[end] >= key)
			end--;
		//从前往后找第一个大于key的位置
		while (start < end && arr[start] <= key)
			start++;
		//交换end和start处的元素
		Swap(arr, end, start);
	}
	//将基准值处和相遇位置处交换
	Swap(arr, end, keyPos);
	return end;
}
//挖坑划分法
int partion2(int* arr, int start, int end) {
	//取中间值作为基准值
	int mid = getMid(arr, start, end);
	//交换 mid 和 start
	Swap(arr, mid, start);

	int key = arr[start];
	while (start < end) {
		//从后往前找第一个小于key的位置
		while (start < end && arr[end] >= key)
			end--;
		//将元素填入坑中
		arr[start] = arr[end];
		//从前往后找第一个大于key的位置
		while (start < end && arr[start] <= key)
			start++;
		arr[end] = arr[start]; 
	}
	//将基准值填入坑中
	arr[start] = key;
	return start;
}
//前后指针划分法
int partion3(int* arr, int start, int end) {
	//取中间值作为基准值
	int mid = getMid(arr, start, end);
	//交换 mid 和 start
	Swap(arr, mid, start);

	int key = arr[start];
	//最后一个小于基准值的位置
	int pre = start;
	//下一个小于基准值的位置
	int cur = start + 1;
	while (cur <= end) {
		//新发现的小数据和尾指针指向的位置不连续,则中间含有大于基准值的数据,故进行交换
		//大数据向后移动,小数据向前移动
		if (arr[cur] < key && ++pre != cur)
			Swap(arr, pre, cur);
		++cur;
	}
	Swap(arr, pre, start);
	return pre;
}
void quickSort(int* arr, int start, int end) {
	if (start >= end)
		return;

	//根据基准值划分区间
	int keyPos = partion3(arr, start, end);
	//左右区间分别排序
	quickSort(arr, 0, keyPos - 1);
	quickSort(arr, keyPos + 1, end);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值