我正在尝试理解冒泡排序算法的可能优化方法。我知道有更好的排序方法,但我只是好奇。
为了测试我使用std :: chrono的效率。程序对10000个长整数数组进行30次排序并打印平均排序时间。在每次迭代中随机选取数字(最多10000个)。这是代码,没有优化:
#include <iostream>
#include <ctime>
#include <chrono>
using namespace std;
int main() {
//bubble sort
srand(time(NULL));
chrono::time_point<chrono::steady_clock> start, end;
const int n = 10000;
int i,j, last, tests = 30,arr[n];
long long total = 0;
bool out;
while (tests-->0) {
for (i = 0; i < n; i++) {
arr[i] = rand() % 1000;
}
j = n;
start = chrono::high_resolution_clock::now();
while(1){
out = 0;
for (i = 0; i < j - 1; i++) {
if (arr[i + 1] < arr[i]) {
swap(arr[i + 1], arr[i]);
out = 1;
}
}
if (!out) {
break;
}
//j--;
}
end = chrono::high_resolution_clock::now();
total += chrono::duration_cast<chrono::nanoseconds>(end - start).count();
cout << "Remaining :"<<tests << endl;
}
cout << "Average :" << total / static_cast<double>(30)/1000000000<<" seconds"; // tests(30) + nanosec -> sec
cin.sync();
cin.ignore();
return 0;
}
平均排序时间为0.17秒。
如果我取消注释第47行(j--;)以避免比较已经排序的数字,我得到0.12排序时间,这是可以理解的。
如果我记得发生交换的最后一个位置,我知道在该索引之后,元素被排序,因此可以在进一步的迭代中排序到该位置。在这篇文章的第二部分中更好地解释了:https://stackoverflow.com/a/16196115/1967496。 这是实现新的可能优化的代码:
#include <iostream>
#include <ctime>
#include <chrono>
using namespace std;
int main() {
//bubble sort
srand(time(NULL));
chrono::time_point<chrono::steady_clock> start, end;
const int n = 10000;
int i,j, last, tests = 30,arr[n];
long long total = 0;
bool out;
while (tests-->0) {
for (i = 0; i < n; i++) {
arr[i] = rand() % 1000;
}
j = n;
start = chrono::high_resolution_clock::now();
while(1){
out = 0;
for (i = 0; i < j - 1; i++) {
if (arr[i + 1] < arr[i]) {
swap(arr[i + 1], arr[i]);
out = 1;
last = i;
}
}
if (!out) {
break;
}
j = last + 1;
}
end = chrono::high_resolution_clock::now();
total += chrono::duration_cast<chrono::nanoseconds>(end - start).count();
cout << "Remaining :"<<tests << endl;
}
cout << "Average :" << total / static_cast<double>(30)/1000000000<<" seconds"; // tests(30) + nanosec -> sec
cin.sync();
cin.ignore();
return 0;
}
注意第40和48行。问题出现了:现在平均时间约为0.17秒。 我的代码中有问题,或者我错过了什么?
更新
我用10倍的数字进行排序,现在得到以下结果: 没有优化:19.3秒 第一次优化(j--):14.5秒 第二(假设)优化(j =最后+ 1):17.4秒;
根据我的理解,第二种方法在任何情况下都应该优于第一种方法,但数字会说明其他方法。
答案 0 :(得分:1)
嗯......问题在于这个问题可能没有正确或错误的答案。
首先,当你只比较10000个元素时,你无法真正称它为效率测试。尝试比较更多的元素 - 可能是500000(尽管你可能需要为此动态地分配一个数组)。
其次,它可能是编译器。编译器经常尝试优化事物,以便程序执行更顺畅,更快。