分治与递归

  1. Fibonacci数列
    无穷数列1,1,2,3,5,8,13,21,34,55,……,称为Fibonacci数列。它可以递归地定义为:
    F(n)={■(1@1@F(n-1)+F(n-2))┤ ■(n=0@n=1@n>1)
    第n个Fibonacci数可递归地计算如下:
    int fibonacci(int n)
    {
    if (n <= 1) return 1;
    return fibonacci(n-1)+fibonacci(n-2);
    }
    编写完整的主函数,分别记录利用上述递归函数求第47, 48, 49, 50, 51, 52个Fibonacci数所花费的时间。
    #include
    #include
    using namespace std;
    int f(int n){
    if(n<=1){
    return 1;
    }
    else{
    return f(n-1)+f(n-2);
    }
    }
    int main(){
    cout< return 0;
    }
    #include
    #include
    using namespace std;
    int f(int n){
    if(n<=1){
    return 1;
    }
    else{
    return f(n-1)+f(n-2);
    }
    }
    int main(){
    cout< return 0;
    }

N=47 time=19.22s
N=48 time=31.06s
N=49 time=50.07s
N=50 time=80.87
N=51 time=130.7s
N=52 time=211s

将递归函数改为尾递归,或者是递推函数,求第47, 48, 49, 50, 51,52个Fibonacci数所花费的时间,观察效率是否得到提高。

#include
#include
#include    //引入头文件
using namespace std;
int f(int n, int ret1, int ret2)
{
if (n == 0)
return ret1;
return f(n - 1, ret2, ret1 + ret2);
}
int main() {
DWORD t1,t2;
t1 = GetTickCount();
f(52, 0, 1);
t2 = GetTickCount();
cout<<"time = "<<((t2-t1)*1.0/1000)< //输出时间(单位:s)
cout<< f(52, 0, 1);
system(“pause”);
return 0;
}

N=47 time=0.25s
N=48 time=0.26s
N=49 time=0.26s
N=50 time=0.27s
N=51 time=0.28s
N=52 time=0.5s

  1. 教材42页算法实现题2-4:半数单集问题。
    #include
    #include
    using namespace std;
    int count(int x)
    {
    int s=0;
    if(!x)
    return 1;
    else
    for(int i=0;i<=x/2;i++)
    {
    s+=count(i);//递归调用count函数
    if(i>10&&(2*(i/10))<=i%10)//剔除重复元素
    s-=count(i/10);
    }
    return s;
    }
    int main()
    {
    int n;
    cin>>n;
    cout< return 0;
    }

  2. 教材45页算法实现题2-11:整数因子分解问题。
    #include
    #include
    using namespace std;
    int s (int n) {
    int count=0;
    for (int i = 2; i < n; i++) {
    if (n%i == 0) {
    count++;
    count=count+s(n / i);//分解
    }
    }
    return count;
    }
    int main() {
    int n;
    cin >> n;
    cout< system(“pause”);
    return 0;
    }

以下两题选做一题:
4. 教材2.10节中最近对问题(二维平面上的点),编程实现用分治法求解。
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
struct Point
{
int x;
int y;
Point() {}
Point(int m_x, int m_y)
:x(m_x), y(m_y) {}
};
/***********************************************************************/
/
函数功能:按点的X坐标排序 /
/
***********************************************************************/
struct CmpX : public binary_function
{
bool operator() (const Point& lhs, const Point& rhs)
{
return (lhs.x < rhs.x);
}
};
/***********************************************************************/
/
函数功能:按点的Y坐标排序 /
/
***********************************************************************/
struct CmpY : public binary_function
{
bool operator() (const Point& lhs, const Point& rhs)
{
return (lhs.y < rhs.y);
}
};
/***********************************************************************/
/
类功能:产生无重复的随机数
类成员:num 表示要产生的随机数的个数
bound 表示每个随机数的范围[0, bound-1). /
/
**********************************************************************/
class Random
{
public:
explicit Random(int m_num, int m_bound)
:num(m_num), bound(m_bound)
{
arr = new int[m_bound];
for (int i = 0; i < bound; i++)
arr[i] = i;
}
int
GetResult()
{
int temp = 0;
srand((unsigned)time(0));
for (int i = 0; i < num; i++)
{
temp = rand() % (bound - i - 1) + i;
swap(arr[i], arr[temp]);
}
return arr;
}
~Random()
{
delete[]arr;
}
private:
int arr;
int num; //随机数的个数
int bound; //随机数的范围
};
/
**********************************************************************/
/
函数功能:求两点间的距离 /
/
***********************************************************************/
inline double Distance(const Point& lhs, const Point& rhs)
{
int x_diff = lhs.x - rhs.x;
int y_diff = lhs.y - rhs.y;
double res = x_diff * x_diff + y_diff * y_diff;
return sqrt(res);
}
/***********************************************************************/
/
函数功能:求数组中两点间的最短距离 /
/
***********************************************************************/
double GetShortestDistace(Point arr[], int low, int high)
{
double result = 0.;

if (high - low < 3) //小于等于3个点时
{
	if (high - low == 1) //2个点时
	{
		double distance = Distance(arr[low], arr[high]);
		return distance;
	}
	else //3个点
	{
		double distance1 = Distance(arr[low], arr[low + 1]);
		double distance2 = Distance(arr[low], arr[low + 2]);
		double distance3 = Distance(arr[low + 1], arr[low + 2]);
		return min(min(distance1, distance2), distance3);
	}
}
int middle = (low + high) / 2;
double left_distance = GetShortestDistace(arr, low, middle);        //求middle左边的最短距离
double right_distance = GetShortestDistace(arr, middle + 1, high);    //求middle右边的最短距离

double delta = min(left_distance, right_distance); //中间区域的界限
result = delta;
vector midArea;    //存放中间条带区域的点
for (int k = low; k < high; k++)
{
	if (arr[k].x > arr[middle].x - delta && arr[k].x < arr[middle].x + delta)
		midArea.push_back(arr[k]);
}
sort(midArea.begin(), midArea.end(), CmpY()); //按Y坐标排序
int size = midArea.size();
for (int i = 0; i < size; i++)
{
	int k = (i + 7) > size ? size : (i + 7);    //只有选取出7个点(证明过程没看懂)
	for (int j = i + 1; j < k; j++)
	{
		if (Distance(midArea.at(i), midArea.at(j)) < result)
			result = Distance(midArea.at(i), midArea.at(j));
	}
}
return result;

}
#define N 100 //点的个数
int main()
{
Point arr[N];
Random random(2 * N, 1000);
int *result = random.GetResult();
for (int i = 0; i < N; i++)
arr[i] = Point(result[i], result[i + N]);
sort(arr, arr + N, CmpX());
double res = GetShortestDistace(arr, 0, N);
cout << “The shortest distance is:” << res << endl;
system(“pause”);
return 0;
}

你可能感兴趣的:(算法与分析设计,分治与递归)