题目
给定你一个长度为 n 的整数数列。
请你使用快速排序对这个数列按照从小到大进行排序。
并将排好序的数列按顺序输出。
输入格式
输入共两行,第一行包含整数 n。
第二行包含 n 个整数(所有整数均在 1∼10e9 范围内),表示整个数列。
输出格式
输出共一行,包含 n 个整数,表示排好序的数列。
数据范围
1≤n≤100000
输入样例:
5
3 1 2 4 5
输出样例:
1 2 3 4 5
思路
使用快排模版
代码
#include <bits/stdc++.h>
using namespace std;
//const int Max = 10e9+10;
void QuickSort (int *a ,int l, int r){
if(l >= r) return; //递归终止条件
int i = l-1 ,j = r+1 ,x = a[ (l+r) >> 1 ];
while(i < j){
do i++ ; while( a[i] < x);
do j-- ; while( a[j] > x);
//不能设为">=“,不能用while
if( i < j ) swap(a[i], a[j]);
}
QuickSort(a, l, j);
QuickSort(a, j+1, r);
}
int main(){
int n;
scanf("%d", &n);//数组个数
int a[n+1];
for(int i = 0; i < n; i++){
scanf("%d", &a[i] );
}//输入数组
QuickSort(a, 0, n-1); //调用函数进行快排
for(int i = 0; i < n; i++){
printf("%d", a[i] );
if(i != n-1) printf(" ");
}//输出数组
return 0;
}
部分代码分析
1. 使用 do····while,而不是用 while
while(i < j){
do i++ ; while( a[i] < x);
do j-- ; while( a[j] > x);
if( i < j ) swap(a[i], a[j]);
}
while(i < j){
while( a[i] < x) i++ ;
while( a[j] > x) j--;
if( i < j ) swap(a[i], a[j]);
}
两者的不同点在于do····while是先执行,再判断-->等价于前置运算。
do i++; while(q[i] < x);
do j--; while(q[j] > x);
//等价于
while(q[++i] < x);
while(q[--j] > x);
而while是先判断再执行,i 指针指向不小于 x的数会停下来,而 j 指针指向不大于x数会停下来,来进行交换后再判断。
即此时的 a[ i ] >= x , a [ j ] <= x;
交换后的 a [ i ] <= x , a[ j ] >= x , 对于 do···while 直接 i ++ ; j ++;,而 while 要先判断,若a [i ] < x
可以 i ++; 若 a [i ] == x ,就不能 i ++;若( a [ i ] == x && a [ j ] == x ),就导致 一直 停滞,死循环。
那能不能 将 while 中的判断条件中的 “ < ” 改为 "<=" ( a[ i ] <= x )
❌
若选取的x
是数组里最大的数,序列中所有的数都满足q[i] <= x
,会导致i
会一直++
发生越界都不会停下来。
若选取的x
是数组里最小的数,同理q[j] >= x
恒成立,j
会一直--
发生越界。