分治的基本概念
把一个任务,分为形式和原任务相同,但是规模更小的几个部分任务,分别完成,或只需要选一部分完成。然后再处理完成后的这一个或几部分的结果,实现整个任务的完成。
分治的生活例子——称假币
分治的典型应用:归并排序
数组排序任务可以如下完成:
- 把前一半排序
- 把后一半排序
- 把两半归并到一个新的有序数组,然后再拷贝回原数组,排序完成。
代码实现:
#include<iostream> using namespace std; void Merge(int a[], int s, int m, int e, int tmp[]) {//将数组a的局部a[s,m]和a[m+1,c]合并到tmp,并保证tmp有序,然后再拷贝回a[s,m] int pb = 0; int p1 = s, p2 = m + 1;//p1是指向前一半的指针,p2是指向后一半的指针 while (p1 <= m && p2 <= e)//做两个指针指向元素大小的比较,将较小值赋给tmp { 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]; } 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); } } int main() { int a[10] = { 13, 27, 19, 2, 8, 12, 2, 8, 30, 89 }; int b[10]; int size = sizeof(a) / sizeof(int); MergeSort(a, 0, size - 1, b); for (int i = 0; i < size; i++) cout << a[i] << ","; cout << endl; return 0; }
分治的典型应用:快速排序
数组排序任务可以如下完成:
- 设k=a[0],将k挪到适当位置,使得比k小的元素都在k左边,比k大的元素都在k右边,和k相等的,不关心在k左右均可
- 把k左边的部分快速排序
- 把k右边的部分快速排序
代码实现
#include<iostream> using namespace std; void swap(int &a, int &b) { int tmp = a; a = b; b = tmp; } void QuickSort(int a[], int s, int e) { if (s >= e) return; int k = a[s]; int i = s, j = e; while (i != j) { while (j > i&&a[j] >= k) j--; swap(a[i], a[j]); while (i < j&&a[i] <= k) i++; swap(a[i], a[j]); }//处理完毕后,a[i]=k QuickSort(a, s, i - 1); QuickSort(a, i + 1, e); } int main() { int a[] = { 93, 27, 30, 2, 8, 12, 2, 8, 30, 89 }; int size = sizeof(a) / sizeof(int); QuickSort(a, 0, size - 1); for (int i = 0; i < size; i++) cout << a[i] << ","; cout << endl; return 0; }
分治的典型应用:输出前m大的数
例 求排列的逆序数
本人有点不会做这个,希望读者有好的想法可以交流一下~~