0
点赞
收藏
分享

微信扫一扫

《算法设计与分析》第二章 递归与分治策略

萧让听雪 2022-01-20 阅读 35

第二章 递归与分治策略

1. 递归

阶乘函数(O(n))

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

Fibonacci数列(O(2^n))

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

排列问题

  1. 问题描述:对n个元素进行全排列,列出所有情况,例如1,2,3三个数字会得到1 2 3,1 3 2,2 1 3,2 3 1,3 1 2,3 2 1这6中情况

  2. 思路:设n为元素个数,元素集合为R(r1,r2,r3…rn),计算方法为Perm(n)
    当n = 1时,则只有一种情况 r;
    当n > 1时,则有perm(R)由(r1)Perm(R1),(r2)Perm(R2),(r3)Perm(R3) … … (rn)Perm(Rn)
    在这里插入图片描述

  3. 算法思想:在一般情况下,k<m。算法将list[k:m]中的每个元素分别与list[k]中的元素交换,然后递归地计算list[k+1:m]的全排列,并将计算结果作为list[0:k]的后缀。

  4. 代码


#include<iostream>
using namespace std;
void perm(int list[], int k, int m)
 {
	if(k == m)
  {
  for(int i = 0; i <= m; i++) cout << list[i];		
	cout << endl;
  } 
else 
{
	for(int i = k; i <= m; i++)
  {
	   swap(list[k], list[i]);
	   perm(list, k + 1, m);
	   swap(list[k], list[i]); //还原
	 }
 }
}
void swap(int &a, int &b)
{
	int temp = a;
	a = b;
	b = temp;
}

int main()
{
	int a[3] = {1, 2, 3};
	perm(a, 0, 2);
	return 0;
}

Hanoi塔问题

  1. 问题描述
    在这里插入图片描述
  2. 算法思想(递归)
    (1)当n=1时,问题比较简单。此时,只要将编号为1的圆盘从塔座a直接移至塔座b上即可。
    (2)当n>1时,需要利用塔座c作为辅助塔座。此时要设法将n-1个较小的圆盘依照移动规则从塔座a移至塔座c上,然后将剩下的最大圆盘从塔座a移至塔座b上,最后设法将n-1个较小的圆盘依照移动规则从塔座c移至塔座b上。
    (3)由此可见,n个圆盘的移动问题就可分解为两次n-1个圆盘的移动问题,这又可以递归地用上述方法来做。
  3. 代码
void hanoi( int n,int a,int b,int c)
//hanoi(n, a,b, c)表示将塔座a上自下而上,由大到小叠放在一起的n个圆盘依移动规则移至塔座b上并仍按同样顺序叠放。
//在移动过程中,以塔座c作为辅助塔座。
{
    if(n>0)
    {
        hanoi(n-1,a,c,b);  //以b为辅助,把a移到c
        move(a,b);         //move(a, b)表示将塔座a上编号为n的圆盘移至塔座b上
        hanoi(n-1,c,b,a)    //以a为辅助,把c移到b
    }
 }
  1. 时间复杂度分析:求解如下递归关系得O(2^n)
    在这里插入图片描述

2.分治法

  1. 基本思想
    将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同。递归地解这些子问题,然后将各子问题地解合并得到原问题的解。
  2. 分治法复杂性分析
    (1)递归树法
    在这里插入图片描述
    在这里插入图片描述
    (2)主定理法
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

二分搜索技术(O(logn))

  1. 基本思想
    将n个元素分成个数大致相同的两半,取a[n/2]与x作比较。
    如果x=a[n/2],则找到x,算法终止;
    如果x<a[n/2],则只在数组a的左半部分继续搜索x;
    如果x>a[n/2],则只在数组a的右半部分继续搜索x;
  2. 算法描述
template <class Type>
int BinarySearch(Type a[],const Type& x,int n)
{  
    int right=n-1;
    int left=0;
    while(left<=right)
    {
         int middle=(left+right)/2;
         if(x==a[middle])  return middle;
         else if(x>a[middle])  left=middle+1;
 	      else right=middle-1;
    }
    return -1;  //没有找到x
}
举报

相关推荐

0 条评论