一、选择排序算法详解
选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。
首先给定一无序数组
第一轮排序,将第一个元素5与之后的元素依次比较,选择最小的元素3与第一个元素5交换位置。待排序序列变为{8,5,9,4}。
第二轮排序,将待排序序列的第一个元素(数组第二个元素8)与之后的元素依次比较,选择最小的元素4与待排序序列的第一个元素8交换位置。待排序序列为{5,9,8}。
第三轮排序,将待排序序列的第一个元素(数组第三个元素5)与之后的元素依次比较,因为5本身就是待排序序列最小元素,无需交换,待排序序列为{9,8}。
第四轮排序,将待排序序列的第一个元素(数组第四个元素9)与之后的元素依次比较,选择最小的元素8与待排序序列的第一个元素9交换位置。排序完成。
//基于数组的选择排序算法
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define MAXSIZE 20
void Input(int r[], int n);//输入数组的n个元素
void Output(int r[], int n);//输出数组的n个元素
void SelectSort(int r[], int n);//选择排序(升序)
void Swap(int* a, int* b);//交换a和b所指变量的值
int main()
{
int a[MAXSIZE];//定义大小为MAXSIZE的数组
int len;//定义数组的长度
printf("请输入数组的长度为:\n");
scanf("%d", &len);
printf("输入数组的%d个元素:\n", len);
Input(a, len);//输入数组的N个元素
printf("排序前数组a的元素为:");
Output(a, len);//输出排序前数组的元素
SelectSort(a, len);//选择排序
printf("排序后数组a的元素为:");
Output(a, len);
return 0;
}
void Input(int r[], int n)
{
for (int i = 0; i < n; i++)
{
scanf("%d", &r[i]);
}
}
void Output(int r[], int n)
{
for (int i = 0; i < n; i++)
{
printf("%d ", r[i]);
}
printf("\n");
}
void Swap(int* a, int* b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void SelectSort(int r[], int n)
{
int i, j, k;//k记录最小元素的下标
for (i = 0; i < n - 1; i++)
{
k = i;
for (j = i + 1; j < n; j++)
{
if (r[j] < r[k])
k = j;
}
if (k != i)
Swap(&r[i], &r[k]);
printf("第%d轮排序后的数组",i+1);
Output(r, n);
}
}
二、选择排序性能分析
时空复杂度
- 时间复杂度:需要遍历数组才能找到峰值元素,所以复杂度与原始序列是否有序无关,最好最坏和平均情况的时间复杂度都为O(n^2)
- 空间复杂度:需要一个临时变量用来交换数组内数据位置,所以空间复杂度为O(1)
算法稳定性
选择排序是给每一个位置选择当前元素最小的,比方给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推。直到第n-1个元素,第n个元素不用选择了,由于仅仅剩下它一个最大的元素了。那么,在一趟选择。假设一个元素比当前元素小。而该小的元素又出如今一个和当前元素相等的元素后面。那么交换后稳定性就被破坏了。
举个例子·,序列{5, 8, 5 ,2, 9},我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序是一个不稳定的排序算法。