您的位置:首页 > 其它

Sort and Shuffle 排序和打乱

2015-07-20 15:22 441 查看
排序可视化

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;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: