快速排序【模板】

快速排序是一种高效的排序算法,采用分治法的策略,通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

快速排序的基本思想

快速排序的基本思想是选择一个基准元素(base),通常选择第一个或最后一个元素,然后对数组进行分区操作,使得:

  • 比基准元素小的元素都移到基准的左边

  • 比基准元素大的元素都移到基准的右边 这个过程称为一趟快速排序。

以下是按原理写的代码

#include <bits/stdc++.h>
using namespace std;
int n;
int a[100100] = {0},b[100100] = {0},c[100100] = {0},d[100100] = {0};
void wsort(int l,int r){
	if(l >= r){
		return ;
	}
	int k = rand() % (r - l + 1) + l,l1 = 0,l2 = 0,l3 = 0;
	for(int i = l;i <= r;i++){
		if(a[i] < a[k]){
			b[l1] = a[i];
			l1++;
		}else{
			if(a[i] == a[k]){
				c[l2] = a[i];
				l2++;
			}else{
				d[l3] = a[i];
				l3++;
			}
		}
	}
	for(int i = 0;i < l1;i++){
		a[l + i] = b[i];
	}
	for(int i = 0;i < l2;i++){
		a[l + l1 + i] = c[i];
	}
	for(int i = 0;i < l3;i++){
		a[l + l1 + l2 + i] = d[i];
	}
	wsort(l,l1 - 1 + l);
	wsort(l + l1 + l2,r);
}
int main(){
	srand(time(0));
	scanf("%d",&n);
	for(int i = 0;i < n;i++){
		scanf("%d",&a[i]);
	}
	wsort(0,n - 1);
	for(int i = 0;i < n;i++){
		printf("%d ",a[i]);
	}
	return 0;
}

代码功能概述

该代码实现了一个随机化的快速排序算法(Quicksort),用于对输入的整数数组进行排序。核心思路是通过随机选择基准值(pivot)将数组划分为三部分:小于基准、等于基准和大于基准的元素,再递归处理前两部分和后两部分。


关键变量与数据结构

a[100100]:存储待排序的原始数组,容量为100100。
b[100100]c[100100]d[100100]:临时数组,分别存储小于、等于和大于基准值的元素。
n:输入数组的长度。
wsort(l, r):递归排序函数,处理数组区间 [l, r]


核心算法逻辑

随机选择基准值
通过 k = rand() % (r - l + 1) + l 在区间 [l, r] 中随机选择一个下标 k,其对应的值 a[k] 作为基准值。

三路划分
遍历区间 [l, r],将元素分类到临时数组:

  • b[] 存储小于 a[k] 的元素。
  • c[] 存储等于 a[k] 的元素。
  • d[] 存储大于 a[k] 的元素。

合并与递归
将分类后的三部分按顺序写回原数组 a[]

  1. 先写入 b[](小于基准的部分)。
  2. 接着写入 c[](等于基准的部分)。
  3. 最后写入 d[](大于基准的部分)。
    递归调用 wsort 处理小于基准([l, l + l1 - 1])和大于基准([l + l1 + l2, r])的子区间。

主函数流程

  1. 初始化随机种子:srand(time(0))
  2. 输入数组长度 n 和数组元素 a[0..n-1]
  3. 调用 wsort(0, n-1) 排序。
  4. 输出排序后的数组。

代码特点与注意事项

随机化优化
通过随机选择基准值,避免最坏情况的时间复杂度退化(如数组已有序时普通快排的 $O(n^2)$ 复杂度)。

三路划分优势
处理重复元素时效率更高,避免重复元素导致的递归深度增加。

时空复杂度

  • 时间复杂度:平均 O(n log n),最坏 O(n^2)(极低概率)。
  • 空间复杂度:O(n)(临时数组占用)。

 

点个赞吧!!!求求了!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值