快排【每日一练】

1. 思想

  1. 找出数组中某个元素作为轴值,并把它放到数组右端
  2. 利用双指针,将数组左边全部变成 < arr[end],右边变成 >= arr[end]
  3. 记得把轴值放回分界点
  4. 递归调用快排,处理左边和右边的子数组

1.1 优化

  • 如果数组 size 小于一定值,可以直接用插入排序

2. 算法代码

  • 头文件见附录
/**
 * @brief 插入排序
 * [begin, end]
*/
template <typename T>
void insert_sort(vector<T>& arr, size_t begin, size_t end){
	if(begin>=end){
		return;
	}

	for(size_t i=begin; i<=end; ++i){
		// 从 i 一直向前交换,直到遇到边界或者前一个正序的情况
		for(size_t j=i; j>begin && arr[j]<arr[j-1]; --j){
			swap(arr[j-1], arr[j]);
		}
	}
}

/**
 * @brief 快排
 * [begin, end]
 * 最差情况:当数组元素完全一样,每次只能完成 1 个元素的排序,需要 O(n^2)
 * */
template <typename T>
void quick_sort(std::vector<T> &array, size_t begin, size_t end){
	if(begin>=end){
		return;
	}
	if(end-begin<=10){
		insert_sort(array, begin, end);
		return;
	}
	size_t idx = begin + ((end-begin)>>1);
	size_t left = begin, right = end;
	
	// 将选定的轴值放在最右,作为哨兵
	swap(array[idx], array[end]);
	// 将数组分为左边小于轴值,右边大于等于轴值 
	while(left < right){
		while(left<right && array[left]<array[end]){
			++left;
		}
		while(left<right && array[right]>=array[end]){
			--right;
		}
		std::swap(array[left], array[right]);
	}
	std::swap(array[left], array[end]);
	// 特别注意,size_t 情况下要避免 i==0 时减1 
	if(left>0)
		quick_sort(array, begin, left-1);
	quick_sort(array, left+1, end);
}
  • 注意:
    1. size_t 变量使用减法的时候要小心下溢出,跟有符号整型计算的时候要小心有符号的转换(有符号自动转为无符号)
  • 不足:
    1. 如果数组的元素全部相同,这个快排的复杂度会变成 O ( n 2 ) O(n^2) O(n2),要优化请看 leetcode 的题解

3. 附录

#include <vector>
using std::vector;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值