排序算法

选择排序

Posted by Liangjf on April 9, 2018

排序算法之选择排序

1.选择排序介绍

选择排序分为三种,直接选择排序、树形选择排序、堆排序。直接选择排序和堆排序是不稳定排序,树形选择排序是稳定排序。在这里介绍的是直接选择排序。其他的后面再分析。

直接选择排序算法思想:第一趟从n个元素的数据序列中选出关键字最小/大的元素并放在最前/后位置,下一趟从n-1个元素中选出最小/大的元素并放在最前/后位置。以此类推,经过n-1趟完成排序。

2.选择排序算法分析

直接选择排序的最好时间复杂度和最差时间复杂度都是O(n²),因为即使数组一开始就是正序的,也需要将两重循环进行完,平均时间复杂度也是O(n²)。空间复杂度为O(1),因为不占用多余的空间。直接选择排序是一种原地排序(In-place sort)并且定(stable sort)的排序算法,优点是实现简单,占用空间小,缺点是效率低,时间复杂度高,对于大规模的数据耗时长。

算法步骤:

  • 第1趟,在待排序记录r[1]~r[n]中选出最小的记录,将它与r[1]交换;
  • 第2趟,在待排序记录r[2]~r[n]中选出最小的记录,将它与r[2]交换;
  • 以此类推,第i趟在待排序记录r[i]~r[n]中选出最小的记录,将它与r[i]交换,使有序序列不断增长直到全部排序完毕

3.选择排序算法从实现到优化

V1.0

template <typename T>
void SelectionSort2(T a[], int len)
{
    for(int i = 0; i < len; i++) {
        int MinIndex = i;
        for(int j = i+1; j < len; j++) {
            if(a[MinIndex] < a[j]) {
                MinIndex = j;
            }
        }
        swap(a[MinIndex], a[i]);
    }
}

4.选择排序多种场景下的测试

int main() {
	int N = 20000;

	//稀疏数组,随机性大
	int *arr1 = SortTestHelper::CreateRandomArray(N, 0, 1000000);
	SortTestHelper::testSort("SelectionSort", SelectSortFunc::SelectionSort2, arr1, N);

	//近乎有序
	int *arr2 = SortTestHelper::CreateRandomArray(N, 0, 100);
	SortTestHelper::testSort("SelectionSort", SelectSortFunc::SelectionSort2, arr2, N);

	//基本有序
	int *arr3 = SortTestHelper::CreateRandomArray(N, 0, 10);
	SortTestHelper::testSort("SelectionSort", SelectSortFunc::SelectionSort2, arr3, N);

	delete[] arr1;
	delete[] arr2;
	delete[] arr3;
	return 0;
}

测试结果:

SelectionSort : 0.424071s SelectionSort : 0.416928s SelectionSort : 0.410701s

根据结果表明,选择排序是一种稳定的排序算法,在随机性很大和近乎有序,有序的情况下算法的时间复杂度基本不变。但是这也是一个劣势,效率较差。