分治思想与应用
分治
分治算法就是分而治之。分治分治,分为两部分,分和治。
分:
划分子问题,讲一个问题划分成若干个独立的具有共性的子问题。
治:
求解每个子问题。
分解:
分解子问题的原则:
- 子问题与原问题性质相似。
- 子问题规模较小(有解)
合并:把每个子问题的解合并成原问题的解
适用场景
- 在一个较小规模上得到解
- 该问题上有最有子结构
- 每个子问题的解,可以合并为原问题的解
例题1:二分查找: (适合有序顺序表)
给定一个升序有序数组,要求找到到值为key的元素的位置,若没有则返回-1。
#include "iostream"
using namespace std;
int halfSearch(int Data[], int low, int high, int key);
int main()
{
int n[] = {1,2,3,4,5,6,7,8};
int k;
cout << "Please Input Key:";
cin >> k;
cout << halfSearch(n, 0, sizeof(n)/sizeof(n[0]), k);
return 0;
}
//high = length
//递归
int halfSearch(int Data[], int low, int high, int key){
int mid = (low + high) / 2;
if (low <= high){
if (Data[mid] < key)
halfSearch(Data, mid + 1, high, key);
else if (Data[mid] > key)
halfSearch(Data, low, mid-1, key);
else if (Data[mid] == key)
return mid;
}
else
return -1;
}
例题2:返回X的n次方
#include "iostream"
using namespace std;
int Power(int x, int n);
int main(int argc, char const *argv[])
{
int x1, n1;
cout << "Please Input x and n:";
cin >> x1 >> n1;
cout << "Power(x,n) is " << Power(x1,n1) << endl;
return 0;
}
int Power(int x, int n){
int result;
if ( n == 1)
return x;
if ( n%2 == 0 )
result = Power(x, n/2)*Power(x, n/2);
else
result = Power(x, (n - 1)/2)*Power(x, (n+1)/2);
return result;
}
例题3:归并排序 (二路归并)
给定一个无序顺序表,请使用分治思想,将其排序。
#include "iostream"
#include "string"
using namespace std;
void Marge_Sort(int a[], int low, int high, int *tmp);
void Print(int a[], int length);
int main(int argc, char const *argv[])
{
int a1[] = {3,2,8,5,4,7,6,9};
int *tmp, n;
n = sizeof(a1)/sizeof(a1[0]);
tmp = (int *)malloc(n*sizeof(a1[0]));
Marge_Sort(a1, 0, n-1, tmp);
free(tmp);
Print(a1, n);
return 0;
}
void Marge_Sort(int a[], int low, int high, int *tmp){
int i, j, k;
if (low < high){
// 分:
int mid = (low + high) / 2;
Marge_Sort(a, low, mid, tmp);
Marge_Sort(a, mid + 1, high, tmp);
// 治:
for (k = 0, i = low, j = mid + 1; i < mid + 1 && j < high + 1;){
if (a[i] < a[j])
tmp[k++] = a[i++];
else
tmp[k++] = a[j++];
}
while(i < mid+1)
tmp[k++] = a[i++];
while(j < high + 1)
tmp[k++] = a[j++];
memcpy((void*)(a + low), (void *)tmp, (high - low + 1)*sizeof(a[0]));
}
}
void Print(int a[], int length){
int i = 0;
while (i < length)
cout << a[i++] << " ";
cout << endl;
}