选择排序
工作原理是从待排序的数据元素中选出最小(或最大)的一个元素,并与第一个数交换位置,然后选择剩下数组中最小的数,放到数组的第二个位置,
一次类推。
图解过程如下:
选择排序特点是:
1、运行时间和数组内容无关:我们会发现,即使是一个已经排序好的数组去使用选择排序,运行的时间与随机的数组排序时间居然一样长
2、移动的数据少:数组的交换次数和数组大小是线性关系。
/**
* 选择排序 每次选择剩下数组中最小的数,然后与剩下数组最前面的数交换位置,直到结束。
*
* @author xiaoqi
*
*/
public class Selection {
public static void sort(int[] a) {
for (int i = 0; i < a.length; i++) {
int min = i;// min为最小值的下标
//找出剩余数组的最小值
for (int j = i + 1; j < a.length; j++) {
if(a[min] > a[j]){
min = j;
}
}
//交换位置
int temp = a[i];
a[i] = a[min];
a[min] = temp;
}
}
}
插入排序
插入排序就如同我们打牌一样,按照顺序把每张牌插入一个已经排好序的数组中,剩余的数组右移即可。
图解如下:
特点,插入排序所需时间与数组的初识顺序相关,通过这点我们知道,它的运行效率是要高于选择排序的。其比较适合部分有序和规模中小的数组。
/**
* 插入排序 如同打牌一样,将剩下数组的第一个插入到前面已经排好序的数组中,然后后移插入位置到原位置的数组一位 特别适合有一定顺序的数组
*
* @author xiaoqi
*
*/
public class Insertion {
/**
* 将a[i]取出,然后从a[i-1]的位置开始从已经排序好的数组的最后一个位置开始向左(依次到第0个位置)比较,大于就交换位置
*
* 通过交换位置的方式向右移动
* @param a
*/
public static void sort2(int[] a) {
for (int i = 1; i < a.length; i++) {
for (int j = i; j > 0; j--) {
if (a[j] < a[j-1]) {
int temp = a[j-1];
a[j-1] = a[j];
a[j] = temp;
}
}
}
}
}
希尔排序
希尔排序是对插入排序的一种优化。我们知道,插入排序是适合部分有序的数组,这样就可以使移动的数组尽量的小。而希尔排序就是先把一个数组变成“部分有序”,再进行插入排序,从而得到结果。他的思想是设置一个h,通过插入排序,让数组中任意间隔h的元素都是有序的,然后缩小h的值,再排序,直到h为1。因此它的效率取决于h的选取。
图解:
/**
* 希尔排序 是插入排序的一种改进,它的空间复杂度取决于一个常数因子,但是小于插入排序。
* 思想:把数组分为间隔为h的h个数组,然后分别插入排序,再把分为h/k(k>1)个数组,再插入排序,直到h为1。
* @author xiaoqi
*
*/
public class Shell {
public static void sort(int[] a){
int N = a.length;
int h = 1;
//假设这个常数因子是 d = 1/3
//先得到一个h/d + 1大于 数组长度的最小值
while(h < N/3){
h = 3 * h + 1;
}
//进行插入排序直到h为1
while(h >= 1){
//每个数组间隔为h,进行插入排序
for(int i=h;i< N;i++){
for(int j = i;j >= h;j -= h){
if(a[j] < a[j-h]){
int temp = a[j];
a[j] = a[j-h];
a[j-h] = temp;
}
}
}
//缩小h
h = h /3;
}
SortTest.show();
SortTest.isSorted(a);
}
}