排序_01
1.选择排序
public void selection(int[] a) {
int N = a.length;
for (int i = 0;i < N - 1;i++ ) {
int min = i;
// 找到最小的交换位置
for (int j = i + 1;j < N;j++ ) {
if (less(a[j],a[min])) {
min = j;
}
}
exec(a, i, min);
}
}
2.冒泡排序
public void bubble(int[] a) {
for (int i = 0; i < a.length - 1; i++) {
// 找到最大的,放后面
for (int j = 0; j < a.length - 1 - i; j++) {
if (less(a[j + 1], a[j])) {
exec(a, j + 1, j);
}
}
}
}
3.插入排序、希尔排序
public void Insertion(int[] a) {
int N = a.length;
for (int i = 1;i < N;i++ ) {
// 将a[i]插入到a[i-1]、a[i-2]、a[i-3] ...之中
for (int j = i;j >= 1 && less(a[j],a[j - 1]);j-- ) {
exec(a, j, j - 1);
}
}
}
// 先把数组变为h有序的数组,之后利用插入排序。加快了插入排序的速度
public static void Shell(Comparable[] a) {
int n = a.length;
// 3x+1 increment sequence: 1, 4, 13, 40, 121, 364, 1093, ...
int h = 1;
while (h < n/3) {
h = 3*h + 1;
}
while (h >= 1) {
// h-sort the array
for (int i = h; i < n; i++) {
for (int j = i; j >= h && less(a[j], a[j-h]); j -= h) {
exch(a, j, j-h);
}
}
h /= 3;
}
}
4. 归并排序
自顶向下的排序
Class Merge{
public static void sort(int[] a,int left,int right) {
if (right == left) {
// 只剩下一个元素,不再分解
return;
}
int mid = left + (right - left) / 2;
// sort left
sort(a, left, mid);
// sort right
sort(a, mid + 1, right);
merge(a, left, mid, right);
}
public static void merge(int[] a,int left,int mid,int right) {
// 定义辅助数组, 暂存排好序的数据
int[] help = new int[right - left + 1];
int i = 0;
// 左边数组指针
int p1 = left;
// 右边数组指针
int p2 = mid + 1;
while (p1 <= mid && p2 <= right) {
help[i++] = a[p1] < a[p2] ? a[p1++] : a[p2++];
}
// 跳出上一个while,肯定有一个已经遍历完毕
while (p1 <= mid) {
help[i++] = a[p1++];
}
while (p2 <= right) {
help[i++] = a[p2++];
}
// 合并到原数组
for (int i = 0;i < help.length ;i++ ) {
a[left+i] = help[i];
}
}
// pdf 210页 11/12
private static Comparable[] aux;
public static void merge(int[] a,int lo,int mid,int hi) {
// copy to aux[]
for (int k = lo; k <= hi; k++) {
aux[k] = a[k];
}
// merge back to a[]
// 左半边用尽(取右半边的元素)、右半边用尽(取左半边的元素)、
// 右半边的当前元素小于左半边的当前元素(取右半边的元素)
// 以及右半边的当前元素大于等于左半边的当前元素(取左半边的元素)。
int i = lo, j = mid+1;
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++];
}
}
}
5.快排
/**
* @Date 2021/11/28 10:54
*/
public class QuickSort {
public static void main(String[] args) {
int[] a = new int[]{5, 6, 10, 2, 3};
sort(a, 0, a.length - 1);
for (int i : a) {
System.out.println(i);
}
}
public static void sort(int a[], int left, int right) {
// 递归终止条件
if (right <= left) {
return;
}
// 划分过程
int j = partition(a, left, right);
sort(a, left, j - 1);
sort(a, j + 1, right);
}
public static int partition(int[] a, int left, int right) {
// 左右扫描指针 i, j
int i = left;
int j = right + 1;
// 主元素
int prim = a[left];
// 一遍扫描结束之后退出
while (true) {
// 扫描左右检查是否结束并交换元素
while (less(a[++i], prim))
if (i == right) break;
while (less(prim, a[--j]))
if (j == left) break;
if (i >= j) break;
exec(a, i, j);
}
// 将主元素放到 j 位置
exec(a, left, j);
return j;
}
private static void exec(int[] a, int i, int j) {
int t = a[i];
a[i] = a[j];
a[j] = t;
}
private static boolean less(int x, int y) {
return x < y;
}
}
基于三划分的改进
public class QuickSort {
public static void main(String[] args) {
int[] a = new int[]{5, 6, 10, 2, 3};
sort(a, 0, a.length - 1);
for (int i : a) {
System.out.println(i);
}
}
public static void sort(int a[], int left, int right) {
// 递归终止条件
if (right <= left) {
return;
}
// 划分过程
int[] p = partition(a, left, right);
sort(a, left, p[0] - 1);
sort(a, p[0] + 1, right);
}
public static int[] partition(int[] a, int left, int right) {
// 三划分: 小于区域 -- 等于区域 -- 大于区域
int less = left - 1;
int more = right;
//最后一个元素当主元素
while (left < more) {
if (less(a[left], a[right])) {
exec(a, ++less, left++);
} else if (less(a[right], a[left])) {
exec(a, --more, left);
} else {
left++;
}
}
// 主元素和大于区域的第一个元素交换位置
exec(a, more, right);
// 返回的是小于区域之后的第一个,和大于区域之前的那个
return new int[]{less + 1, more};
}
private static void exec(int[] a, int i, int j) {
int t = a[i];
a[i] = a[j];
a[j] = t;
}
private static boolean less(int x, int y) {
return x < y;
}
2021.11.28 15:08

浙公网安备 33010602011771号