算法分析-----递归与分治策略

1、递归的概念

        直接或间接的调用自身的算法成为递归算法。用函数自身给出定义的函数称为递归函数。

       例1:阶乘函数

        

int factorial(int n)
{
    if(n==0) return 0;
    return n*factorial(n-1);
}

    例2:Fibonacci数列

    

int Fibonacci(int n)
{
    if(n<1) return 1;
    return Fibonacci(n-1)+Fibonacci(n-2);
}

    例3 全排列问题 

//全排列问题
/*设 R={r1,r2,…,rn} 是要进行排列的 n 个元素,Ri=R-{ri}。
集合 X 中元素的全排列记为 perm(X)。
(ri)perm(X) 表示在全排列 perm(X) 的每一个排列前加上前缀得到的排列。
R 的全排列可归纳定义如下: 
当 n=1 时,perm(R)=(r),其中 r 是集合 R 中唯一的元素;
当 n>1 时,perm(R)由 (r1)perm(R1),(r2)perm(R2),…,(rn)perm(Rn) 构成。
实现思想:将整组数中的所有的数分别与第一个数交换,这样就总是在处理后 n-1 个数的全排列。

【示例】

当 n=3,并且 E={a,b,c},则:
perm(E)=a.perm({b,c}) + b.perm({a,c}) + c.perm({a,b})
perm({b,c})=b.perm(c) + c.perm(b)
a.perm({b,c})=ab.perm(c) + ac.perm(b)
=ab.c + ac.b=(abc, acb)*/
#include 
#include 

using namespace std;

template
void Perm(Type list[],  int k, int m )
{ //产生[list[k:m]的所有排列
    if(k==m)
     {  //只剩下一个元素
         for (int i=0;i<=m;i++) 
     cout<

2、分治法的基本思想

    分治法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题。这些子问题相互独立且与原问题相同,递归的解决这些子问题,然后将各子问题的解合并并得到原问题的解。从分治法的一般设计模式可以看出,用它设计的程序一般时递归算法。

    例1 二分搜索

    

template
int BinarySearch(Type a[],Type &x,int n)
{
    int left,right=n-1;
    while(left<=right)
        {
            int middle=(left+right)/2;
            if(x==a[middle]) return middle;
            if(x>a[middle]) left=middle+1;
            else 
               right=middle-1;
            
        }
    return -1;//未找到
}

    例2 归并排序

  

/*归并排序是利用归并的思想,采用分治策略,将问题分为一些小问题然后递归求解。在治阶段将分阶段得到****的各答案合在一起。比如一个{8,4,5,7,1,3,6,2}的数列分成{8,4,5,7}和{1,3,6,2}之后
****再分成{8,4},{5,7},{1,3},{6,2}再分成{8}{4}{5}{7}{1}{3}{6}{2},然后开始比较先比较8,4
****小的放前面之后合并,{4,8},以此类推合并{5,7},{1,3},{2,6}再比较合并{4,5,7,8},{1,****2,3,6},再比较合并{1,2,3,4,5,6,7,8}.
****归并是稳定排序,时间复杂度nlogn。
*/
#include 
#include
//using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
//template
//合并
void Merge(int A[], int TmpAry[], int Lpos, int Rpos, int RightEnd)
{
	int i, LeftEnd, NumTypes, TmpPos; 
	LeftEnd = Rpos - 1;
	TmpPos = Lpos;     //临时数组指针
	NumTypes = RightEnd - Lpos + 1;
	while (Lpos <= LeftEnd&&Rpos <= RightEnd)
	{
		if (A[Lpos] <= A[Rpos])
		{
			TmpAry[TmpPos++] = A[Lpos++];
		
		}
			
		else
		{
			TmpAry[TmpPos++] = A[Rpos++];
			
		}
			

	}
	
	while (Lpos <= LeftEnd)
	{
		TmpAry[TmpPos++] = A[Lpos++];
		
	}
		
	while (Rpos <= RightEnd)
	{
		TmpAry[TmpPos++] = A[Rpos++];
		
	}
		
	//复制
	for (i = 0; i

     例3 快速排序

  

/****
****采用三数中值法选区枢纽元
****在数据小于一定值时采用插入排序可以实现更高效率的排序
****
****
****
****
****/
#include 
#define cutoff 3
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
template 
void swap(Type &a, Type &b)
{
	Type temp;
	temp = a;
	a = b;
	b = temp;
}
template
void InsertSort(Type A[], int N)
{
	int i, j;
	Type temp;
	for (i = 1; i= 0 && A[j - 1]>temp; j--)
			A[j] = A[j - 1];
		A[j] = temp;
	}
}

//以三数中值作为基准值 
template 
Type Median3(Type A[], int left, int right)
{
	int center = (left + right) / 2;
	if (A[left]>A[center])
		swap(A[left], A[center]);
	if (A[left]>A[right])
		swap(A[left], A[right]);
	if (A[center]>A[right])
		swap(A[center], A[right]);
	//以上得到A[left]<=A[center]<=A[right]
	swap(A[center], A[right - 1]);//隐藏枢纽元
	return A[right - 1];	       //返回枢纽元 
}
template 
void QSort(Type A[], int left, int right)
{
	int i, j;
	Type Pivot;
	Pivot = Median3(A, left, right);
	i = left; j = right - 1;
	if (left + cutoff <= right)
	{
		for (;;)
		{
			while (A[++i]Pivot){}
			if (i

 

你可能感兴趣的:(【数据结构与算法】)