有许多算法在结构上是递归的:为了解决一个给定问题,算法要一次或多次地调用其自身来解决相关的子问题。这些算法通常采用分治策略:将原问题分成n个规模较小而结构与原问题相似的子问题。递归地解这些子问题,然后合并其结果就得到原问题的解。N=2时的分治法又称二分法。
用分治法求解一个问题,所需的时间是由子问题的个数,大小以及把这个问题分解为子问题所需的工作总量来确定的。一般来说,二分法(即把任意大小的问题尽可能的等分为两个子问题)较为有效。
分治法在每一层递归上都有三个步骤:
分解:将原问题分解成一系列子问题;
解决:递归的解各子问题。若子问题足够小,则直接解
合并:将子问题的结果合并成原问题的解;
分治算法实例
快速排序
设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。
一趟快速排序的算法是:
1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;
2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];
3)从j开始向前搜索,即由后开始向前搜索(j–),找到第一个小于key的值A[j],将A[j]和A[i]互换;
4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换;
5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。
合并排序
归并操作的工作原理如下:
第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
第二步:设定两个指针,最初位置分别为两个已经排序序列的起始位置
第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
重复步骤3直到某一指针超出序列尾
将另一序列剩下的所有元素直接复制到合并序列尾
/*
* =====================================================================================
*
* Filename: merge.cc
*
* Description: 合并排序,快速排序
*
* Version: 1.0
* Created: 05/25/2015 08:21:08
* Revision: none
* Compiler: gcc
*
* Author: xiu,
* Organization:
*
* =====================================================================================
*/
#include<iostream>
using namespace std;
#define N 6
//输出测试
void out( int *list )
{
cout << "\n_________________________________\n" << endl;
for ( int i = 0 ; i < N ; i++ )
{
cout << list[i] << "\t" ;
}
cout << "\n_________________________________\n" << endl;
}
//将数组位置为q的元素插入到p位置的元素那
void insert(int *list, int p, int q )
{
int temp = list[q];
for( int i = q ; i >= p; i-- )
{
list[i] = list[ i-1 ];
}
list[p] = temp;
}
//合并函数(将数组中q+1——r的元素插入到 p——q中)
void merge(int *list, int p, int q, int r)
{
int i = p ,j = q + 1 ;
while( j <= r )
{
while( i <= q )
{
if( list[i] >= list[j] )
{
insert( list, i, j );
break;
}
else
{
i++;
}
}
j++;
i = p ;
}
}
//合并排序
//将list里面p 到 r顺序的数组排序
void merge_sort( int *list, int p, int r )
{
if ( (r-p) >= 1 )
{
int q = ( p + r ) / 2 ;
merge_sort( list , p , q ) ;
merge_sort( list , q+1 , r ) ;
merge(list, p, q, r);
out( list );
}
}
//交换p和q位置的列表中的值
void swap( int *list, int p, int q )
{
int temp = list[p];
list[p] = list[q];
list[q] = temp;
}
//快速排序
void quick_sort( int *list, int start,int end )
{
if( start > end )
{
return;
}
int low = start;
int high = end;
int key = list[ low ];
while( low < high )
{
while(low < high && list[high] >= key )
{
high--;
}
list[low] = list[high];
while(low < high && list[low] <= key )
{
low++;
}
list[high] = list[low];
}
list[low] = key;
quick_sort(list, start, low-1 );
quick_sort(list, low+1, end );
}
int main()
{
int list[ N ] = { 5 , 8 , 3 , 4 , 9 , 2 } ;
//merge_sort( list , 0 , N-1 ) ; //合并排序
quick_sort( list , 0, N-1 ); //快速排序
out( list );
return 0;
}