把一个任务,分成形式和原任务相同,但规模更小的几个部分任务(通常是两个部分),分别完成,或只需要选一部完成。然后再处理完成后的这一个或几个部分的结果,实现整个任务的完成。
数组排序任务可以如下完成:
1) 把前一半排序
2)把后一半排序
3)把两半归并到一个新的有序数组,然后再拷贝回原数组,排序完成。
public class _27归并排序 {
static int[] a = {13,27,19,2,8,30,89};
static int[] b = new int[10];
public static void main(String[] args) {
int size = a.length;
MergeSort(a, 0, size-1, b);
for (int i=0; i<size; ++i) {
System.out.print(a[i] + " ");
}
System.out.println();
}
static void MergeSort(int[] a, int s, int e, int[] tmp) {
if (s < e) {
int m = s + (e-s)/2;
MergeSort(a, s, m, tmp);
MergeSort(a, m+1, e, tmp);
Merge(a, s, m, e, tmp); // 二分归并
}
}
static void Merge(int[] a, int s, int m, int e, int[] tmp) {
int pb = 0;
int p1 = s;
int p2 = m + 1;
while (p1 <= m && p2 <= e) {
if (a[p1] < a[p2]) {
tmp[pb++] = a[p1++];
} else {
tmp[pb++] = a[p2++];
}
}
while (p1 <= m) {
tmp[pb++] = a[p1++];
}
while (p2 <= e) {
tmp[pb++] = a[p2++];
}
for (int i=0; i<e-s+1; ++i) {
a[s+i] = tmp[i];
}
}
}
数组排序任务可以如下完成:
1)设k=a[0], 将k挪到适当位置,使得比k小的元素都 在k左边,比k大的元素都在k右边,和k相等的,不关心在k左右出现均可(O(n)时间完成)
2)把k左边的部分快速排序
3)把k右边的部分快速排序
public class _28快速排序 {
static int[] a = {93, 27, 30, 2, 8, 12, 2, 8, 30, 89};
public static void main(String[] args) {
int size = a.length;
QuickSort(a, 0, size-1);
for (int i=0; i<size; ++i) {
System.out.print(a[i] + " ");
}
System.out.println();
}
static void QuickSort(int[] a, int s, int e) {
if ( s >= e) {
return;
}
int k = a[s];
int i = s;
int j = e;
while (i != j) {
while (j>i && a[j] >= k) { // 先找右边 找比K小的 相等的不用处理
--j;
}
swap(i, j);
while (i<j && a[i] <= k) { // 再找左边 找比k大的 相等的不用处理
++i;
}
swap(i, j);
}
QuickSort(a, s, i-1);
QuickSort(a, i+1, e);
}
static void swap(int i, int j) {
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}