分治

分治的基本概念

把一个任务,分为形式和原任务相同,但是规模更小的几个部分任务,分别完成,或只需要选一部分完成。然后再处理完成后的这一个或几部分的结果,实现整个任务的完成。

分治的生活例子——称假币


分治的典型应用:归并排序

数组排序任务可以如下完成:

  1. 把前一半排序
  2. 把后一半排序
  3. 把两半归并到一个新的有序数组,然后再拷贝回原数组,排序完成。

代码实现:

#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;
}

分治的典型应用:快速排序

数组排序任务可以如下完成:

  1. 设k=a[0],将k挪到适当位置,使得比k小的元素都在k左边,比k大的元素都在k右边,和k相等的,不关心在k左右均可
  2. 把k左边的部分快速排序
  3. 把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大的数




例 求排列的逆序数





本人有点不会做这个,希望读者有好的想法可以交流一下~~











猜你喜欢

转载自blog.csdn.net/qq_42020563/article/details/80607694