C++学习笔记#24(2021.6.10)

237 阅读1分钟

快速排序

看了y神的快速排序,可是说是非常的优雅而简洁了,显得之前学过的书本上的非常臃肿,而且acwing的oj非常看重时间效率,稍不留神就超时了,还学到一句话叫做边界问题背模板

直接上代码:

#include<iostream>
using namespace std;
const int N = 100010;
int q[N], t;
void QuickSort(int q[], int l, int r){
	if(l >= r) return;
	int i = l - 1, j = r + 1, x = q[(l + r) / 2];
	while (i < j) {
		do i++; while (q[i] < x);
		do j--; while (q[j] > x);
		if (i < j) swap(q[i], q[j]);
	}
	QuickSort(q, l, j);
	QuickSort(q, j + 1, r);
}

int main() {
	scanf("%d", &t);
	for (int i = 0; i < t; i++) {
		scanf("%d", &q[i]);
	}
	QuickSort(q, 0, t - 1);
	for (int i = 0; i < t; i++) {
		printf("%d ", q[i]);
	}
	return 0;
}

代码短小精悍,但是我自己按自己理解写的代码总是超时,比较之后发现

int i = l - 1, j = r + 1, x = q[l];

中的

x = q[l];

这一行出了问题,因为我之前学的快排总是把第一个元素当做pivot,但是测试用例中如果有已经有序的用例的话,时间复杂度就会变成n方,所以要用

x = q[(l + r) / 2];

或者

x = q[(l + r) >> 1];

位运算符相当于向下取整,如果以i为分界点的话就是

x = q[(l + r + 1) >> 1];

新知识点: 数学上可以证明,a/b向上取整,相当于 (a+b-1)/b向下取整,方便代码实现。

ps:挑战模式针不戳,帮同学们避免了眼高手低的问题,嘻嘻