递归与分治[2019.5.25]
1、 $\sqrt {\rm{n}} $段合并排序算法:
将数组a[0,n-1]划分为$\sqrt {\rm{n}} $个子数组,每个子数组有O($\sqrt {\rm{n}} $)个元素。然后递归地对分割后的子数组进行排序,最后将所得到的$\left\lfloor {\sqrt {\rm{n}} } \right\rfloor $个排好序的子数组合并排序。
分治算法基本思想
将数组分为$\sqrt {\rm{n}} $个子问题,递归的结束条件为根号子问题规模≤1,根据根号下内容不同,分为1、2、3),对于问题排序,然后归并。
Code:
#include <bits/stdc++.h> using namespace std; void sort_2_3(int* arr, int p, int q){ int num = q - p + 1; if(num == 2){ cout<<"sort_2_3 2:"<<arr[p]<<","<<arr[p+1]<<endl; if(arr[p] > arr[p+1]){ int tmp = arr[p]; arr[p] = arr[p+1]; arr[p+1] = tmp; } cout<<"sort_2_3 2:"<<arr[p]<<","<<arr[p+1]<<endl; } else if(num == 3){ cout<<"sort_2_3 3:"<<arr[p]<<","<<arr[p+1]<<","<<arr[p+2]<<endl; int Min = arr[p]; int Max = arr[p]; int min_i = 0; int max_i = 0; for(int index=0; index<3; index++){ if(arr[p + index] < Min){ Min = arr[p + index]; min_i = index; }else if(arr[p + index] > Max){ Max = arr[p + index]; max_i = index; } } int Mid = arr[ p + 3 - min_i - max_i ]; arr[p] = Min; arr[p + 1] = Mid; arr[p + 2] = Max; cout<<"sort_2_3 3:"<<arr[p]<<","<<arr[p+1]<<","<<arr[p+2]<<endl; } } void Merge(int*arr, int p, int q){ cout<<"merge:"<<p<<","<<q<<endl; for(int i=p;i<=q;i++){ cout<<arr[i]<<" "; } cout<<endl; int n = q - p + 1; int num = int(sqrt(n)); //开辟暂存空间 int i=0; vector<vector<int> > tmps (num); for(; i< num- 1; i++){ tmps[i].resize(num + 1); } tmps[i].resize(n - i*num + 1); //初始化数据 for(i=0; i < num - 1; i++){ int j=0; for(; j < num; j++){ tmps[i][j] = arr[p + i*num + j]; } tmps[i][j] = INT_MAX; } int in = 0; for(; in < n - i * num; in++) tmps[i][in] = arr[p + i*num + in]; tmps[i][in] = INT_MAX; cout<<"初始化数据:"<<endl; for(int i=0; i<num;i++){ for(int j=0;j<tmps[i].size();j++){ cout<<tmps[i][j]<<" "; } cout<<endl; } cout<<"初始化数据."<<endl; //每行标记 int poses[num]; for(int i=0; i<num ;i++){ poses[i]=0; } //比较 int Min = tmps[0][0]; int index_row = 0; for(i=p; i<=q; i++){ for(int j=0; j<num; j++){ if(tmps[j][poses[j]] < Min){ Min = tmps[j][poses[j]]; index_row = j; } } arr[i] = tmps[index_row][poses[index_row]]; Min = tmps[index_row][poses[index_row] + 1]; poses[index_row]++; } for(int i=p;i<=q;i++){ cout<<arr[i]<<" "; } cout<<endl; } void sqrt_n_sort(int* arr, int p, int q){ cout<<"deviation"<<endl; int n = q -p + 1; int num = int(sqrt(n)); if(num > 1){ int i=0; for(;i < num -1 ; i++){ cout<<p + num*i<<","<<p + num*(i+1) - 1<<endl; sqrt_n_sort(arr, p + num*i, p + num*(i+1) - 1 ); } cout<<p + num*i<<","<<q<<endl; sqrt_n_sort(arr, p + num*i, q); Merge(arr, p, q); }else{ sort_2_3(arr,p,q); } } int main(){ int arr[10] = {1,2,3,4,5,6,7,8,9,10}; sqrt_n_sort(&arr[0], 0, 9); for(int i=0; i<10; i++){ cout<<arr[i]<<" "; } return 0; }
2、 用分治法设计一个算法,在数组A中寻找最大元素和最小元素
将数组a[0,n-1]划分为$\sqrt {\rm{n}} $个子数组,每个子数组有O($\sqrt {\rm{n}} $)个元素。然后递归地对分割后的子数组进行排序,最后将所得到的$\left\lfloor {\sqrt {\rm{n}} } \right\rfloor $个排好序的子数组合并排序。排序后即可得到max与min。
#include <bits/stdc++.h> using namespace std; void sort_2_3(int* arr, int p, int q, int* arr_min_max){ int num = q - p + 1; int len = 0; if(num == 2){ len = 2; }else if(num == 3){ len = 3; } for(int i=p; i < p + len; i++){ if(arr[i] < arr_min_max[0]){ arr_min_max[0] = arr[i]; } if(arr[i] > arr_min_max[1]){ arr_min_max[1] = arr[i]; } } } void sqrt_n_sort(int* arr, int p, int q, int* arr_min_max){ cout<<"deviation"<<endl; int n = q -p + 1; int num = int(sqrt(n)); if(num > 1){ int i=0; for(;i < num -1 ; i++){ cout<<p + num*i<<","<<p + num*(i+1) - 1<<endl; sqrt_n_sort(arr, p + num*i, p + num*(i+1) - 1, arr_min_max); } cout<<p + num*i<<","<<q<<endl; sqrt_n_sort(arr, p + num*i, q, arr_min_max); }else{ sort_2_3(arr,p,q,arr_min_max); } } int main(){ int arr[10] = {1,2,3,4,5,6,7,8,9,10}; int arr_min_max[2] = {INT_MAX,INT_MIN}; sqrt_n_sort(&arr[0], 0, 9, &arr_min_max[0]); cout<<"min:"<<arr_min_max[0]<<" max:"<<arr_min_max[1]<<endl; return 0; }