Sort and Shuffle 排序和打乱

来源:互联网 发布:java web小项目下载 编辑:程序博客网 时间:2024/05/16 09:31

排序可视化

Sort 排序:


定义数组排序的基本方法:

public abstract class ArraySort {public static boolean INCREASE = true;public static boolean DECREASE = false;protected static <T extends Comparable<? super T>> boolean compare(T a,T b, boolean order, Comparator<T> comparator) {int cmp = COMPARE(a, b, comparator);if (order == INCREASE) {return cmp < 0;} else {return cmp > 0;}}public static <T extends Comparable<? super T>> int COMPARE(T a, T b,Comparator<T> comparator) {if (comparator != null) {return comparator.compare(a, b);} else {return a.compareTo(b);}}protected static void swap(Object[] array, int i, int j) {Object temp = array[i];array[i] = array[j];array[j] = temp;}public static <T extends Comparable<? super T>> boolean isSorted(T[] array) {return isSorted(array, INCREASE, null);}public static <T extends Comparable<? super T>> boolean isSorted(T[] array,boolean order) {return isSorted(array, order, null);}public static <T extends Comparable<? super T>> boolean isSorted(T[] array,Comparator<T> comparator) {return isSorted(array, INCREASE, comparator);}public static <T extends Comparable<? super T>> boolean isSorted(T[] array,boolean order, Comparator<T> comparator) {for (int i = 1; i < array.length; i++) {if (compare(array[i], array[i - 1], order, comparator)) {return false;}}return true;}public <T extends Comparable<? super T>> void sort(T[] array) {sort(array, INCREASE, null);}public <T extends Comparable<? super T>> void sort(T[] array, boolean order) {sort(array, order, null);}public <T extends Comparable<? super T>> void sort(T[] array,Comparator<T> comparator) {sort(array, INCREASE, comparator);}public abstract <T extends Comparable<? super T>> void sort(T[] array,boolean order, Comparator<T> comparator);}

排序基于Decision Tree,算法至少NlogN。

In-place是说sort用的memory不超过 c*logN.

凡是长距离swap的都是unstable的。

HeapSort 对于cash memory的利用很差,特别是大数组的情况。


1. Selection Sort 选择排序:

每次在剩余的元素中选择最小的,和当前待定排序位置的元素交换位置。Unstable, in-place, O(N^2)

public class SelectionSort extends ArraySort {@Overridepublic <T extends Comparable<? super T>> void sort(T[] array,boolean order, Comparator<T> comparator) {for (int i = 0; i < array.length - 1; i++) {int base = i;for (int j = i + 1; j < array.length; j++) {if (compare(array[j], array[base], order, comparator)) {base = j;}}swap(array, i, base);}}}

2. Insertion Sort 插入排序:

每次将当前元素放到已排序队列的合适位置,利用元素交换,自后向前,逐个比较。Stable, in-palce, O(N^2)

public class InsertionSort extends ArraySort {@Overridepublic <T extends Comparable<? super T>> void sort(T[] array,boolean order, Comparator<T> comparator) {for (int i = 1; i < array.length; i++) {int j = i;while (j > 0) {if (compare(array[j], array[j - 1], order, comparator)) {swap(array, j, j - 1);--j;} else {break;}}}}}

3. Shell Sort:

每次将给定间隔的元素进行插入排序,间隔为3x+1。 Unstable, in-place, O(N^1.5)

public class ShellSort extends ArraySort {@Overridepublic <T extends Comparable<? super T>> void sort(T[] array,boolean order, Comparator<T> comparator) {int N = array.length;int step = 1;while (step < N / 3) {step = 3 * step + 1;}while (step >= 1) {for (int i = step; i < N; i++) {for (int j = i; j >= step&& compare(array[j], array[j - step], order, comparator); j -= step) {swap(array, j, j - step);}}step = step / 3;}}}


4. Merge Sort  归并排序:

树形结构,依次将两个有序数组合并成一个。Stable, O(NlgN)

O(N) = O(N/2)+O(N/2)+N

Top-down 递归:

