问题:
将数组 a[0,n-1]划分为 根号n 个子数组,每个子数组有 O(根号n)个元素。然后递归地对分割后的子数组进行排序,最后将所得到的根号n 个排好序的子数组合并排序。
工具与语言
我选择的为VS Studio和C++语言。
分治算法基本思想
分治法的设计思想:
将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。
分治策略:
对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解决,然后将各子问题的解合并得到原问题的解。
本问题的解决思路为:
首先将问题分解为 根号n 个子问题。对每个子问题同样分解为 根号n 个子问题。当子问题足够小时便直接解决子问题不在分解,并始合并子问题。
映射到本问题则为对a[0,n-1]排序,首先将a[0,n-1]划分为 根号n 数组并对每个子数组进行排序,然后将子数组进行归并操作。对于每个子数组当问题规模仍然很大时,将其划分为 根号n 子数组,并对子数组进行排序,然后将子数组进行归并操作。当子数组问题规模足够小是直接解决此问题。
解决问题
#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
#pragma region 输入
int *input(int n)
{
int* arr = (int*)malloc(sizeof(int)*n);
for (int i = 0; i < n; i++)
{
arr[i] = rand();
}
return arr;
}
#pragma endregion
#pragma region 输出
void output(int* arr,int n)
{
for (int i = 0; i < n; i++)
{
cout << arr[i] << " ";
}
cout << endl;
}
#pragma endregion
#pragma region 排序
//选择排序
int sort(int* arr, int size)
{
if (size == 0)
{
return 0;
}
for (int i = 0; i < size; i++)
{
for (int j = i + 1; j < size; j++)
{
if (arr[j] < arr[i])
{
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
return 0;
}
//复制数组
void arrcopy(int*arrcopyform, int*arr1,int size)
{
for (int i = 0; i < size; i++)
{
arr1[i] = arrcopyform[i];
}
}
//归并
void Merging(int* arr, int first1,int last1,int first2,int last2) {
int size1 = last1 - first1;
int size2 = last2 - first2;
int* arr1 = (int*)malloc(sizeof(int)*size1);
int* arr2 = (int*)malloc(sizeof(int)*size2);
int* arr3;
if (first1 < first2)
{
arr3 = arr + first1;
}
else
{
arr3 = arr + first2;
}
arrcopy(arr + first1, arr1, size1);
arrcopy(arr + first2, arr2, size2);
int a = 0;
int p = 0;
int q = 0;//游标
while (p < size1 && q < size2)
{
if (arr1[p] < arr2[q])
{
arr3[a] = arr1[p];
p++;
a++;
}
else
{
arr3[a] = arr2[q];
q++;
a++;
}
}
if (p == size1)
{
while (q < size2)
{
arr3[a] = arr2[q];
a++;
q++;
}
}
else
{
while (p < size1)
{
arr3[a] = arr1[p];
a++;
p++;
}
}
free(arr1);
free(arr2);
}
void rsort(int* arr, int first, int last)
{
int size = last - first;
int sq = (int)sqrt(size);
if (size > 3)
{
int spfirst, splast;
for (int i = 0; i < sq - 1; i++)
{
spfirst = first+sq * i;
splast = spfirst + sq;
rsort(arr, spfirst, splast);
}
rsort(arr, splast, last);
}
else
{
int* tfirst = arr + first;
sort(tfirst, size);
}
int spfirst1 = first;
int splast1 = first + sq;
int spfirst2=first;
int splast2;
for (int i = 1; i < sq - 2; i++)
{
spfirst2 = first+sq * i;
splast2 = spfirst2 + sq;
Merging(arr, spfirst1, splast1, spfirst2, splast2);
splast1 += sq;
}
Merging(arr, spfirst1, splast1, splast1, last);
}
#pragma endregion
int main()
{
int n;
cin >> n;
cout << endl;
int* arr = input(n);
output(arr, n);
rsort(arr, 0, n);
cout<<"After Sorting."<<endl;
output(arr, n);
free(arr);
system("pause");
return 0;
}