选择排序的基本思想:每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完 。
第一种实现方法:
void SelectSort(int* arr, int n)
{
for (int j = 0;j < n - 1;j++)
{
int mini = n - 1;
int begin = j;
for (int i = begin;i < n - 1;i++)
{
if (arr[mini] > arr[i])
mini = i;
}
int tmp = arr[mini];
arr[mini] = arr[begin];
arr[begin] = tmp;
}
}
int main()
{
int a[] = { 8,5,7,8,9,0,9,3};
SelectSort(a, sizeof(a) / sizeof(a[0]));
for (auto e : a)
{
cout << e << " ";
};
return 0;
}
第二种方法:
如果要将一数组排为升序,将数组第一个元素的下标用begin记录,数组的第二个元素用end记录;遍历第一遍数组将数组中的最大值的下标用maxi记录,将数组的最小值的下标用mini记录;第一遍遍历数组结束后将此时数组的最大值与下标为end元素的值交换,数组最小值与下标为begin元素的值交换,然后--begin ++end,如此循环,指导begin<=end时结束。
编译结果情况1,此时的待排序数组是:8,5,7,8,9,0,9,3 可以看到运行结果显然不是我们所想要的。
void swap(int& a, int& b)
{
int tmp = a;
a = b;
b = tmp;
}
void SelectSort(int* a, int n)
{
int begin = 0;
int end = n - 1;
while (begin < end)
{
int maxi = end, mini = begin;
for (int i = begin;i <= end;i++)
{
if (a[maxi] < a[i])
maxi = i;
if (a[mini] > a[i])
mini = i;
}
swap(a[begin], a[mini]);
swap(a[end], a[maxi]);
--end;
++begin;
}
}
int main()
{
int a[] = { 8,5,7,8,9,0,9,3};
SelectSort(a, sizeof(a) / sizeof(a[0]));
for (auto e : a)
{
cout << e << " ";
};
return 0;
}
情况2:但是当待排序数组是 8,5,7,8,0,9,9,3时
这是因为第2种情况中的待排序数组进行第四次循环时,出现了交换两次的问题,如下:
因此我们需要注意当end-begin=1时的情况,接下来对代码进行优化:
void SelectSort(int* a, int n)
{
int begin = 0;
int end = n - 1;
while (begin < end)
{
int maxi = end, mini = begin;
for (int i = begin;i <= end;i++)
{
if (a[maxi] < a[i])
maxi = i;
if (a[mini] > a[i])
mini = i;
}
swap(a[begin], a[mini]);
if(begin+1!=end)//或者是if(end - begin > 1)
swap(a[end], a[maxi]);
--end;
++begin;
}
}
int main()
{
int a[] = { 8,5,7,8,0,9,9 ,3 };
SelectSort(a, sizeof(a) / sizeof(a[0]));
for (auto e : a)
{
cout << e << " ";
};
return 0;
}