我一直在尝试编写自己的选择排序算法,并且已经在随机生成的大小为10000,50000和100000的数组上进行测试。我的算法工作正常,但我试图让它尽快运行。在我的机器上,测试分别需要大约0.45秒,1.88秒和11.77秒。有没有办法改进我的算法,所以我可以让它运行得更快?
void SelectionSort(int array[], int len){
int temp,i,j,min,minpos;
for(j=0;j<len;j++){
minpos=j;
for(i=j+1;i<len;i++){
if(array[minpos]>array[i]){
minpos=i;
}
}
temp=array[j];
array[j]=array[minpos];
array[minpos]=temp;
}
}
答案 0 :(得分:0)
如果一个数组只包含两个元素,那么由于外部循环的这种情况,它不会被排序
for(j=0;j<len-2;j++){
^^^^^^^
我认为如果在交换数组元素之前你会检查当前元素和最小元素是否相同,你可以提高效率。
所以我想建议以下实现
void SelectionSort( int a[], size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
size_t min = i;;
for ( size_t j = i + 1; j < n; j++ )
{
if ( a[j] < a[min] ) min = j;
}
if ( i != min )
{
int tmp = a[i];
a[i] = a[min];
a[min] = tmp;
}
}
}
答案 1 :(得分:0)
没有什么可以“算法明智”来改善排序代码的运行时间。选择排序就像它获得的一样简单。
虽然您可以稍微优化代码。 我能想到的一个简单的改变是 -
而不是 -
if(array[minpos]>array[i]){
minpos=i;
}
DO
int val = array[i];
if(minval>val){
minpos=i;
minval=val;
}
用于交换
array[minpos] = array[j];
array[j] = minval;
我试图做的是尽量减少内存访问次数。您重复访问了array [minpos],这可能会导致缓存未命中。将其复制到一个单独的变量中,允许将其提升为一个保存取消引用的寄存器。
最后,您可以让编译器尽可能地进行优化。
尝试在Microsoft C编译器上的gcc / clang和/ O2上传递-O3标志。
我觉得与-O3交流可以给你最快的执行时间。
答案 2 :(得分:0)
可以对您的代码进行一些改进。每个数字都将在排序数组中自行交换,而不是被忽略。
例如:
如果给你一个数组[4, 5, 20, 30, 40]
在您给定的代码中:
void SelectionSort(int array[], int len){
int temp,i,j,min,minpos;
for(j=0;j<len;j++){
minpos=j;
for(i=j+1;i<len;i++){
if(array[minpos]>array[i]){
minpos=i;
}
}
temp=array[j];
array[j]=array[minpos];
array[minpos]=temp;
}
minpos永远不会改变,因此它会自行交换。您可以将交换置于if条件中,而不是这样做,并创建另一个名为swapped的变量,当交换发生时,该变量将像交换机一样。
因此:
void SelectionSort(int array[], int len)
{
int temp, i, j, minpos, swapped;
swapped = 0;
for(j=0; j<len; j++)
{
minpos=j;
for(i=j+1; i<len; i++)
{
if(array[minpos] > array[i]){
minpos=i;
swapped=1;
}
}
if (swapped == 1)
{
temp=array[j];
array[j]=array[minpos];
array[minpos]=temp;
swapped = 0;
}
}
}
另外,如果你做j&lt; len - 1在你的第一个for循环中,这将使你免于最后比较最后一个数字。
我还想指出你有一个名为min的变量,你声明但不使用。
对于大小为20000,40000和100000的大型数据集,我个人不会使用选择排序,因为平均情况和更糟糕的情况是二次O(n ^ 2)时间,与堆或合并相比较慢排序
很抱歉,代码中突出显示的部分看起来有些不可思议。