首页 > 其他分享 >AcWing 785. 快速排序

AcWing 785. 快速排序

时间:2023-12-04 11:22:19浏览次数:31  
标签:tmp 785 return int 基准 while 排序 AcWing

题面
给定你一个长度为 \(n\) 的整数数列。
请你使用快速排序对这个数列按照从小到大进行排序。
并将排好序的数列按顺序输出。

原题链接:785. 快速排序 - AcWing

需要注意的几个点:

  1. 左右哨兵的发动顺序;
  2. 相同元素的相对位置;
  3. 边界划分问题[1]
#include<bits/stdc++.h>
using namespace std;

const int N = 100005;

int n;
int a[N];

//啊哈算法P18
void quickSort(int l, int r) {
	//当待排序的子序列长度为0或1(即left>right)时停止
	if (l > r)
		return;
	int tmp = a[l];	//取当前数组区间首元素为基准数
	int i = l;
	int j = r;
	while (i != j) {
		//先从右往左找基准数右边第一个小于基准数的数
		//TIP1 - 顺序很重要:基准数左侧均小于基准数,而右侧均大于基准数
		//若先发动左指针找较大数,则会越过最终基准数应在的位置
		while (a[j] >= tmp && i < j)
			j--;
		//再从左往右找基准数左边第一个大于基准数的数
		//TIP2 - 判断条件中的“等于”很重要:
		//若不考虑相等情况,那么相同元素的顺序将会改变,破坏排序的稳定性
		while (a[i] <= tmp && i < j)
			i++;
		//若i与j指针未相遇,则交换i与j各自所指的数字
		if (i < j)
			swap(a[i], a[j]);
	}
	//此时i与j指针相遇,基准数归位
	a[l] = a[i];
	a[i] = tmp;
	//左右分别递归
	quickSort(l, i - 1);
	quickSort(i + 1, r);
}
//法二
void quickSort2(int l, int r) {
	if (l >= r)
		return;
	//始终取当前数组中位元素为基准数,无需根据比较结果将其移位
	int tmp = a[(l + r) >> 1];
	int i = l;
	int j = r; 
	while (i <= j) {
		//先从右往左找基准数右边第一个小于等于基准数的数
		while (a[j] > tmp)
			j--;
		//再从左往右找基准数左边第一个大于等于基准数的数
		while (a[i] < tmp)
			i++;
		//若i指针未越过j指针,则交换i与j,然后各自继续前进一步
		//TIP3 - 边界问题:若此处不为≤,则会造成无限划分问题(将n分成0和n)
		//原因:在数组递归到最终只有两个元素且有序的情况下,j会取到l-1
		if (i <= j)
			swap(a[i++], a[j--]);
	}
	quickSort2(l, j);
	quickSort2(i, r);
}

int main()
{
	cin >> n;
	for (int i = 0; i < n; i++)
		cin >> a[i];
	//quickSort(0, n - 1);
	quickSort2(0, n - 1);
	for (int i = 0; i < n; i++)
		cout << a[i] << " ";
	return 0;
}
//法三
void quick_sort(int l, int r)
{
    if(l==r)
        return q[l];
    LL x=q[(l+r)>>1];
    int i=l-1;
    int j=r+1;
    while(i<j){
    //为什么此处先发动左哨兵也没关系?
    //因为判定条件并非“两哨兵相遇”        
    while(q[++i]<x);
        while(q[--j]>x);
        if(i<j)
            swap(q[i],q[j]);
    }
    quick_sort(l, j);
    quick_sort(j+1, r);
}

  1. https://www.acwing.com/solution/content/16777/ ↩︎

标签:tmp,785,return,int,基准,while,排序,AcWing
From: https://www.cnblogs.com/haruhomu/p/17874520.html

相关文章

  • AcWing 4. 多重背包问题
    题面:有\(N\)件物品和一个容量是\(V\)的背包。第\(i\)件物品最多有\(s_i\)件,每件体积是\(v_i\),价值是\(w_i\)。求解将哪些物品装入背包,可使这些物品的体积总和不超过背包容量,且价值总和最大。输出最大价值。原题链接:4.多重背包问题I-AcWing多重背包实际上沿......
  • AcWing 5. 多重背包问题 II
    题面:有\(N\)件物品和一个容量是\(V\)的背包。第\(i\)件物品最多有\(s_i\)件,每件体积是\(v_i\),价值是\(w_i\)。求解将哪些物品装入背包,可使这些物品的体积总和不超过背包容量,且价值总和最大。输出最大价值。原题链接:5.多重背包问题II-AcWing先前的思路[1]:将......
  • AcWing 3. 完全背包问题
    题面:有\(N\)种物品和一个容量是\(V\)的背包,每种物品都有无限件可用。第\(i\)种物品的体积是\(v_i\),价值是\(w_i\)。求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。输出最大价值。原题链接:3.完全背包问题-AcWing根据01背包的思路扩......
  • AcWing 2. 01背包问题
    题面:有 \(N\) 件物品和一个容量是 \(V\) 的背包。每件物品只能使用一次。第 \(i\) 件物品的体积是 \(v_i\),价值是 \(w_i\)。求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。输出最大价值。原链接:2.01背包问题-AcWing有限集的最优问......
  • 详解十大经典排序算法(三):插入排序(Insertion Sort)
    算法原理每次从无序部分选择一个元素,将其插入到有序部分的正确位置,重复这个过程直至整个数组有序。算法描述插入排序是一种简单直观的排序算法,它的基本思想是将一个待排序的元素插入到已经排序好的序列中的适当位置,从而得到一个新的、长度加一的有序序列。插入排序的过程类似于整理......
  • Acwing第132场周赛
    AcWing5366.大小写转换#include<bits/stdc++.h>#definelsp<<1#definersp<<1|1#definePIIpair<int,int>#definelllonglong#definedbdouble#defineullunsignedlonglong#defineendl'\n'#defineioios::sync_with_......
  • 算法之快速排序2基准元素的选择
    一:概述基准元素,英文是pivot,在分治的过程中,基准元素为中心,把其他的元素移动到它的左右两边。二:具体说明最简单的方式就是选择数列的第1个元素。这种选择在绝大多数情况下是没有问题的。但是,假如有一个原本逆序的数列,期望排列成顺序数列,那会出现什么情况呢?整个数列被分成了两部分,每一......
  • C语言冒泡排序法
    引言冒泡排序是一种交换排序,它的基本思想是:两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止。冒泡的实现在细节上可以有很多种变化。最简单排序实现/*对顺序表L做交换排序*/voidBubbleSortO(SqList*L){ inti,j;for(i=1;i<L->length;i++) { fo......
  • 前缀和/差分——acwing算法基础课笔记
    个人笔记,欢迎补充,指正。一维前缀和对于数组:a[1],a[2],a[3]...a[n];其前缀和数组为s[i]=a[1]+a[2]+...+a[i];下标必须从1开始求前缀和1for(inti=1;i<n;++i)2s[i]=s[i-1]+a[i];s[0]需要定义为0作用求原数组里一段数(l,r)的和......
  • 链表为什么适合归并排序而不是快速排序?
    链表适合归并排序而不是快速排序的原因主要有以下几点:内存访问模式:快速排序的效率主要来源于引用的局部性,计算机硬件在这里得到了优化,因此访问彼此相邻的内存位置往往比访问分散在内存中的内存位置更快。然而,链表单元格经常分散在内存中,所以访问相邻的链表单元格没有局部性......