本文的内容是对算法(Algorithms)第四版中的算法源码的总结及部分补充
主类(排序的通用函数)
public class Example {
private static boolean less(Comparable v, Comparable w) {
return v.compareTo(w) < 0;
}
private static void exch(Comparable[] a, int i, int j) {
Comparable t = a[i];
a[i] = a[j];
a[j] = t;
}
private void show(Comparable[] a) {
//在单行中打印数组
for(int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
System.out.println();
}
public static boolean isSorted(Comparable[] a) {
for(int i = 1; i < a.length; i++) {
if(less(a[i], a[i - 1])) {
return false;
}
}
return true;
}
/***
public static class Select{
}
public static class Insert{
}
......
****/
}
1、选择排序-select_sort
public static class Select{
public static void sort(Comparable[] a) {
int N = a.length;
for(int i = 0; i < N; i++) {
int min = i;
for(int j = i + 1; j < N; j++) {
if(less(a[min], a[j])) {
min = j;
}
}
exch(a, i, min);
}
}
}
2、插入排序-insert_sort
public static class Insert{
public static void sort(Comparable[] a) {
int N = a.length;
for(int i = 1; i < N; i++) {
for(int j = i; j > 0 && less(a[j], a[j - 1]); j--) {
exch(a, j ,j - 1);
}
}
}
}
3、冒泡排序-bubble_sort
public static class Bubble{
public static void sort(Comparable[] a) {
int N = a.length;
for(int i = 0; i < N - 1; i++) {
for(int j = 0; j < N - 1 - i; j++) {
if(less(a[j + 1], a[j])) {
exch(a, j, j +1);
}
}
}
}
}
4、希尔排序-shell_sort
public static class Shell{
public static void sort(Comparable[] a) {
int N = a.length;
int h = 1;
while(h < N / 3) {
h = h * 3 + 1;
}
while(h >= 1) {
for(int i = h; i < N; i++) {
for(int j = h; j >= h && less(a[j], a[j - h]); j -= h) {
exch(a, j, j - h);
}
}
h /= 3;
}
}
}
5、归并排序-merge_sort
5.1、归并排序-(递归实现)
public static class Merge{
private static Comparable[] aux; //归并需要的辅助数组
public static void sort(Comparable[] a) {
aux = new Comparable[a.length];
sort(a, 0, a.length - 1);
}
private static void sort(Comparable[] a, int lo, int hi) {
if(lo >= hi) {
return;
}
int mid = lo + (hi - lo) / 2;
sort(a, lo, mid); //将左半边排序
sort(a, mid + 1, hi); //将右半边排序
merge(a, lo, mid, hi); //归并
}
/*** 原地归并所需要的算法 ***/
private static void merge(Comparable[] a, int lo, int mid, int hi) {
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[i], aux[j])) {
a[k] = aux[i++];
}else {
a[k] = aux[j++];
}
}
}
}
5.2、归并排序-自底向上
public static class MergeBu{
private static Comparable[] aux; //归并所需要的辅助数组
public static void sort(Comparable[] a) {
//进行lgN次两两归并
int N = a.length;
aux = new Comparable[N];
for(int sz = 1; sz < N; sz = sz + sz) {
for(int lo = 0; lo < N - sz; lo += sz + sz) {
merge(a, lo, lo + sz - 1, Math.min(lo + sz + sz - 1, N - 1));
}
}
}
/*** 原地归并所需要的算法 ***/
public static void merge(Comparable[] a, int lo, int mid, int hi) {
//代码同上
}
}
6、快速排序-quick_sort
public static class Quick{
public static void sort(Comparable[] a) {
//Collections.shuffle(a); 消除对输入的依赖 a类型需为List
sort(a, 0, a.length - 1);
}
public static void sort(Comparable[] a, int lo, int hi) {
if(lo >= hi) {
return;
}
int j = partition(a, lo, hi); //找出切分元素的位置
sort(a, lo, j - 1); //将左半部分a[lo..j - 1]排序
sort(a, j + 1, hi); //将右半部分a[j + 1..hi]排序
}
public static int partition(Comparable[] a, int lo, int hi) {
//将数组切分为a[lo..i - 1], a[i], a[i + 1, 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;
}
exch(a, i, j);
}
exch(a, lo, j); //将v = a[i]放入正确的位置
return j;
}
}
三向切分的快速排序-quick3way
避免大量重复数字对函数的调用
public static class Quick3way{
private static void sort(Comparable[] a) {
sort(a, 0, a.length - 1);
}
private static void sort(Comparable[] a, int lo, int hi) {
if(lo >= hi) {
return;
}
int lt = lo, i = lo + 1, gt = hi;
Comparable v = a[lo];
while(i <= gt) {
int cmp = a[i].compareTo(v);
if(cmp < 0) {
exch(a, lt++, i++);
}else if(cmp > 0) {
exch(a, i, gt--);
}else {
i++;
}
} //满足 a[lo..lt - 1] < v = a[lt..gt] > a[gt + 1..hi]
sort(a, lo, lt - 1);
sort(a, gt + 1, hi);
}
}
7、堆排序-heap_sort
//大多数情况下堆排序下标是从1开始的,这样更方便,而且下标为0的地方也可以作为哨兵
public static class Heap{
private static void sort(Comparable[] a) {
int N = a.length - 1;
for(int k = N / 2; k >= 0; k--) { //构造堆
sink(a, k, N);
}
while(N > 0) { //销毁堆
exch(a, 0, N--);
sink(a, 0, N);
}
}
//下沉 (自顶向下堆的有序化的实现) (小元素移至数组右端)
private static void sink(Comparable[] a, int k, int N) {
while(2 * k + 1 <= N) {
int j = 2 * k + 1;
if(j + 1 <= N && less(a[j], a[j + 1])) {
j++;
}
if(!less(a[k], a[j])) {
break;
}
exch(a, k , j);
k = j;
}
}
}
8、桶排序-bucket_sort
public static class Bucket{
private final static int N = 100; //假如数字大小在1-100之间
private static int[] aux;
public Bucket(){
aux = new int[N + 1];
}
public void sort(int a[]) {
for(int i : a) {
aux[i]++;
}
int k = 0;
for(int i = 0; i <= N; i++) {
if(aux[i] > 0) {
while(aux[i]-- > 0) {
a[k++] = i;
}
}
}
}
}
9、基数排序-radix_sort
基数排序在字符串的排序算法中用的比较多,后期的内容会涉及到···