序言
排序是编程中经常要碰到的一类问题,有时候在硬件水平有限的情况下,一个简短高效的排序算法能够是程序的运行速度提升一个档次,因此该博客汇总了经常用到而且有效的排序算法,并给出基于Java语言的实现代码。
代码说明
- 由于本次实现的排序算法大部分基于先比较然后交换的方法,因此为了避免编写重复的代码,我们先将通用的方法代码写到一个抽象类中作为排序类的模板,并用protected修饰,然后每一个具体的排序算法继承该模板并给出具体的排序的实现代码即可。
- 为了使算法具有更大的应用空间,我使用了Java的Comparable接口作为比较对象,因此任何一个实现类Comparable接口的对象都可以直接使用该算法进行比较,在Java中很多类都实现了Comparable接口,比如8个基本类型的包装类,String类等。
排序类算法模板
类名我使用AbstractSort,你可以随意
package com.tyutlh.algorithms.sort;
import java.util.Arrays;
/**
* This class defines a general template for sorting algorithms,
* each subclass should be provide a specific sorting method that
* implements the {@code sortMethod(Comparable[])} method, moreover
* should be provide a {@code sort(Comparable<?>[] a)} method like the
* following example.
*
* <p><pre>
* public class MySort extends AbstractSort {
* public static void sort(Comparable<?>[] a) {
* new MySort().sortMethod(a);
* }
* {@code @Override}
* protected void sortMethod(Comparable<?>[] a) {
* //specific implement details.
* }
* }
* </pre></p>
*
* @author TYUT_LH
* @since 11
* @see java.lang.Comparable
*/
@SuppressWarnings("rawtypes")
public abstract class AbstractSort {
/**
* The specific sorting method
*
* @param a The array to be sorted.
*/
protected abstract void sortMethod(Comparable[] a);
/**
* Swap element at i and j in {@code a} array.
*
* @param a The array to be swapped.
* @param i The first element index.
* @param j The second element index.
*/
protected void swap(Comparable[] a, int i, int j) {
Comparable t = a[i];
a[i] = a[j];
a[j] = t;
}
/**
* Compare v and w and return a integer that represent their size
* relationship, its determined by the return result of
* {@code compareTo(Object o)}.
*
*
* @param v The first element to be compared
* @param w The second element to be compared.
* @return An integer that represent the size relationship between
* v and w.
*/
@SuppressWarnings({"unchecked"})
protected boolean less(Comparable v, Comparable w) {
return v.compareTo(w) < 0;
}
/**
* Print all elements on the console.
*
* @param a The array to be printed.
*/
public static void show(Comparable[] a) {
System.out.println(Arrays.toString(a));;
}
}
具体的排序类算法的实现代码
1.插入排序
插入排序(Insertion Sort)的算法描述是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。
package com.tyutlh.algorithms.sort;
/**
* Insertion sorting implementation class.
*
* @author TYUT_LH
*
*/
@SuppressWarnings("rawtypes")
public class InsertionSort extends AbstractSort {
/**
* Sorts the specified array into an ordered state, according the
* return value of {@code compareTo(Object o)} that defined by the
* element in the array.
*
* @param a The array to be sorted.
*/
public static void sort(Comparable[] a) {
new InsertionSort().sortMethod(a);
}
@Override
protected void sortMethod(Comparable[] a) {
int len = a.length;
for (int i = 1; i < len; i++) {
for (int j = i; j > 0 && less(a[j], a[j - 1]); j--)
swap(a, j, j - 1);
}
}
}
- 选择排序
选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。选择排序是不稳定的排序方法。
package com.tyutlh.algorithms.sort;
/**
* Selection sorting implementation class.
*
* @author TYUT_LH
*
*/
@SuppressWarnings("rawtypes")
public class SelectionSort extends AbstractSort {
/**
* Sorts the specified array into an ordered state, according the
* return value of {@code compareTo(Object o)} that defined by the
* element in the array.
*
* @param a The array to be sorted.
*/
public static void sort(Comparable[] a) {
new SelectionSort().sortMethod(a);
}
@Override
protected void sortMethod(Comparable[] a) {
int len = a.length;
for (int i = 0; i < len; i++) {
int min = i;
for (int j = i + 1; j < len; j++) {
if (less(a[j], a[min]))
min = j;
}
swap(a, i, min);
}
}
}
- 希尔排序
希尔排序(Shell’s Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因D.L.Shell于1959年提出而得名。
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
在该例子代码中:增量选择的是1, 4, 7 …
package com.tyutlh.algorithms.sort;
/**
* Shell sorting implementation class.
*
* @author TYUT_LH
*
*/
@SuppressWarnings("rawtypes")
public class ShellSort extends AbstractSort {
/**
* Sorts the specified array into an ordered state, according the
* return value of {@code compareTo(Object o)} that defined by the
* element in the array.
*
* @param a The array to be sorted.
*/
public static void sort(Comparable[] a) {
new ShellSort().sortMethod(a);
}
@Override
protected void sortMethod(Comparable[] a) {
int len = a.length;
int h = 1;
while (h < len / 3)
h = 3 * h + 1;
while (h >= 1) {
for (int i = h; i < len; i++) {
for (int j = i; j >= h && less(a[j], a[j - h]); j -= h)
swap(a, j, j - h);
}
h /= 3;
}
}
}
- 归并排序
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。归并排序是一种稳定的排序方法。
package com.tyutlh.algorithms.sort;
/**
* Merge sorting implementation class.
*
* <p>Explanation:The sorting algorithm of this class does not
* implement the {@code sortMethod(Comparable[])} abstract
* method in the superclass because it needs to use recursion.
* </p>
*
* @author TYUT_LH
*
*/
@SuppressWarnings("rawtypes")
public class MergeSort extends AbstractSort {
/**
* An auxiliary array for the array which to be sorted.
*/
private static Comparable[] aux;
/**
* Sorts the specified array into an ordered state, according the
* return value of {@code compareTo(Object o)} that defined by the
* element in the array.
*
* @param a The array to be sorted.
*/
public static void sort(Comparable[] a) {
aux = new Comparable[a.length];
new MergeSort().sortMethod(a);
}
@Override
protected void sortMethod(Comparable[] a) {
int len = a.length;
int step = 1;
while (step < len) {
int lo = 0;
for (; lo + step < len; lo = lo + step + 1)
merge(a, lo, lo + step, lo + step / 2);
if (lo < len)
merge(a, lo - step - 1, len - 1, lo - 1);
step = 2 * step + 1;
}
}
private void merge(Comparable[] a, int lo, int hi, int mid) {
int i = lo, j = mid + 1;
for (int k = lo; k <= hi; k++)
aux[k] = a[k];
for (int k = lo; k <= hi; k++) {
if (i > mid) a[k] = aux[j++];
else if (j > hi) a[k] = aux[i++];
else if (less(aux[j], aux[i])) a[k] = aux[j++];
else a[k] = aux[i++];
}
}
}
/***********End of file****************/
- 快速排序
快速排序由C. A. R. Hoare在1960年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
package com.tyutlh.algorithms.sort;
import java.util.Random;
/**
* Quick sorting implementation class.
*
* <p>
* This class uses a general quick sort algorithm, which may be generally
* efficient for arrays with more duplicate primary keys. If so, the
* {@link #Quick3WaysSort} class is recommended.
* </p>
* @author TYUT_LH
* @see Quick3WaysSort
*/
@SuppressWarnings({"rawtypes"})
public class QuickSort extends AbstractSort {
/**
* Sorts the specified array into an ordered state, according the
* return value of {@code compareTo(Object o)} that defined by the
* element in the array.
*
* @param a The array to be sorted.
*/
public static void sort(Comparable[] a) {
QuickSort qs = new QuickSort();
qs.disorder(a);
qs.sortMethod(a, 0, a.length - 1);
}
@Override
protected void sortMethod(Comparable[] a) {}
protected void sortMethod(Comparable[] a, int lo, int hi) {
if (hi <= lo)
return;
int j = partition(a, lo, hi);
sortMethod(a, lo, j - 1);
sortMethod(a, j + 1, hi);
}
protected int partition(Comparable[] a, int lo, int hi) {
int i = lo, j = hi + 1;
Comparable v = a[lo];
while (true) {
while (less(a[++i], v)) if (i == hi) break;
while (less(v, a[--j])) if (j == lo) break;
if (i >= j) break;
swap(a, i, j);
}
swap(a, lo, j);
return j;
}
protected void disorder(Comparable[] a) {
int bound = a.length;
Random rand = new Random();
for (int i = 0; i < bound / 2; i++) {
int higher = rand.nextInt(bound);
while (higher <= 0) higher = rand.nextInt(bound);
int lower = rand.nextInt(higher);
swap(a, lower, higher);
}
}
}
参考文献
《算法 第4版》