Sort and Shuffle 排序和打乱
2015-07-20 15:22
441 查看
排序可视化
排序基于Decision Tree,算法至少NlogN。
In-place是说sort用的memory不超过 c*logN.
凡是长距离swap的都是unstable的。
HeapSort 对于cash memory的利用很差,特别是大数组的情况。
O(N) = O(N/2)+O(N/2)+N
Divide and Conquer 方法。aux作为辅助数组用于暂存,只作一次声明。less(后,前)来保证stable。每次merge后要将aux拷贝回原array。
优化:
1. 当数组长度小于8时用插入排序。
2. 两段排序后,当第一段最后的元素不大于第二段第一个元素时,不用merge。
树形结构自下而上,每两个相邻大小为size的数组进行归并。end要注意,最后一个数组大小够不够size。
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 { @Override public <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 { @Override public <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 { @Override public <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 @Override public <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 ****/ @Override public <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; // 建立heap for (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为左child int 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 { @Override public <T> void shuffle(T[] array) { int N = array.length; HashMap<Double, T> map = new HashMap<Double, T>(); double[] val = new double ; 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; } @Override public <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 < b public 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 array public default <T> void swap(T[] array, int i, int j) { T temp = array[i]; array[i] = array[j]; array[j] = temp; } // Sort method public <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 { @Override public <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]; } @Override public <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; } }
相关文章推荐
- Fly-By Topology
- keySet 与entrySet 遍历HashMap性能差别
- http://sass-lang.com/documentation/Sass/Script/Functions.html
- GTK中如何捕捉和屏蔽按键信号(如F10等)
- 光标
- 可穿戴设备(CC2541)上微信(8)
- 【W3s学JSON】JSON入门概念学习笔记 _W3school
- Windows Azure Virtual Machine (24) Azure VM支持多网卡功能
- Decorator Pattern
- 解决Ubuntu Server 12.04换了网卡MAC地址后 网络不可用的问题.
- Swift 学习之二十一:?和 !(详解)
- c#怎样将object转换过程int型
- Is memcached a dinosaur in comparison to Redis?
- Java通过JNI调用C++
- 每天一个linux命令(37):date命令
- SQL Server中的高可用性---概念
- 常见异常
- wax
- CentOS6.5下编译安装LAMP环境
- Angular.js学习笔记