简单排序算法
冒泡排序
冒泡排序算法是一种很简单的排序算法,它重复的访问要排序的数列,比较两个相邻的元素,如果这个两个元素不是出于正确的位置及左边的元素比右边大,则交换这两个元素的位置(从小到大排序)。一直重复这个过程直到所有的元素都是有序的。
例如:对{5 1 4 2 8}进行从小到大进行排序。
第一遍
( 5 1 4 2 8 ) → ( 1 5 4 2 8 ), 首先, 冒泡算法比较第一个和第二个元素,因为 5>1 所以进行交换。
( 1 5 4 2 8 ) → ( 1 4 5 2 8 ), 因为 5>4 进行交换
( 1 4 5 2 8 ) → ( 1 4 2 5 8 ), 交换,因为 5>2
( 1 4 2 5 8 ) → ( 1 4 2 5 8 ), 现在, 因为这两个元素出于有序状态 (8>5) ,所有算法并不交换他们。
第二遍
( 1 4 2 5 8 ) → ( 1 4 2 5 8 )
( 1 4 2 5 8 ) → ( 1 2 4 5 8 ), 交换因为 4>2
( 1 2 4 5 8 ) → ( 1 2 4 5 8 )
( 1 2 4 5 8 ) → ( 1 2 4 5 8 )
现在该数组是有序的了,但是该算法并不知道是否已经完成了排序。因此,该算法需要继续访问数组,如果访问数组时没有任何的元素交换,则说明该数组是有序的
第三遍
( 1 2 4 5 8 ) → ( 1 2 4 5 8 )
( 1 2 4 5 8 ) → ( 1 2 4 5 8 )
( 1 2 4 5 8 ) → ( 1 2 4 5 8 )
( 1 2 4 5 8 ) → ( 1 2 4 5 8 )
插入排序
插入排序的工作方式像许多人工排序一手扑克牌。开始时,我们的左手边为空并且桌子上的牌面向下。然后,我们每次从桌子上拿走一张牌并将它插入左手中正确的位置。为了找到一张牌正确的位置,我们从右到左将它与已在手中的每张牌进行比较,如图所示。拿在左手上的牌总是排好序的,原来这些牌是桌子上牌堆中顶部的牌。
其插入排序算法的过程为:
代码为:
希尔排序
由于插入排序一次只能消除一个逆序对,及元素只能一点一点地从数组的一端移动到另一端。希尔排序为了加快速度简单的修改了插入排序,交换不相邻的元素以对数组的局部进行排序,并最终用插入排序将局部有序的数组排序。
希尔排序的思想是使数组中任意间隔为h的元素是有序的。这样的数组称为h有序数组。换句话说,一个h有序数组就是h个互相独立的有序数组编织在一起组成一个数组。在进行排序是,如果好很大,我们就能将元素移动到很远的地方,为实现更小的h有序创造方便。用这种方式,对于任意以1结尾的h序列,我们都能够将数组排序。这就是希尔排序。
理论很难懂,来点实际的举个“栗子”吧。列如对数列{81, 94, 11, 96, 12, 35, 17, 95, 28, 58, 41, 75, 15},进行希尔排序。
首先使用5间隔进行排序
![]()
![]()
持续这个过程直到所有以5间隔的元素都是有序的
![]()
接下来说继续对上列数列分别进行3间隔和1间隔排序
其中我们把5间隔,3间隔,1间隔称为递增序列或者说增量序列。增量序列满足以下条件
对于不同的增量序列,希尔排序不同的性能。其中比较常用的增量序列为
Dk=3∗Dk−1+1
where
D1=1
希尔排序代码为:
三种代码的Java实现为:
package SimpleSort;
import java.util.*;
import static java.lang.System.out;
public class Sort {
private static <T> void swap(T [] arr, int i, int j) {
T tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
/**
* 冒泡排序算法
* @param arr 要排序的数组
*/
public static void bubbleSort(Comparable [] arr) {
int N = arr.length;
boolean flag = false;
for (int i = 0; i < arr.length; ++i) {
flag = false;
for (int j = 0; j < arr.length - 1 - i; ++j) {
if (arr[j].compareTo(arr[j+1]) > 0) {
swap(arr, j, j+1);
flag = true;
}
}
// 如果没有进行交换,说明已经排好序
if (!flag) break;
}
}
/**
* 冒泡排序算法
* @param arr 要排序的数组
* @param comparator 类比较器
* @param <T> 泛型参数
*/
public static <T> void bubbleSort(T [] arr, Comparator comparator) {
int N = arr.length;
boolean flag = false;
for (int i = 0; i < arr.length; ++i) {
flag = false;
for (int j = 0; j < arr.length - 1 - i; ++j) {
if (comparator.compare(arr[j], arr[j+1]) > 0) {
swap(arr, j, j+1);
flag = true;
}
}
// 如果没有进行交换,说明已经排好序
if (!flag) break;
}
}
/**
* 插入排序
* @param arr 要排序的数组
*/
public static void insertSort(Comparable [] arr) {
for (int i = 1; i < arr.length; ++i) {
Comparable key = arr[i];
int j = i - 1;
while (j >= 0 && arr[j].compareTo(key) > 0) {
arr[j+1] = arr[j];
--j;
}
arr[j+1] = key;
}
}
/**
* 插入排序
* @param arr 要排序的数组
* @param comparator 比较器
* @param <T> 泛型参数
*/
public static <T> void insertSort(T [] arr, Comparator comparator) {
for (int i = 1; i < arr.length; ++i) {
T key = arr[i];
int j = i - 1;
while (j >= 0 && comparator.compare(arr[j], key) > 0) {
arr[j+1] = arr[j];
--j;
}
arr[j+1] = key;
}
}
/**
* 希尔排序
* @param arr 要排序的数组
*/
public static void shellSort(Comparable [] arr) {
int N = arr.length;
int k = 1, hibb;
// 逆序求出Hibbard增量序列
List<Integer> gaps = new ArrayList<>();
while(true) {
hibb = (int)(Math.pow(2, k) - 1);
if (hibb > N) break;
gaps.add(hibb);
++k;
}
for (k = gaps.size()-1; k >= 0; --k) {
int gap = gaps.get(k);
for (int i = gap; i < N; ++i) {
Comparable key = arr[i];
int j = i;
while (j >= gap && arr[j-gap].compareTo(key) >= 0) {
swap(arr, j, j - gap);
j -= gap;
}
arr[j] = key;
}
}
}
public static double time(String alg) {
Double [] arr = new Double[100000];
for (int i = 0; i < arr.length; ++i)
arr[i] = Math.random();
long callTime = System.currentTimeMillis();
if (alg.equals("bubbleSort")) bubbleSort(arr);
else if (alg.equals("insertSort")) insertSort(arr);
else if (alg.equals("shellSort")) shellSort(arr);
callTime = System.currentTimeMillis() - callTime;
return callTime*1.0/1000;
}
public static void main(String [] args) {
Integer [] arr = new Integer[10];
Random random = new Random(123);
for (int i = 0; i < arr.length; ++i)
arr[i] = random.nextInt(100);
insertSort(arr, new Comparator<Integer>() {
@Override
public int compare(Integer a, Integer b) {
return Integer.compare(a, b);
}
});
out.println(Arrays.toString(arr));
//随进产生100000个元素,三种排序算法的运行时间为
out.println("shell sort : " + time("shellSort") + "s");
out.println("insert sort : " + time("insertSort") + "s");
out.println("bubble sort: " + time("bubbleSort") + "s");
}
}
附上Java算法gitHub
https://github.com/liangpj/AlgorithmsJava.git
Reference:
[1] Wikipedia, Bubble Sort
[2]. 《算法导论》第三版 Thomas H.Cormen et al.
[3]. 数据结构–陈越、何钦铭