public class MergeSort extends ArraySort {// Recursive Merge Sort@Overridepublic <T extends Comparable<? super T>> void sort(T[] array,boolean order, Comparator<T> comparator) {@SuppressWarnings("unchecked")T[] aux = (T[]) new Comparable[array.length];sort(array, aux, 0, array.length - 1, order, comparator);}private static <T extends Comparable<? super T>> void merge(T[] array,T[] aux, int start, int mid, int end, boolean order,Comparator<T> comparator) {int i = start;int j = mid + 1;int k = start;while (true) {if (compare(array[j], array[i], order, comparator)) {aux[k++] = array[j++];} else {aux[k++] = array[i++];}if (i == mid + 1) {while (j <= end) {aux[k++] = array[j++];}break;}if (j == end + 1) {while (i <= mid) {aux[k++] = array[i++];}break;}}System.arraycopy(aux, start, array, start, end - start + 1);}private static <T extends Comparable<? super T>> void sort(T[] array,T[] aux, int start, int end, boolean order, Comparator<T> comparator) {if (end - start + 1 < 8) {insertionSort(array, start, end, order, comparator);return;}int mid = start + ((end - start) >> 1);sort(array, aux, start, mid, order, comparator);sort(array, aux, mid + 1, end, order, comparator);if (!compare(array[mid + 1], array[mid], order, comparator)) {return;}merge(array, aux, start, mid, end, order, comparator);}private static <T extends Comparable<? super T>> void insertionSort(T[] array, int start, int end, boolean order,Comparator<T> comparator) {for (int i = start; i <= end; i++) {for (int j = i; j > 0; j--) {if (compare(array[j], array[j - 1], order, comparator)) {swap(array, j, j - 1);} else {break;}}}}}

Divide and Conquer 方法。aux作为辅助数组用于暂存,只作一次声明。less(后,前)来保证stable。每次merge后要将aux拷贝回原array。

优化:

1. 当数组长度小于8时用插入排序。

2. 两段排序后,当第一段最后的元素不大于第二段第一个元素时,不用merge。

Bottom-up merge sort 非递归:

public static <T extends Comparable<? super T>> void sortBU(T[] array, boolean order, Comparator<T> comparator) {int N = array.length;@SuppressWarnings("unchecked")T[] aux = (T[]) new Comparable[array.length];for (int size = 1; size < N; size <<= 1) {for (int start = 0; start < N - size; start += size << 1) {merge(array, aux, start, start + size - 1, Math.min(start + (size << 1) - 1, N - 1), order, comparator);}}}

树形结构自下而上,每两个相邻大小为size的数组进行归并。end要注意,最后一个数组大小够不够size。

5. Quick Sort 快排:

每次分割两部分,左边都比分割点小,右边都比分割点大。

普通Quick Sort:

public class QuickSort extends ArraySort {/**** Normal Quick Sort ****/@Overridepublic <T extends Comparable<? super T>> void sort(T[] array, boolean order, Comparator<T> comparator) {sort(array, 0, array.length - 1, order, comparator);}private static <T extends Comparable<? super T>> void sort(T[] array,int start, int end, boolean order, Comparator<T> comparator) {if (end - start + 1 <= 10) {insertionSort(array, start, end, order, comparator);return;}int mid = partition(array, start, end, order, comparator);sort(array, start, mid - 1, order, comparator);sort(array, mid + 1, end, order, comparator);}private static <T extends Comparable<? super T>> int partition(T[] array,int start, int end, boolean order, Comparator<T> comparator) {int i = start;int j = end + 1;while (true) {// array[start] >= array[++i]while (compare(array[++i], array[start], order, comparator)) {if (i == end) {break;}}// array[start] < array[--j]while (compare(array[start], array[--j], order, comparator)) {if (j == start) {break;}}if (i >= j) {break;}swap(array, i, j);}swap(array, start, j);return j;}private static <T extends Comparable<? super T>> void insertionSort(T[] array, int start, int end, boolean order,Comparator<T> comparator) {for (int i = start; i <= end; i++) {for (int j = i; j > 0; j--) {if (compare(array[j], array[j - 1], order, comparator)) {swap(array, j, j - 1);} else {break;}}}}}

3-way Quick Sort:

循环中分割点一直移动,与分割点相等的元素会和分割点排在一起。有利于处理duplicate。
public static <T extends Comparable<? super T>> void sort3Way(T[] array,boolean order, Comparator<T> comparator) {sort3(array, 0, array.length - 1, order, comparator);}public static <T extends Comparable<? super T>> void sort3(T[] array,int start, int end, boolean order, Comparator<T> comparator) {if (end - start + 1 <= 10) {insertionSort(array, start, end, order, comparator);return;}int lt = start;int gt = end;T v = array[start];int i = start;while (i <= gt) {int cmp = COMPARE(array[i], v, comparator);if (order == INCREASE) {if (cmp < 0) {swap(array, lt++, i++);} else if (cmp > 0) {swap(array, i, gt--);} else {i++;}} else {if (cmp < 0) {swap(array, i, gt--);} else if (cmp > 0) {swap(array, lt++, i++);} else {i++;}}}sort3(array, start, lt - 1, order, comparator);sort3(array, gt + 1, end, order, comparator);}

6. 堆排序

建立最大堆,然后依次把堆顶元素放到末尾。

public static <T extends Comparable<T>> void sort(T[] array) {int tail = array.length - 1;// 建立heapfor (int i = array.length / 2 - 1; i >= 0; i--) {percolateDown(array, i, tail);}// 排序。依次将最大值移除堆放在数组末尾。通过tail控制堆大小while(tail > 0) {swap(array, 0, tail--);percolateDown(array, 0, tail);}}private static <T extends Comparable<T>> void percolateDown(T[] array, int k, int tail) {// 初始化max为左childint max = k * 2 + 1;if (max > tail) {return;}// 如果右child存在,且大,则max为右child。if (max + 1 <= tail && array[max + 1].compareTo(array[max]) > 0) {max = max + 1;}if (array[k].compareTo(array[max]) < 0) {swap(array, k, max);k = max;percolateDown(array, k, tail);}}private static <T> void swap(T[] array, int i, int j) {T temp = array[i];array[i] = array[j];array[j] = temp;}

Shuffle 打乱:

定义接口:

public interface MyShuffle {public <T> void shuffle(T[] array);}

1. Sort Shuffle 排序打乱:

将每个元素给定一个随机值,将值排序,则元素被打乱

public class SortShuffle implements MyShuffle {@Overridepublic <T> void shuffle(T[] array) {int N = array.length;HashMap<Double, T> map = new HashMap<Double, T>();double[] val = new double[N];for (int i = 0; i < N; i++) {val[i] = Math.random() + Math.random();map.put(val[i], array[i]);}Arrays.sort(val);for (int i = 0; i < N; i++) {array[i] = map.get(val[i]);}}}


2. Knuth Shuffle 逐步打乱:

每次当前元素和前面(含自身)的元素随机交换。

public class KnuthShuffle implements MyShuffle {public static <T> void swap(T[] array, int i, int j) {T temp = array[i];array[i] = array[j];array[j] = temp;}@Overridepublic <T> void shuffle(T[] array) {int N = array.length;Random rand = new Random();for (int i = 1; i < N; i++) {swap(array, i, rand.nextInt(i + 1));}}}

Select 选择:

在数组中选择大小为第k的数字。

定义接口:

public interface MySelect {// Check if a < bpublic default <T extends Comparable> boolean less(T a, T b) {// public default boolean less(Comparable a, Comparable b)return a.compareTo(b) < 0;}public default <T> boolean less(T a, T b, Comparator<T> comparator) {return comparator.compare(a, b) == -1;}// Swap i and j in arraypublic default <T> void swap(T[] array, int i, int j) {T temp = array[i];array[i] = array[j];array[j] = temp;}// Sort methodpublic <T> Comparable<T> select(Comparable<T>[] array, int k);public <T> T select(T[] array, int k, Comparator<T> comparator);}

1. Quick Select 快速选择:

基于Quick Select 快排。
public class QuickSelect implements MySelect {@Overridepublic <T> Comparable<T> select(Comparable<T>[] array, int k) {int start = 0;int end = array.length - 1;while (start < end) {int mid = partition(array, start, end);if (mid < k) {start = mid + 1;} else if (mid > k) {end = mid - 1;} else {return array[k];}}return array[k];}@Overridepublic <T> T select(T[] array, int k, Comparator<T> comparator) {int start = 0;int end = array.length - 1;while (start < end) {int mid = partition(array, start, end, comparator);if (mid < k) {start = mid + 1;} else if (mid > k) {end = mid - 1;} else {return array[k];}}return array[k];}private <T> int partition(Comparable<T>[] array, int start, int end) {int i = start;int j = end + 1;while (true) {// array[start] >= array[++i]while (less(array[++i], array[start])) {if (i == end) {break;}}// array[start] < array[--j]while (less(array[start], array[--j])) {if (j == start) {break;}}if (i >= j) {break;}swap(array, i, j);}swap(array, start, j);return j;}private <T> int partition(T[] array, int start, int end,Comparator<T> comparator) {int i = start;int j = end + 1;while (true) {// array[start] >= array[++i]while (less(array[++i], array[start], comparator)) {if (i == end) {break;}}// array[start] < array[--j]while (less(array[start], array[--j], comparator)) {if (j == start) {break;}}if (i >= j) {break;}swap(array, i, j);}swap(array, start, j);return j;}}



0 0
原创粉丝点击