#include <iostream>
int* creatRandNum(const int num, const int left, const int right)
{
// int arr[num] = {0};
int *arr = new int[num];
srand(time(NULL));
for (int i = 0; i < num; ++i) {
arr[i] = rand() % (right - left + 1) + left;
}
return arr;
}
void insertSort(int* arr, const int num)
{
for (int i = 1; i < num; ++i) {
for (int j = i; j > 0 && arr[j] < arr[j-1]; --j) {
std::swap(arr[j], arr[j-1]);
}
}
}
int sumArr(int* arr, int num)
{
if (num == 0)
return 0;
return arr[num-1] + sumArr(arr, num-1);
}
int sumArrAdv(int* arr, int num)
{
return num == 0 ? 0 : arr[num-1] + sumArrAdv(arr, num-1);
}
void printNum(int* arr, const int num)
{
for (int i = 0; i < num; ++i) {
std::cout << arr[i] << " ";
}
}
int main()
{
int left = 0;
int right = 10;
int num = 6;
int* array = creatRandNum(num, left, right);
printNum(array, num);
std::cout << "----------------" << std::endl;
insertSort(array, num);
printNum(array, num);
std::cout << "array sum is " << sumArr(array, num) << std::endl;
std::cout << "array sum is " << sumArrAdv(array, num);
return 0;
}
递归的三大要素
参考:为什么你学不会递归?告别递归,谈谈我的经验
第一要素:明确你这个函数想要干什么
对于递归,我觉得很重要的一个事就是,这个函数的功能是什么,他要完成什么样的一件事,而这个,是完全由你自己来定义的。也就是说,我们先不管函数里面的代码什么,而是要先明白,你这个函数是要用来干什么。
例如,我定义了一个函数
// 算 n 的阶乘(假设n不为0)
int f(int n){
}
这个函数的功能是算 n 的阶乘。好了,我们已经定义了一个函数,并且定义了它的功能是什么,接下来我们看第二要素。
第二要素:寻找递归结束条件
所谓递归,就是会在函数内部代码中,调用这个函数本身,所以,我们必须要找出递归的结束条件,不然的话,会一直调用自己,进入无底洞。也就是说,我们需要找出当参数为啥时,递归结束,之后直接把结果返回,请注意,这个时候我们必须能根据这个参数的值,能够直接知道函数的结果是什么。
例如,上面那个例子,当 n = 1 时,那你应该能够直接知道 f(n) 是啥吧?此时,f(1) = 1。完善我们函数内部的代码,把第二要素加进代码里面,如下
// 算 n 的阶乘(假设n不为0)
// 算 n 的阶乘(假设n不为0)
int f(int n){
if(n == 1){
return 1;
}
}
有人可能会说,当 n = 2 时,那我们可以直接知道 f(n) 等于多少啊,那我可以把 n = 2 作为递归的结束条件吗?
当然可以,只要你觉得参数是什么时,你能够直接知道函数的结果,那么你就可以把这个参数作为结束的条件,所以下面这段代码也是可以的。
// 算 n 的阶乘(假设n>=2)
int f(int n){
if(n == 2){
return 2;
}
}
注意我代码里面写的注释,假设 n >= 2,因为如果 n = 1时,会被漏掉,当 n <= 2时,f(n) = n,所以为了更加严谨,我们可以写成这样:
// 算 n 的阶乘(假设n不为0)
int f(int n){
if(n <= 2){
return n;
}
}
第三要素:找出函数的等价关系式
第三要素就是,我们要不断缩小参数的范围,缩小之后,我们可以通过一些辅助的变量或者操作,使原函数的结果不变。
例如,f(n) 这个范围比较大,我们可以让 f(n) = n * f(n-1)。这样,范围就由 n 变成了 n-1 了,范围变小了,并且为了原函数f(n) 不变,我们需要让 f(n-1) 乘以 n。
说白了,就是要找到原函数的一个等价关系式,f(n) 的等价关系式为 n * f(n-1),即
f(n) = n * f(n-1)。
这个等价关系式的寻找,可以说是最难的一步了,如果你不大懂也没关系,因为你不是天才,你还需要多接触几道题。
找出了这个等价,继续完善我们的代码,我们把这个等价式写进函数里。如下:
// 算 n 的阶乘(假设n不为0)
int f(int n){
if(n <= 2){
return n;
}
// 把 f(n) 的等价操作写进去
return f(n-1) * n;
}
至此,递归三要素已经都写进代码里了,所以这个 f(n) 功能的内部代码我们已经写好了。
这就是递归最重要的三要素,每次做递归的时候,你就强迫自己试着去寻找这三个要素。
#include <iostream>
int sumArr(int num)
{
if(num == 1)
{
return 1;
}
return num + sumArr(num-1);
}
int sumFar(int num)
{
if(num == 1)
{
return 1;
}
printf("%d\t", num);
return num*sumFar(num-1);
}
int main() {
std::cout << sumArr(100) << std::endl;
std::cout << sumFar(5) << std::endl;
return 0;
}