目录
1.选择排序
public class SelectionSort {
private SelectionSort(){}
public static <E extends Comparable> void sort(E[] arr){
for(int i = 0; i < arr.length; i ++){
// 选择 arr[i...n) 中的最小值
int minIndex = i;
for(int j = i; j < arr.length; j ++){
if(arr[j].compareTo(arr[minIndex]) < 0)
minIndex = j;
}
swap(arr, i, minIndex);
}
}
private static <E> void swap(E[] arr, int i, int j){
E t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
}
2.快速排序
import java.util.Arrays;
import java.util.Random;
public class QuickSort {
private QuickSort(){}
public static <E extends Comparable<E>> void sort(E[] arr){
Random rnd = new Random();
sort(arr, 0, arr.length - 1, rnd);
}
private static <E extends Comparable<E>> void sort(E[] arr, int l, int r, Random rnd){
if(l >= r) return;
int p = partition(arr, l, r, rnd);
sort(arr, l, p - 1, rnd);
sort(arr, p + 1, r, rnd);
}
private static <E extends Comparable<E>> int partition(E[] arr, int l, int r, Random rnd){
// 生成 [l, r] 之间的随机索引
int p = l + rnd.nextInt(r - l + 1);
swap(arr, l, p);
// arr[l+1...j] < v ; arr[j+1...i] >= v
int j = l;
for(int i = l + 1; i <= r; i ++)
if(arr[i].compareTo(arr[l]) < 0){
j ++;
swap(arr, i, j);
}
swap(arr, l, j);
return j;
}
public static <E extends Comparable<E>> void sort2ways(E[] arr){
Random rnd = new Random();
sort2ways(arr, 0, arr.length - 1, rnd);
}
private static <E extends Comparable<E>> void sort2ways(E[] arr, int l, int r, Random rnd){
if(l >= r) return;
int p = partition2ways(arr, l, r, rnd);
sort2ways(arr, l, p - 1, rnd);
sort2ways(arr, p + 1, r, rnd);
}
private static <E extends Comparable<E>> int partition2ways(E[] arr, int l, int r, Random rnd){
// 生成 [l, r] 之间的随机索引
int p = l + rnd.nextInt(r - l + 1);
swap(arr, l, p);
// arr[l+1...i-1] <= v; arr[j+1...r] >= v
int i = l + 1, j = r;
while(true){
while(i <= j && arr[i].compareTo(arr[l]) < 0)
i ++;
while(j >= i && arr[j].compareTo(arr[l]) > 0)
j --;
if(i >= j) break;
swap(arr, i, j);
i ++;
j --;
}
swap(arr, l, j);
return j;
}
public static <E extends Comparable<E>> void sort3ways(E[] arr){
Random rnd = new Random();
sort3ways(arr, 0, arr.length - 1, rnd);
}
private static <E extends Comparable<E>> void sort3ways(E[] arr, int l, int r, Random rnd){
if(l >= r) return;
/** 三路快速排序的 partition 过程 **/
// 生成 [l, r] 之间的随机索引
int p = l + rnd.nextInt(r - l + 1);
swap(arr, l, p);
// arr[l + 1, lt] < v, arr[lt + 1, i - 1] == v, arr[gt, r] > v
int lt = l, i = l + 1, gt = r + 1;
while(i < gt){
if(arr[i].compareTo(arr[l]) < 0){
lt ++;
swap(arr, i, lt);
i ++;
}
else if(arr[i].compareTo(arr[l]) > 0){
gt --;
swap(arr, i, gt);
}
else{ // arr[i] == v
i ++;
}
}
swap(arr, l, lt);
/** 三路快速排序的 partition 过程结束 **/
// 递归调用
sort3ways(arr, l, lt - 1, rnd);
sort3ways(arr, gt, r, rnd);
}
private static <E> void swap(E[] arr, int i, int j){
E t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
public static void main(String[] args){
int n = 1000000;
Integer[] arr = ArrayGenerator.generateRandomArray(n, n);
Integer[] arr2 = Arrays.copyOf(arr, arr.length);
Integer[] arr3 = Arrays.copyOf(arr, arr.length);
System.out.println("Random Array");
SortingHelper.sortTest("QuickSort", arr);
SortingHelper.sortTest("QuickSort2Ways", arr2);
SortingHelper.sortTest("QuickSort3Ways", arr3);
System.out.println();
arr = ArrayGenerator.generateOrderedArray(n);
arr2 = Arrays.copyOf(arr, arr.length);
arr3 = Arrays.copyOf(arr, arr.length);
System.out.println("Ordered Array");
SortingHelper.sortTest("QuickSort", arr);
SortingHelper.sortTest("QuickSort2Ways", arr2);
SortingHelper.sortTest("QuickSort3Ways", arr3);
System.out.println();
arr = ArrayGenerator.generateRandomArray(n, 1);
arr2 = Arrays.copyOf(arr, arr.length);
arr3 = Arrays.copyOf(arr, arr.length);
System.out.println("Same Value Array");
// SortingHelper.sortTest("QuickSort", arr);
SortingHelper.sortTest("QuickSort2Ways", arr2);
SortingHelper.sortTest("QuickSort3Ways", arr3);
System.out.println();
}
}
3.归并排序
import java.util.Arrays;
public class MergeSort {
private MergeSort(){}
public static <E extends Comparable> void sort(E[] arr){
E[] temp = Arrays.copyOf(arr, arr.length);
sort(arr, 0, arr.length - 1, temp);
}
private static <E extends Comparable> void sort(E[] arr, int l, int r, E[] temp){
if (l >= r) return;
int mid = l + (r - l) / 2;
sort(arr, l, mid, temp);
sort(arr, mid + 1, r, temp);
if(arr[mid].compareTo(arr[mid + 1]) > 0)
merge(arr, l, mid, r, temp);
}
public static <E extends Comparable> void sortBU(E[] arr){
E[] temp = Arrays.copyOf(arr, arr.length);
int n = arr.length;
// 使用插入排序优化
// 遍历一遍,对所有 arr[i, i + 15] 的区间,使用插入排序法
for(int i = 0; i < n; i += 16)
InsertionSort.sort(arr, i, Math.min(n - 1, i + 15));
// 遍历合并的区间长度
// 注意,sz 从 16 开始
for(int sz = 16; sz < n; sz += sz){
// 遍历合并的两个区间的起始位置 i
// 合并 [i, i + sz - 1] 和 [i + sz, i + sz + sz - 1]
for(int i = 0; i + sz < n; i += sz + sz)
if(arr[i + sz - 1].compareTo(arr[i + sz]) > 0)
merge(arr, i, i + sz - 1, Math.min(i + sz + sz - 1, n - 1), temp);
}
}
private static <E extends Comparable> void merge(E[] arr, int l, int mid, int r, E[] aux){
System.arraycopy(arr, l, aux, l, r - l + 1);
int i = l, j = mid + 1;
// 每轮循环为 arr[k] 赋值
for(int k = l; k <= r; k ++){
if(i > mid){
arr[k] = aux[j]; j ++;
}
else if(j > r){
arr[k] = aux[i]; i ++;
}
else if(aux[i].compareTo(aux[j]) <= 0){
arr[k] = aux[i]; i ++;
}
else{
arr[k] = aux[j]; j ++;
}
}
}
public static void main(String[] args){
int n = 10000000;
Integer[] arr = ArrayGenerator.generateRandomArray(n, n);
Integer[] arr2 = Arrays.copyOf(arr, arr.length);
SortingHelper.sortTest("MergeSort", arr);
SortingHelper.sortTest("MergeSortBU", arr2);
}
}
4.插入排序
import java.util.Arrays;
public class InsertionSort {
private InsertionSort(){}
public static <E extends Comparable<E>> void sort(E[] arr){
for(int i = 0; i < arr.length; i ++){
// 将 arr[i] 插入到合适的位置
E t = arr[i];
int j;
for(j = i; j - 1 >= 0 && t.compareTo(arr[j - 1]) < 0; j --){
arr[j] = arr[j - 1];
}
arr[j] = t;
}
}
public static <E extends Comparable<E>> void sort(E[] arr, int l, int r){
for(int i = l; i <= r; i ++){
// 将 arr[i] 插入到合适的位置
E t = arr[i];
int j;
for(j = i; j - 1 >= l && t.compareTo(arr[j - 1]) < 0; j --){
arr[j] = arr[j - 1];
}
arr[j] = t;
}
}
}
5.堆排序
import java.util.Arrays;
public class HeapSort {
private HeapSort(){}
public static <E extends Comparable<E>> void sort(E[] data){
if(data.length <= 1) return;
for(int i = (data.length - 2) / 2 ; i >= 0 ; i --)
siftDown(data, i, data.length);
for(int i = data.length - 1; i >= 0; i --){
swap(data, 0, i);
siftDown(data, 0, i);
}
}
// 对 data[0, n) 所形成的最大堆中,索引 k 的元素,执行 siftDown
private static <E extends Comparable<E>>void siftDown(E[] data, int k, int n){
while(2 * k + 1 < n){
int j = 2 * k + 1; // 在此轮循环中,data[k]和data[j]交换位置
if( j + 1 < n && data[j + 1].compareTo(data[j]) > 0 )
j ++;
// data[j] 是 leftChild 和 rightChild 中的最大值
if(data[k].compareTo(data[j]) >= 0 )
break;
swap(data, k, j);
k = j;
}
}
private static <E> void swap(E[] arr, int i, int j){
E t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
public static void main(String[] args) {
int n = 1000000;
Integer[] arr = ArrayGenerator.generateRandomArray(n, n);
Integer[] arr2 = Arrays.copyOf(arr, arr.length);
Integer[] arr3 = Arrays.copyOf(arr, arr.length);
Integer[] arr4 = Arrays.copyOf(arr, arr.length);
Integer[] arr5 = Arrays.copyOf(arr, arr.length);
SortingHelper.sortTest("MergeSort", arr);
SortingHelper.sortTest("QuickSort2Ways", arr2);
SortingHelper.sortTest("QuickSort3Ways", arr3);
SortingHelper.sortTest("HeapSort", arr4);
}
}
6.冒泡排序
import java.util.Arrays;
public class BubbleSort {
private BubbleSort(){}
public static <E extends Comparable<E>> void sort(E[] data){
for(int i = 0; i + 1 < data.length; i ++){
// arr[0, i) 已排好序
// 通过冒泡在 arr[i] 位置放上合适的元素
for(int j = data.length - 1; j > i; j --)
if(data[j - 1].compareTo(data[j]) > 0)
swap(data, j - 1, j);
}
}
public static <E extends Comparable<E>> void sort2(E[] data){
for(int i = 0; i + 1 < data.length; i ++){
// arr[0, i) 已排好序
// 通过冒泡在 arr[i] 位置放上合适的元素
boolean isSwapped = false;
for(int j = data.length - 1; j > i; j --)
if(data[j - 1].compareTo(data[j]) > 0){
swap(data, j - 1, j);
isSwapped = true;
}
if(!isSwapped) break;
}
}
public static <E extends Comparable<E>> void sort3(E[] data){
for(int i = 0; i + 1 < data.length; ){
// arr[0, i) 已排好序
// 通过冒泡在 arr[i] 位置放上合适的元素
int lastSwappedIndex = data.length - 1;
for(int j = data.length - 1; j > i; j --)
if(data[j - 1].compareTo(data[j]) > 0){
swap(data, j - 1, j);
lastSwappedIndex = j - 1;
}
i = lastSwappedIndex + 1;
}
}
private static <E> void swap(E[] arr, int i, int j){
E t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
public static void main(String[] args) {
int n = 100000;
Integer[] arr = ArrayGenerator.generateRandomArray(n, n);
Integer[] arr2 = Arrays.copyOf(arr, arr.length);
Integer[] arr3 = Arrays.copyOf(arr, arr.length);
System.out.println("Random Array");
SortingHelper.sortTest("BubbleSort", arr);
SortingHelper.sortTest("BubbleSort2", arr2);
SortingHelper.sortTest("BubbleSort3", arr3);
System.out.println();
arr = ArrayGenerator.generateOrderedArray(n);
arr2 = Arrays.copyOf(arr, arr.length);
arr3 = Arrays.copyOf(arr, arr.length);
System.out.println("Ordered Array");
SortingHelper.sortTest("BubbleSort", arr);
SortingHelper.sortTest("BubbleSort2", arr2);
SortingHelper.sortTest("BubbleSort3", arr3);
}
}
7.希尔排序
import java.util.Arrays;
public class ShellSort {
private ShellSort(){}
public static <E extends Comparable<E>> void sort(E[] data){
int h = data.length / 2;
while(h >= 1){
for(int i = h; i < data.length; i ++){
E t = data[i];
int j;
for(j = i; j - h >= 0 && t.compareTo(data[j - h]) < 0; j -= h)
data[j] = data[j - h];
data[j] = t;
}
h /= 2;
}
}
public static void main(String[] args) {
int n = 1000000;
Integer[] arr = ArrayGenerator.generateRandomArray(n, n);
Integer[] arr2 = Arrays.copyOf(arr, arr.length);
SortingHelper.sortTest("ShellSort", arr);
SortingHelper.sortTest("MergeSort", arr2);
}
}