递归的实质,函数自己调用自己。——但C++语言不允许main函数调用自己
包含一个递归调用的递归:
例如代码:
#include<iostream>
using namespace std;
int m(int); //m函数
int main()
{
int a = 0;
a = m(a); //函数参数为a,并将返回值赋值给a
cout << a << endl;
system("pause");
return 0;
}
int m(int a)
{
a++; //a+1
if (a < 10) m(a); //当a<10的时候,调用函数m,参数为a,注意,ma的返回值不影响if判断语句中的a<10。
cout << "a = " << a << endl; //输出本函数的值
return a;
}
输出:
a = 10
a = 9
a = 8
a = 7
a = 6
a = 5
a = 4
a = 3
a = 2
a = 1
1
请按任意键继续. . .
解释:
①在m函数中(这时候是最外层的m),a++后,a=1;又因为1<10,于是执行m函数(第二层m函数),参数是a=1;
第二层m函数,参数是a=1,a++后a=2,2<10,于是执行m函数(第三层m函数),参数是a=2;
依次类推……
第九层m函数,参数是a=9,a++后a=10,if判断语句不通过,于是执行下一行代码,打印a=10;然后第九层函数执行完,跳回第八层函数,返回值是10(但第八层函数并没有接收这个返回值);
第八层函数的if语句执行结束(已经调用完第九层函数),此时a=9,打印a=9,跳回第七层函数;
依次类推……
第一层(最外层)m函数,此时a=1,返回值是a(1),于是main函数中a=1;
②假如没有a++这行代码,函数就会陷入无限循环之中。
另一代码:打印缩进图形的星:
//打印从两边缩进的星
#include<iostream>
using namespace std;
const int kuan = 20;
char zifu[kuan];
void ab(char,int); //无返回值函数,参数为char
int main()
{
char x = '*';
for (int i = 0;i < kuan;i++)
zifu[i] = ' ';
ab(x, 20);
system("pause");
return 0;
}
void ab(char m,int n)
{
zifu[kuan - n] = m;
zifu[n - 1] = m;
for (int i = 0;i < kuan;i++)
cout << zifu[i];
cout << endl;
n--;
if (n > kuan / 2)ab(m, n);
}
输出:
* *
** **
*** ***
**** ****
***** *****
****** ******
******* *******
******** ********
********* *********
********************
请按任意键继续. . .
包含多个递归调用的递归:
因为多个递归可以多次调用自己,因此需要一个变量可以控制调用的次数,并且这个变量在每次调用的时候,可以增加或者减少,以满足停止调用的条件。
如代码:
#include<iostream>
const int kuan = 66;
const int dives = 5;
void shu(char ar[], int low, int high, int level);
int main()
{
char ruler[kuan]; //字符串宽
int i; //初始化i,因为在其他地方也要用i,所以在for外面初始化
for (i = 1;i < kuan - 2;i++)
ruler[i] = ' '; //从第2个字符到倒数第二个字符,都是空格
ruler[kuan - 1] = '\0'; //最后一个字符为空字符(因为是字符串)
int max = kuan - 2; //max是字符宽度-2(这样将指示倒数第二个字符)
int min = 0; //min是0,
ruler[min] = ruler[max] = '|'; //第一个和倒数第二个字符是|,注意,最后一个是空字符
std::cout << ruler << std::endl; //输出字符串,这个时候第一个和倒数第二个是|,其他是空格
for (i = 1;i <= dives;i++)
{
shu(ruler, min, max, i); //调用函数,参数是字符串,min,max,
std::cout << ruler << std::endl; //输出字符串
for (int j = 1;j < kuan - 2;j++) //重置字符串为空字符,注意,没清楚字符串第一个字符和倒数第二个字符
ruler[j] = ' ';
}
system("Pause");
return 0;
}
void shu(char ar[], int low, int high, int level)
{
if (level == 0) //当level为0时,结束函数,level初始为for循环中的i
return;
int mid = (high + low) / 2; //min是high和low的平均数,即为中间
ar[mid] = '|'; //中间为|,
shu(ar, low, mid, level - 1); //执行函数,level-1,mid替代high为参数,即层次每高1级,即可在low和mid中间的位置插入一个字符|
shu(ar, mid, high, level - 1); //在mid和high中间插入一个字符。
}
输出:
| |
| | |
| | | | |
| | | | | | | | |
| | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
请按任意键继续. . .
解释:
①控制函数层级的是level,每次函数自己调用自己的时候,level将-1,当level=0时,函数直接返回(即这次调用结束);
②初始level为for循环中的i,第一次是i=0,因此函数直接返回;
当for循环进入i=1时,函数执行第一次,并且在函数自己调用自己的时候,level-1的值为0,调用后,函数直接返回;
当for循环进入i=2时,函数执行第一次,然后函数在自己调用自己的时候,level-1的值为1,因此函数执行第一次的时候,可以调用自己两次,加上函数第一次,共执行三次(即多出三个“|”);
当for循环进入i=3时,同i=2,但此时是三层函数,执行1+2+4=7次,即多出7个“|”。
依次类推。
③函数的特点是,定出左边的字符和最右边字符的位置,然后给中间字符赋值字符“|”。
并且以中间位置,为下一次调用函数时的最左边或者最右边位置。
即第一轮是1#(ar[0])和64#(ar[63])位置有字符;(调用0次函数)
第二轮时1#,64#以及他们中间的位置32#(ar[31])位置有字符;(调用1次函数)
第三轮,除了第二轮的三个,还在1#和32#、32#和64#中间有字符,即16#和48#;(调用1+2次函数)
第四轮,除了第三轮的5个,还分别在1和16,16和32,32和48,48和64中间有字符;(调用1+2+4次函数)
即每次都在上一次有字符的位置中间,有字符。
而level是用来控制轮数的。
方向向右的树形图,多重递归的代码:
//思路:
//创建二维字符串,即string[y][x],描述坐标上的点,然后给坐标上的点赋值(“—”或者空字符)
//用多重递归,使得图形为向右的树形图;
//赋值完毕后,打印二维字符串
#include<iostream>
#include<string>
using namespace std;
void shuxingtu(string a[][32], int x, int y);
int main()
{
//首先是给树形图赋值,预计树形图为
string a[32][32];
int x ,y;
x = y = 0;
for (int i = 0;i < 32;i++) //使得32x32的坐标都是空字符
for (int j = 0;j < 32;j++)
a[i][j] = ' ';
y = 16;
a[y][x] = "*";
x = 1;
shuxingtu(a, x, y); //给二维string字符串赋值
//打印字符串
for (int i = 0;i < 32;i++) //使得32x32的坐标都是空字符
{
for (int j = 0;j < 32;j++)
cout << a[i][j];
cout << endl;
}
system("pause");
return 0;
}
void shuxingtu(string a[][32], int x, int y) //导入二维string字符串数组,导入x,y坐标
{
if (x == 16)return; //当层级为0时,结束循环
//注意,导入坐标的点,不赋值——即保持为空字符,导入坐标上下方的点赋值*
a[y + 1][x] = "*"; //上一个y更高一个位置
a[y - 1][x] = "*"; //上一个y更低一个位置
shuxingtu(a, x + 1, y + 1); //再次调用的时候,x坐标+1,y坐标+1(即是调用本函数赋值的两个点往右边一位)
shuxingtu(a, x + 1, y - 1); //再次调用的时候,x坐标+1,y坐标-1(注意,当前函数所赋值*的点为x,y-1与x,y+1
}
输出:
*
*
* *
* *
* * *
* * *
* * * *
* * * *
* * * * *
* * * * *
* * * * * *
* * * * * *
* * * * * * *
* * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * *
* * * * * * *
* * * * * *
* * * * * *
* * * * *
* * * * *
* * * *
* * * *
* * *
* * *
* *
* *
*
*
请按任意键继续. . .
解释:
①如果看以上图标排列不整齐,可能是因为字体问题。
②从左边中间开始,赋值“*”,然后x坐标+1,y+1和y-1位置上的点赋值“*”。并以此类推。