【任务目标】
将无序数组变为有序数组
【选择排序原理】
- 先从数组中选出一个最小的元素,将其与数组首元素交换位置
- 从剩下的n-1个元素中选出最小的元素,将其与数组的第二个元素交换位置
- 从剩下的n-2个元素中选出最小的元素,将其与数组的第三个元素交换位置
- 以此类推,直到剩下的元素个数为0
【选择排序原理概括】
通过循环,每次选出在当前的剩余元素中最小的元素,使得这些选出的元素构成有序数组
【代码实现】
using System;
namespace SelectionSort
{
class Program
{
static void Main(string[] args)
{
int[] A = new int[30];
Random ra = new Random();
for (int i = 0; i < 30; i++)
{
A[i] = ra.Next(200);
}
Program ps = new Program();
ps.SelectSort(A);
Console.WriteLine("排序结果:");
foreach (int a in A)
{
Console.Write(a + " ");
}
bool isSorted = true;
for (int i = 0; i < A.Length-1; i++)
{
if (A[i] > A[i + 1])
{
isSorted = false;
break;
}
}
Console.Write(isSorted);
Console.ReadKey();
}
public void SelectSort(int[] A)
{
for (int i = 0; i < A.Length-1; i++)//在第n-1次就可以结束循环
{
int index = i;
for (int j = i+1; j < A.Length; j++)
{
if (A[index] > A[j])//找出最小元素的索引
{
index = j;
}
}
if (index != i)//交换位置
{
int temp = A[i];
A[i] = A[index];
A[index] = temp;
}
}
}
}
}
【实现结果】
【考虑其他情况】
【元素已经有序或接近有序】例如,对A={0,1,2,3,4,5,6,7,8,9}和A={3,1,2,0,4,5,6,7,8,9},因为每次要选出最小的元素,所以不可避免地要将剩余的所有元素比较一次。选择排序在这种情况下,仍要较长的执行过程。
【元素完全逆序或混乱】例如,对A={9,8,7,6,5,4,3,2,1,0},同上,选出最小元素时不可避免地要将所有元素比较一次。坏的情况与好的情况都要较长的执行过程。
【有多个相同的元素】由于要交换位置,排序前后相同元素的相对次序会改变。
【选择排序改进】
按照选择排序的原理,我们也可以在每次选出最大的元素,将其放在数组的后端。进而,我们可以同时选出最小和最大的元素,分别放在数组的前端和后端。
(还有很多其他改进方向:怎么样更快选出最小的元素;怎么样使得排序前后相同元素的相对次序不改变等)
【改进代码实现】
public void SelectSort2(int[] A)
{
for (int i = 0; i < A.Length >> 1; i++)//考虑了元素个数为偶数、奇数的情况
{
int MaxIndex = i;
int MinIndex = i;
for (int j = i; j < (A.Length - i); j++)//找到最小、最大元素的位置
{
if (A[MinIndex] > A[j])
{
MinIndex = j;
}
if (A[MaxIndex] < A[j])
{
MaxIndex = j;
}
}
if (MaxIndex == i && MinIndex == A.Length - 1 - i)
{//特殊位置:最大的在最前面,最小的在最后面
swap(ref A[MaxIndex], ref A[MinIndex]);
}
else if (MaxIndex == i)//特殊位置:最大的在最前面,最小的在后面
{
swap(ref A[MaxIndex], ref A[A.Length - 1 - i]);
swap(ref A[MinIndex], ref A[i]);
}
else //(MinIndex == A.Length - 1 - i)特殊位置:最小的在最后面,最小的在前面
//和普通情况
{
swap(ref A[MinIndex], ref A[i]);
swap(ref A[MaxIndex], ref A[A.Length - 1 - i]);
}
}
}
//注意交换时用ref参数
public void swap(ref int a, ref int b)
{
int temp = a;
a = b;
b = temp;
}
【改进结果】
【选择排序和冒泡排序的区别】
- 冒泡排序将最大的元素逐渐后移,选择排序将最大的元素直接右移
- 每次循环时,冒泡排序会将大的元素逐渐后移,选择排序只会将最大的元素直接右移
- 排序后,冒泡排序不会改变相同元素的相对次序,选择排序会改变
【选择排序和插入排序的区别】
- 选择排序的排序在查找(选择)最小的元素时完成,插入排序在插入任意的元素时完成
- 排序后,插入排序不会改变相同元素的相对次序,选择排序会改变
【参考】
[1]邓俊辉.数据结构(C++语言版)第三版[M]
【相关链接】
版权声明:本文为enternalstar原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。