算法基础之----直接选择排序(SelectSort)
假设有一个序列,元素个数为n,要对该序列进行排序。
在要排序的这一组数中,找到一个最小(或最大)元素,与第1个位置(下标为0)的元素进行交换。然后,再进行如上操作,从除第一个元素值外的所有元素中,找到
最小(或最大)的元素,与第二个位置(下标为1)处的元素进行交换;以此类推,直到第n-1个元素和第n个元素比较为止。
注:
如果要查找的元素就是下标为i的本身,则不需要进行交换,直接进行下一次循环。
例如:
元素序列:5 8 1 2 6 0 4 3 9 7
第一次 0 8 1 2 6 5 4 3 9 1
第二次 0 1 8 2 6 5 4 3 9 7
…. ….
第n-1次 0 1 2 3 4 5 6 7 9 8
第n次 0 1 2 3 4 5 6 7 8 9
手工过程:(假设一个数组array的长度为n)
第0趟:找出array中下标为0~n-1中最小(或最大)的元素tmp,与array[0]交换
第1趟:找出array中下标为1~n-1中最小(或最大)的元素tmp,与array[1]交换
….
第i趟:找出array中下标为i~n-1中最小(或最大)的元素tmp,与array[i]交换
…..
第n-2趟:将array中下表为n-2和下标为n-1的元素比较,找到合适的位置,进行交换。
如此过程就完成了排序。
代码实现:(此处数组的生成采用一个随机函数生成一个无序数组)
C语言:
#include<stdio.h>
#include<malloc.h>
#include<time.h>
#include<stdlib.h>
typedef unsigned char boolean;
#define TRUE 1
#define FALSE 0
void initData(int *array, int count, int minValue, int maxValue);
void showArray(int *array, int count);
void directSelectSort(int *data, int count);
//直接选择排序,升序
void directSelectSort(int *data, int count) {
int i;
int minValueIndex;
int index;
int temp;
for(i = 0; i < count-1; i++) {
minValueIndex = i;
for(index = i+1; index < count; index++) {
if(data[index] < data[minValueIndex]) {
minValueIndex = index;
}
}
if(minValueIndex != i) {
temp = data[minValueIndex];
data[minValueIndex] = data[i];
data[i] = temp;
}
}
}
void showArray(int *array, int count) {
int i;
for(i = 0; i < count; i++) {
printf(i == 0 ? "%d" : ", %d", array[i]);
}
printf("\n");
}
void initData(int *array, int count, int minValue, int maxValue) {
int i = 0;
int value = maxValue - minValue + 1;
srand(time(0));
for(i = 0; i < count; i++) {
array[i] = minValue + rand()%value;
}
}
void main(void) {
int *array;
array = (int *)calloc(sizeof(int), 20);
initData(array, 20, 1, 100);
showArray(array, 20);
directSelectSort(array, 20);
showArray(array, 20);
}
注:
如果是在Linux环境下,gcc编译,则,需要将main函数的返回值改为int,并且在最后加一句return 0;
Java语言:
public class SelectSort {
public static void main(String[] args) {
int[] array = new int[20];
initData(array, 200);
showData(array);
selectSort(array);
showData(array);
}
/**
* 升序
* 直接选择排序的核心代码
* @param array
*/
private static void selectSort(int[] array) {
int len = array.length;
int minIndex = 0;
for(int i = 0; i < len-1; i++) {
minIndex = i;
for(int j = i+1; j < len; j++) {
if(array[minIndex] > array[j]) {
minIndex = j;
}
}
int tmp;
if(minIndex != i) {
tmp = array[minIndex];
array[minIndex] = array[i];
array[i] = tmp;
}
}
}
/**
* 显示数组
* @param array
*/
private static void showData(int[] array) {
for(int i = 0; i < array.length; i++) {
System.out.printf(i == 0 ? "%d" : ", %d", array[i]);
}
System.out.println();
}
/**
* 初始化一个数组,元素随机产生
* @param array 要初始化的数组
* @param maxValue 数组元素的最大值
*/
private static void initData(int[] array, int maxValue) {
for(int i = 0; i < array.length; i++) {
array[i] = (int)(Math.random()*maxValue);
}
}
}
讨论:
1、 时间和空间复杂度的分析:
主要是比较次数,且始终是n(n-1)/2次,交换次数最多为n-1次,最少为0次,则,
时间复杂度为:O(n(n-1)/2) <==>O(n^2)
空间复杂度为:O(2)
2、 稳定性:
非稳定排序
3、 极端情况下的分析:
完全顺序的情况下,只存在比较,无需交换;
完全逆序的情况,并非最差情况。
极端情况下时间复杂度仍为O(n^2)。