排序_01

排序动画 https://visualgo.net/zh/sorting

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

posted @ 2021-11-28 15:10  哟喝  阅读(22)  评论(0)    收藏  举报