递归的实质,函数自己调用自己。——但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位置上的点赋值“*”。并以此类推。