提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。
提示:以下是本篇文章正文内容,下面案例可供参考
一、递归算法总结
1.什么是递归?
简单的说就是函数自己掉自己的过程。
递归可以看成是一种比较特殊的循环。
递归算法需要注意的地方(可以对应于循环执行的三个条件,初值,循环体,结束条件):
(1)每一个递归函数都必须非递归函数定义的初始值,作为递归函数的出口,或者说递归结束的标志。如果递归函数中没有初始值递归函数将无法计算出具体的值,而且递归调用不会结束。
(2)在设计递归函数的时候需要有重复调用的自身的特性,(类似于函数的循环体)。
2.递归算法的实际应用:
对于解决一些比较复杂的问题可以采用递归,比较容易实现,但是算法的执行效率比较慢,(对栈空间的资源消耗比较大,因为在不断的调用自己开辟空间),时间和空间复杂度比较高,对于一些时间和空间复杂度要求比较高的程序不适合采用递归算法来实现。
所以递归算法往往跟分治算法进行组合使用,分治算法是将原问题变成更小规模的问题,但是原问题和子问题的类型是一致的,这就有了递归性,所以就可以用原问题的方法去解决子问题。
二、算法举例
1.求一个整数的组成
题目:算例;将一个正整数N表示成一系列之的正整数之和
n = n1+n2+n3+…+nk(n1>=n2>=n3>=1,k>=1)
输入一个正整数n,求n的划分数
例如:正整数6的组成有
6 = 6
6 = 5+1
6 = 4+2 6 = 4+1+1
6 = 3+3 6 = 3+2+1 6 = 3+1+1+1
6 = 2+2+2 6 = 2+2+1+1 6 = 2+1+1+1+1
6 = 1+1+1+1+1+1
定义一个表达式:p(n,m)表示正整数n的划分中,加数不大于m的数的组成有哪些。
p(6,2) = 4
解析为:
(1) n < m ---------->p(n,m) = p(n,n)
这是因为任何正整数n的划分中,只存在一种划分即n=n,其最大加数等于n。不存在最大加数大于n的情况(根据划分的定义,任何加数必须大于1)。
(2) n = m ---------->p(n,n) = p(n,n-1)+1
因为最大加数为n的划分只有1种,即n=n。因此最大加数不大于n的划分数就是P(n,n-1)+1
(3) n >m>1 --------->p(n,m) = p(n,m-1)+p(n-m,m)
“正整数n的最大加数不大于m的划分数(n>m>1)”等于“n的最大加数不大于m-1的划分数P(n,m-1)”与“n的最大加数为m的划分数”之和。
(4)n=m=1 ---------->p(n,m)=1;
代码如下(示例):
#include <stdio.h>
int make_num(int n,int m)
{
if(n==1||m==1)
{
return 1;
}
else if(n<m)
{
return make_num(n,n);
}
else if(n == m)
{
return make_num(n,n-1)+1;
}
else
{
return make_num(n,m-1)+make_num(n-m,m);
}
}
int main(int argc, const char *argv[])
{
printf("please input a num\n");
unsigned int n = 0;
scanf("%d",&n);
int ret = make_num(n,n);
printf("ret = %d\n",ret);
return 0;
}
2.一个数的n的阶乘
题目分析:
递归函数的出口为n =1 返回1
递归调用的过程是n >1 n = n*(n-1)
代码展示:
#include <stdio.h>
int factorial_num(int n)
{
if(1 == n)
{
return 1;
}
else
{
return n*factorial_num(n-1);
}
}
int main(int argc, const char *argv[])
{
printf("please input a num\n");
int num = 0;
scanf("%d",&num);
int ret = factorial_num(num);
printf("ret%d\n",ret);
return 0;
}
3.二分查找(递归版)
思想:
#include <stdio.h>
//递归版
int binary_research(int *a, int begin,int end, int num)
{
int mid = 0;
if(begin > end)
{
return -1;
}
else
{
mid = (begin+end)/2;
if(a[mid] == num)
{
return mid;
}
if( a[mid] > num)
{
return binary_research(a, begin, mid-1, num);
}
else
{
return binary_research(a, mid+1, end, num);
}
}
}
//循环版
int bi_serach(int *a,int len, int num )
{
int begin = 0;
int end = len-1;
int mid = 0;
while(begin <= end)
{
mid = (begin + end);
if(a[mid] > num)
{
end = mid -1;
}
else if(a[mid] < num)
{
begin = mid + 1;
}
else
{
break;
}
}
if(begin <= end)
{
return mid;
}
else
{
return -1;
}
}
void show(int *a, int len)
{
int i =0;
for(i=0;i<len;++i)
{
printf("%d ",a[i]);
}
printf("\n");
}
int main(int argc, const char *argv[])
{
int a[10]={1,3,5,7,9,11,13,14,15,19};
show(a,10);
printf("please input find num\n");
int num = 0;
scanf("%d",&num);
//int ret = binary_research(a, 0, 9, num);
int ret = bi_serach(a, 9, num);
if(ret != -1)
{
printf("ret=%d\n",ret);
}
else
{
printf("input error\n");
}
return 0;
}
4.快速排序
思想:确定一个基准值,这个基准值右面都是比它大的值,基准值左面都是比它小的值,定义两个数组下标 i, j进行操作,j先开始走找到一个比基准值小的值放到i下标上,(j不动)i后走找到一个比基准值小的指放在j上,一直走直到当i>j时将基准值放到i或者j的位置(此时i=j),然后继续调用自身就可以,调用函数为左边到i-1,右边到i+1.递归结束的条件是当数组传进来的begin>end时。
#include <stdio.h>
void Qsort(int *a,int begin,int end)
{
if(begin > end)
{
return ;
}
int i = begin;
int j = end;
int key = a[i];
while( i < j)
{
while(i < j && key <= a[j])
{
j--;
}
a[i] = a[j];
while(i < j && key >= a[i])
{
i++;
}
a[j] = a[i];
}
a[i] = key;
Qsort(a,begin,i-1);
Qsort(a,i+1,end);
}
void show(int*a,int len)
{
int i=0;
for(i =0;i<len;++i)
{
printf("%d ",a[i]);
}
printf("\n");
}
int main(int argc, const char *argv[])
{
int a[10] = {6,9,3,4,11,35,67,7,8,2};
show(a,10);
Qsort(a,0,9);
show(a,10);
return 0;
}