冒泡排序不做任何优化:
#include
#include
#include
using namespace std;
void sort(vector& nums){
int size = nums.size();
for(int i = size - 1; i > 0; i--){
for(int j = 0; j < i; j++){
if(nums[j] > nums[j + 1]){
swap(nums[j], nums[j + 1]);
}
}
}
}
int main(){
int n;
cin >> n;
vector nums(n, 0);
for(int i = 0; i < n; i++){
cin >> nums[i];
}
sort(nums);
for(int i = 0; i < n; i++){
if(i == n - 1)
cout << nums[i];
else
cout << nums[i] << " ";
}
}
有两个点超时了,做一点优化看看,增加一个标志,当没有发生交换时,就说明数据已经有序,可以停止了。
依旧超时。在加一点优化,每次循环判断最后一次交换的位置,下次交换到上一轮最后一次交换的位置即可。
void sort(vector& nums){
int size = nums.size();
int lastSwap = size - 1;
while(lastSwap > 0){
bool flag = false;
int lastTmp = lastSwap;
for(int j = 0; j < lastSwap; j++){
if(nums[j] > nums[j + 1]){
flag = true;
swap(nums[j], nums[j + 1]);
lastTmp = j;
}
}
if(!flag)
break;
lastSwap = lastTmp;
}
}
还是超时,冒泡排序时间复杂度为O(n^2),可能是太高了,再试试其他几个排序方法。
void sort(vector& nums){
int size = nums.size();
for(int i = 1; i < size; i++){
int tmpNum = nums[i];
int tmpIndex = i - 1;
while(tmpIndex >= 0 && nums[tmpIndex] > tmpNum){
nums[tmpIndex + 1] = nums[tmpIndex];
tmpIndex--;
}
nums[tmpIndex + 1] = tmpNum;
}
}
插入排序时间复杂度也是O(N^2),但是要比冒泡排序快一些。
原始版本
void sort(vector& nums){
int size= nums.size();
for(int i = 0; i < size; i++){
int min = i;
int minNum = nums[i];
for(int j = i + 1; j < size; j++){
if(nums[j] < minNum){
minNum = nums[j];
min = j;
}
}
swap(nums[i], nums[min]);
}
}
用时都很长,优化一下。在一次循环中找最大值和最小值,这样外循环次数可以减少一半。
void sort(vector& nums){
int size = nums.size();
int halfSize = size >> 1;
int minIndex, minNum, maxIndex, maxNum;
for(int i = 0; i < halfSize; i++){
minIndex = maxIndex = i;
minNum = maxNum = nums[i];
for(int j = i + 1; j < size - i; j++){
if(nums[j] < minNum){
minNum = nums[j];
minIndex = j;
}
if(nums[j] > maxNum){
maxNum = nums[j];
maxIndex = j;
}
}
if(maxIndex == minIndex)
break;
swap(nums[i], nums[minIndex]);
if(maxIndex == i){
maxIndex = minIndex;
}
swap(nums[maxIndex], nums[size - 1 - i]);
}
}
比上次的好了一些,但是选择排序总体上不如插入排序。
使用了Sedgewich增量序列,因为题目中给的最大元素数量是10^5个,所以手动生成增量序列,然后使用希尔排序。
void sort(vector& nums){
int Sedgewich[] = {64769, 36289, 16001, 8929, 3905, 2161, 929,505,209, 109, 41,19, 5,1, 0};
int size = nums.size();
int sIndex = 0;
for(; Sedgewich[sIndex] >= size; sIndex++);
for(int d = Sedgewich[sIndex]; d > 0; d = Sedgewich[++sIndex]){
for(int i = d; i < size; i++){
int tmpNum = nums[i];
int preIndex = i - d;
while(preIndex >= 0 && tmpNum < nums[preIndex]){
nums[preIndex + d] = nums[preIndex];
preIndex -= d;
}
nums[preIndex + d] = tmpNum;
}
}
}
用时缩短了好多。
接下来的排序算法时间复杂度都是O(NlogN)的。
void PercDown(vector& nums, int p, int size){
int parentIndex, childIndex;
int tmpNum = nums[p];
for(parentIndex = p; (parentIndex << 1) + 1 < size; parentIndex = childIndex){
childIndex = (parentIndex << 1) + 1;
if(childIndex < size - 1 && nums[childIndex] < nums[childIndex + 1])
childIndex++;
if(nums[childIndex] > tmpNum){
nums[parentIndex] = nums[childIndex];
}
else
break;
}
nums[parentIndex] = tmpNum;
}
void sort(vector& nums){
int i;
int size = nums.size();
for(i = (size >> 1) - 1; i >= 0; i--){
PercDown(nums, i, size);
}
for(i = size - 1; i > 0; i--){
swap(nums[i], nums[0]);
PercDown(nums, 0, i);
}
}
int getMiddle(vector& nums, int start, int end){
int baseNumIndex = start + rand() % (end - start + 1);
if(end != baseNumIndex)
swap(nums[end], nums[baseNumIndex]);
int baseNumber = nums[end];
int i = start;
for(int j = start; j < end; j++){
if(nums[j] < baseNumber){
swap(nums[j], nums[i]);
i++;
}
}
swap(nums[i], nums[end]);
return i;
}
void quickSort(vector& nums, int start, int end){
if(start >= end)
return;
int middle = getMiddle(nums, start, end);
quickSort(nums, start, middle - 1);
quickSort(nums, middle + 1, end);
}
void sort(vector& nums){
quickSort(nums, 0, nums.size() - 1);
}
void merge(vector& nums, int start, int end, int middle){
int index1 = start;
int index2 = middle + 1;
vector tmp(end - start + 1, 0);
int tmpIndex = 0;
while(index1 <= middle && index2 <= end){
int num1 = nums[index1];
int num2 = nums[index2];
int take = num1 < num2;
tmp[tmpIndex++] = take ? num1 : num2;
index1 += take;
index2 += 1-take;
}
while(index1 <= middle){
tmp[tmpIndex++] = nums[index1++];
}
while(index2 <= end){
tmp[tmpIndex++] = nums[index2++];
}
int size = tmp.size();
for(int i = 0; i < size; i++){
nums[start + i] = tmp[i];
}
}
void merge_sort(vector& nums, int start, int end){
if(start >= end)
return;
int middle = (start + end) >> 1;
merge_sort(nums, start, middle);
merge_sort(nums, middle + 1, end);
merge(nums,start, end, middle);
}
void sort(vector& nums){
merge_sort(nums, 0, nums.size() - 1);
}