首页 > 技术文章 > 分治法

aimojun 2016-09-05 22:50 原文

 

分治法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题相互独立且与原问题相同。递归的解这些子问题,然后将各子问题的解合并得到原问题的解。

分治法所能解决的问题一般具有以下几个特征:
  1) 该问题的规模缩小到一定的程度就可以容易地解决
  2) 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质。
  3) 利用该问题分解出的子问题的解可以合并为该问题的解;
  4) 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。

分治法的基本步骤:
分治法在每一层递归上都有三个步骤:
  分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;
  解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题;
  合并:将各个子问题的解合并为原问题的解。

1>二分查找/折半查找
2>归并排序
3>汉诺塔
4>棋盘策略
5>快速排序
6>循环赛

那么开始吧,折半查找:

 

#include <iostream>
using namespace std;
//二分查找,折半查找

int mid_search(int s[], int left, int right,int find) {  //s[]存放所有待查询的数据
	                                                     // left左边界,right右边界
	int mid = (left + right) / 2;                        //find要查询的数
	for (; left <= right;) {
		if (find < s[mid]) {         //范围缩小到左半区
			right = mid - 1;
		}
		else if (find == s[mid]) {    //找到,递归不再向下
			return mid;
		}
		else {                      //范围缩小到右半区
			left = mid + 1;
		}
		mid = (left + right) / 2;
	}
	if (left >= right) {
		cout << "没有找到!" << endl;
		return -1;
	}

}

int main()
{
	while (1) {
		int s[100], k, j;
		cout << "请输入所有可以查询的数字(-1代表结束):" << endl;  //要按数字大小输入
		cin >> k;
		j = 0;
		while (k != -1) {
			s[j++] = k;
			cin >> k;
		}
		cout << "输入要查询的数字:" << endl;
		int i, m;
		cin >> i;

		m = mid_search(s, 0, j - 1, i);
		if (m != -1) {
			cout << "是左边起第" << m << "个数字(从0开始)" << endl;
		}
		system("pause");
	}
	return 0;
}

归并排序:

 汉诺塔:

#include <iostream>
using namespace std;

void h_sort( int n, char h1, char h2, char h3) {

	if (n == 1) {
		cout <<h1<<"->"<<h3<< endl;
	}
	else
	{
		//B,C互换
		h_sort( n - 1, h1,h3,h2);
		cout << h1 << "->"<<h3 << endl;
		h_sort( n - 1,h2,h1,h3);
	}
}

int main()
{
	while (1) {
		cout << "请输入盘子个数:" << endl;
		int m = 0;
		cin >> m;
		h_sort( m, 'A', 'B', 'C');
		
	}
	return 0;
}

  

推荐阅读