简单排序(冒泡、插入),希尔排序,堆排序,归并排序
9.1 简单排序



package bobo;
import java.util.Arrays;
public class BubbleSort {
public static void main(String[] args) {
int[] arr = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
BubbleSort bubbleSort = new BubbleSort();
bubbleSort.sort(arr);
System.out.println(Arrays.toString(arr));
}
public void sort(int[] arr) {
int N = arr.length;
for (int i = N - 1; i >= 0; i--) {
int flag = 0;
for (int j = 0; j < i; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
flag = 1;
}
}
if (flag == 0) break;
}
}
}

package bobo;
import java.util.Arrays;
public class SimpleSort {
public static void main(String[] args) {
int[] arr = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
SimpleSort simpleSort = new SimpleSort();
simpleSort.sort(arr, arr.length);
System.out.println(Arrays.toString(arr));
}
private void sort(int[] arr, int N) {
int i = 0;
int j = 0;
for (i = 0; i < N; i++) {
if (i == 0) continue; // 第一次摸牌不用排序
int temp = arr[i]; // 先记住牌的大小
for (j = i; j > 0 && arr[j - 1] > temp; j--) { // 从后往前看已知的排,看看应该排在哪里
arr[j] = arr[j - 1]; // 往后移出空位
}
arr[j] = temp; // 新牌落位
}
}
}
9.2 希尔排序



package bobo;
import java.util.Arrays;
public class ShellSort {
public static void main(String[] args) {
ShellSort shellSort = new ShellSort();
int[] arr = {10, 9, 9, 8, 7, 6, 5, 4, 3, 2, 1};
shellSort.sort(arr, arr.length);
System.out.println(Arrays.toString(arr));
}
private void sort (int[] arr, int N) {
int D = 0; // D间隔
for (D = N / 2; D > 0; D /= 2) { /* 希尔增量序列 */
int i = 0;
int j = 0;
for (i = 0; i < N; i++) { // 【注意】i++。也就是说,虽然间隔着D在排序,但并不是完整排完一组才排下一组
if (i < D) continue; // 第一次摸牌不用排序 // 【注意】在插入排序的基础上,改1为D、改-1为-D
int temp = arr[i]; // 先记住牌的大小
for (j = i; j >= D && arr[j - D] > temp; j -= D) { // 从后往前看已知的排,看看应该排在哪里
arr[j] = arr[j - D]; // 往后移出空位
}
arr[j] = temp; // 新牌落位
}
}
}
}
希尔排序的形象展示过程可以参考:希尔排序 | 算法必看系列九
9.3 堆排序

选择排序
package bobo;
import java.util.Arrays;
public class SelectionSort {
public static void main(String[] args) {
int[] arr = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
SelectionSort selectionSort = new SelectionSort();
selectionSort.sort(arr, arr.length);
System.out.println(Arrays.toString(arr));
}
private void sort(int[] arr, int N) {
for (int i = 0; i < N; i++) {
// 每一趟,找到最小元所在的位置pos
int MinPosition = scanForMin(arr, i, N - 1);
// 把最小元放到有序部分的最后面(第i次会放在第i个位置)
int temp = arr[i];
arr[i] = arr[MinPosition];
arr[MinPosition] = temp;
}
}
private int scanForMin (int[] arr, int start, int end) {
int pos = start;
for (int i = start + 1; i <= end; i++) { // 注意起始位置都是可达的
if (arr[i] < arr[pos]) pos = i;
}
return pos; // 返回最小元所在的位置pos
}
}
堆排序
思路1
调成最小堆,然后依次弹出,得到的就是从小到大排序
思路2
调成最大堆,然后把堆顶放到最后,固定住,堆的大小-1


注:PercDown(A, i, N)的含义是:
下滤:将大小为N的数组A中,以A->Data[i]为根的子堆,调整为最大堆
A: 堆 (用数组表示)
i: 下标
N: 堆的规模 (数组的大小)
基础:建立最大堆 (将数组调整成最大堆) (C)
/*----------- 建造最大堆 -----------*/
void PercDown( MaxHeap H, int p )
{ /* 【√】下滤:将H中以H->Data[p]为根的子堆调整为最大堆 */
int Parent, Child;
ElementType X;
X = H->Data[p]; /* 取出根结点存放的值 */
for( Parent=p; Parent*2<=H->Size; Parent=Child ) {
Child = Parent * 2;
if( (Child!=H->Size) && (H->Data[Child]<H->Data[Child+1]) )
Child++; /* Child指向左右子结点的较大者 */
if( X >= H->Data[Child] ) break; /* 找到了合适位置 */
else /* 下滤X */
H->Data[Parent] = H->Data[Child];
}
H->Data[Parent] = X;
}
void BuildHeap( MaxHeap H )
{ /* 调整H->Data[]中的元素,使满足最大堆的有序性 */
/* 这里假设所有H->Size个元素已经存在H->Data[]中 */
int i;
/* 【√】从最后一个结点的父节点开始,到根结点1 */
for( i = H->Size/2; i>0; i-- )
PercDown( H, i );
}
堆排序 (Java)
package bobo;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.Queue;
public class HeapSort {
private void sort(int[] arr, int N) {
Queue<Integer> heap = new PriorityQueue<>(); // 用Java的优先队列建立堆
for (int i = 0; i < N; i++) {
heap.add(arr[i]); // 默认是小顶堆
}
for (int i = 0; i < N; i++) {
arr[i] = heap.remove(); // 逐个从堆顶弹出
}
}
public static void main(String[] args) {
int[] arr = {10, 9, 8, 7, 7, 6, 5, 4, 3, 2, 1};
HeapSort heapSort = new HeapSort();
heapSort.sort(arr, arr.length);
System.out.println(Arrays.toString(arr));
}
}
Java直接调用优先队列PriorityQueue的话,很方便。
但是注意到,Java的PriorityQueue默认是一个小顶堆,如果要大顶堆的话,可以重写Comparator方法,或者是用负值。
final int DEFAULT_INITIAL_CAPACITY = 10;
Queue<Integer> heap = new PriorityQueue<>(DEFAULT_INITIAL_CAPACITY, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
}); // 用Java的优先队列建立堆

9.4 归并排序
