(九十八)递归(函数与函数自己)

递归的实质,函数自己调用自己。——但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=1a++a=22<10,于是执行m函数(第三层m函数),参数是a=2

依次类推……

 

第九层m函数,参数是a=9a++a=10if判断语句不通过,于是执行下一行代码,打印a=10;然后第九层函数执行完,跳回第八层函数,返回值是10(但第八层函数并没有接收这个返回值);

第八层函数的if语句执行结束(已经调用完第九层函数),此时a=9,打印a=9,跳回第七层函数;

依次类推……

 

第一层(最外层)m函数,此时a=1,返回值是a1),于是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时,函数直接返回(即这次调用结束);

 

②初始levelfor循环中的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个,还分别在116163232484864中间有字符;(调用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坐标+1y+1y-1位置上的点赋值“*”。并以此类推。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值