public static <T extends Comparable<? super T>> void insertionSort(T[] a) {
int len = a.length;
for ( int i = 1; i < len; i++) {
for ( int k = i; (k > 0) && (a[k].compareTo(a[k - 1]) < 0); k--) {
swap(a, k, k - 1);
}
}
}
三、冒泡排序
冒泡排序与插入排序有很多相似的地方,只不过是冒泡排序的开销稍高。
伪代码:
for i = 0:n-1,
swapped = false
for j = n-1:i+1,
if a[j] < a[j-1],
swap a[j,j-1]
swapped = true
break if not swapped
end
性能:
最坏的情况:О(<i>n</i><sup>2</sup>)
最好的情况:
平均状况:О(<i>n</i><sup>2</sup>)
稳定
额外需要的空间:O(n)
java实现:
public static <T extends Comparable<? super T>> void bubbleSort(T[] a) {
boolean swapped;
for ( int i = 0; i < a.length; i++) {
swapped = false;
for ( int j = a.length - 1; j > i; j--) {
if (a[j].compareTo(a[j - 1]) < 0) {
swap(a, j, j - 1);
swapped = true;
}
}
if (!swapped) { break; }
}
}
四、希尔排序
希尔排序属于插入类排序,是将整个无序列分割成若干小的子序列分别进行插入排序。将要排序的一组数按某个增量 gap 分成 gap 组,每组中记录的下标相差 gap.对每组中全部元素进行排序,然后再用一个较小的增量对它进行,在每组中再进行排序。当增量减到1时,整个要排序的数被分成一组,排序完成。
性能:
最坏的情况:取决于增量(在这里的基底是3)
最好的情况:取决于增量
平均状况:取决于增量
不稳定
额外需要的空间:O(n)
java实现:
public static <T extends Comparable<? super T>>
void shellSort(T[] a) {
for( int inc = a.length/3; inc > 0; inc /= 3){
for( int index = 0;index < inc; index++){
shellInsertSort(a, index, inc);
}
}
shellInsertSort(a, 0, 1);
}
private static <T extends Object & Comparable<? super T>>
void shellInsertSort(T[] a, int start, int inc) {
//插入排序
for( int i = start + inc;i < a.length; i += inc){
for( int index = i;(index >= inc) && (a[index]).compareTo(a[index - inc]) < 0;index -= inc){
swap(a, index, index - inc);
}
}
}
function heapSort(a, count)
heapify(a, count) //形成初始堆(大根堆)
end := count-1 //子女元素的索引为 2*i+1 and 2*i+2
while end > 0
swap(a[end], a[0]) //交换堆中最大的元素
end := end - 1 //减少堆中元素的个数,重新调整为大根堆
siftDown(a, 0, end)
function heapify(a, count)
start := (count - 2 ) / 2 //将start作为根节点
while start ≥ 0
siftDown(a, start, count-1)
start := start - 1
function siftDown(a, start, end) is
root := start
while root * 2 + 1 ≤ end do //有子节点
child := root * 2 + 1 //左子节点
swap := root //暂存子树根节点)
if a[swap] < a[child] //判断根节点与左子节点的大小
swap := child
//如果存在右子节点,则比较两子节点的大小
if child+1 ≤ end and a[swap] < a[child+1]
swap := child + 1
//判断子节点是否比根节点大
if swap != root
swap(a[root], a[swap])
root := swap //根节点下降到子节点
else
return
性能:
最坏的情况:O(n log n)
最好的情况:O(<i>n</i> )
平均状况:O(<i>n</i> log <i>n</i>)
不稳定
额外需要的空间:O(n)
java 实现:
public static <T extends Comparable<? super T>> void heapSort(T[] a){
heapSortHelp(a,a.length);
}
private static <T extends Comparable<? super T>>
void heapSortHelp(T[] a, int length) {
heapify(a,a.length); //调整为大根堆的形式
int end = a.length - 1;
while(end > 0){
swap(a, 0, end);
end--;
siftDown(a,0,end);
}
}
private static <T extends Comparable<? super T>> void heapify(T[] a, int length) {
int currentSize = length; //存储根堆的元素个数
int start = (currentSize - 2) >>> 1;
while (start >= 0) {
siftDown(a,start,currentSize - 1);
start--;
}
}
private static <T extends Comparable<? super T>>
void siftDown(T[] a, int start, int end) {
int root = start;
while (2*root + 1 <= end) {
int child = 2*root + 1;
int exchange = root;
if (a[exchange].compareTo(a[child]) < 0) {
exchange = child;
}
if ((child + 1 <= end) && (a[child].compareTo(a[child + 1]) < 0)) {
exchange = child + 1;
}
if (exchange != root) {
swap(a, exchange, root);
root = exchange;
} else{
return;
}
}
}
七、快速排序
快速排序(Quicksort)是对冒泡排序的一种改进。由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
伪代码:
function quicksort(array, left, right)
// 子序列有两个或多个元素
if left < right
选取基准元素,索引pivotIndex //left ≤ pivotIndex ≤ right
// 确定基准元素的最终存放位置
pivotNewIndex := partition(array, left, right, pivotIndex)
// 递归快速排序
quicksort(array, left, pivotNewIndex - 1)
quicksort(array, pivotNewIndex + 1, right)
function partition(array, left, right, pivotIndex)
pivotValue := array
swap array and array[right] // 将基准元素移到最后
storeIndex := left
for i from left to right - 1 // left ≤ i < right
if array[i] < pivotValue
swap array[i] and array[storeIndex]
storeIndex := storeIndex + 1
swap array[storeIndex] and array[right] //将基准元素存到其最终存放位置
return storeIndex
性能:
最坏的情况:O(<i>n<sup>2</sup></i>)
最好的情况:O(<i>n</i> log <i>n</i>)
平均状况:O(<i>n</i> log <i>n</i>)
不稳定
额外需要的空间:O(n)
java 实现:
public static <T extends Comparable<? super T>> void quickSort(T[] a) {
quickSortHelp(a, 0, a.length - 1);
}
//left 数组最左边的元素索引,right 数组最右边的元素索引(包含)
private static <T extends Comparable<? super T>>
void quickSortHelp(T[] a, int left, int right) {
if (left < right) {
int privotIndex = (left + right) >>> 1;
int privotNewIndex = partition(a, left, right, privotIndex);
//递归快速排序(分而治之)
quickSortHelp(a, left, privotNewIndex - 1);
quickSortHelp(a, privotNewIndex + 1, right);
}
}
private static <T extends Comparable<? super T>>
int partition(T[] a, int left, int right, int privotIndex) {
T privotValue = a;
swap(a, privotIndex, right);
int storeIndex = left;
for ( int i = left; i < right; i++) {
if (a[i].compareTo(privotValue) < 0) {
swap(a, i, storeIndex);
storeIndex++;
}
}
swap(a, storeIndex, right);
return storeIndex;
}