c语言循环,迭代与递归背后的思维

本文探讨了循环、迭代和递归在编程中的应用,包括有限长度循环的实例、未知长度循环的处理、递归的数学归纳法原理如阶乘、汉诺塔和斐波那契数列,以及尾递归优化。作者强调了递归和迭代的关系,并承诺后续会继续深入探讨这些主题。

目录

写在前面

关键词

一.循环

解释

循环的类型

1.已知循环长度的有限循环

简单但不好想的猜凶手 

2.未知长度有限循环

3.未知长度的无限循环

二.递归——数学归纳法

1.阶乘

尾递归优化

2.汉诺塔问题

3.斐波那契数列

尾递归优化

三.迭代与递归的关系


写在前面

原来想做一个能系统且全面回答:循环的应用场景?迭代能解决的问题,递归一定能解决嘛?递归能解决的问题,迭代一定能解决吗?能,具体代码如何由此及彼,不能,具体限制的原因是什么?但笔者查阅资料后,发现问题比较复杂,就先分享出初阶的结论,并且本文会不定期更新。

关键词

循环是程序设计语言中一种用于反复执行某些代码的处理过程

迭代是指重复反馈过程的活动,每一次迭代的结果会作为下一次迭代的初始值

递归是一种编程技巧,它允许函数调用自身来解决问题

一.循环

解释

我们要循环是因为接下来我们要做的事是同构的,即有相似或相同之处。在循环控制中,最重要的就是循环条件。如果处理不好,就有可能陷入死循环,造成内存溢出,main函数最终不返回0

循环的类型

1.已知循环长度的有限循环

for(int i = 0;i <= 10;i++)
//
while(i)
{
//省略的代码
i--
}

这种代码较好理解,就不过多赘述了。在这里要补充的是一个不容易想到的关于初始化是字符的:

简单但不好想的猜凶手 

日本某地发生了一件谋杀案,警察通过排查确定杀人凶手必为4个嫌疑犯的一个。

以下为4个嫌疑犯的供词:

A说:不是我。

B说:是C。

C说:是D。

D说:C在胡说

已知3个人说了真话,1个人说的是假话。

现在请根据这些信息,写一个程序来确定到底谁是凶手。

#include<stdio.h>
int main()
{
   int killer = 0;
   //分别假设凶手是a,b,c,d,看谁是凶手时满足3个人说了真话,一个人说了假话
   for (killer = 'a'; killer <= 'd'; killer++)
   {
    if ((killer != 'a') + (killer == 'c') + (killer == 'd') + (killer != 'd') == 3)
     printf("凶手是:%c", killer);
   }
   return 0;
}

 本题有两个简单难想的点,1是初始化的不是整型而是字符,2是三真一假的表示。

2.未知长度有限循环

未知长度在于,每一次循环的长度都有可能不一样,有限循环在于他一定有尽头,循环条件的真假一般与我们的输入密切相关。

	int arr[1000] = { 0 };
	int count = 0;
	do
	{
		scanf("%d", &arr[count]);
		count++;
	} while (getchar() != '\n');

比如上一期博客未定长度的整型数组的输入,数组的长度是由我们控制的,循环次数当然也是由我们控制的。再比如有些游戏用input的输入来控制循环的发生:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

void menu()
{
	printf("*********************\n");
	printf("********1.开始********\n");
	printf("********0.结束********\n");
	printf("*********************\n");
}

void game()
{
	srand((unsigned int)time(NULL));
	int goal = rand() % 100;
    int k = NULL;
	while (goal != k)
	{
		printf("请输入数字:>>");
		scanf("%d", &k);
		if (goal > k)
		{
			printf("猜小了\n");
		}
		else if (goal < k)
		{
			printf("猜大了\n");
		}
	}
	if (goal == k)
	{
		printf("恭喜你,猜对了\n");
	}
}

int main()
{
	int input = 0;
	do
	{
		menu();
		printf("请输入数字:>>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出\n");
			break;
		default:
			printf("请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}

 这种类型的循环主要是刚开始的意识问题,不知道可以这么玩。

3.未知长度的无限循环

这种循环是没有意义的,没有尽头,有也只是内存泄漏——迭代只是时间问题,递归更不用说——本质都是没有“终止条件”。

二.递归——数学归纳法

迭代与普通的循环无异,主要是递归。当一个函数调用自己时,一般要用到if,else语句,用来表明循环结束的条件。写一个递归函数,要在写完基本情况的情况下,明确递归函数能干什么,想象它已经写完了。然后再调用。注意最后一定会收敛于基本情况。

1.阶乘

#include<stdio.h>
int fun(int n)
{
  if(n==1||n==0) return 1;//如果参数是0或者1返回1
  return n*fun(n-1);//否则返回n和下次递归的积
}
 
int main()
{
  int n;
  scanf("%d",&n);
  printf("%d\n",fun(n));
  return 0;
}

基本情况是0和1,确定好返回值后,对于一般情况,假设已经写完后,调用自身,最终收敛于基本情况,就一定能递归出来。

尾递归优化

#include<stdio.h>

int jiecheng(int n,int m)
{
	if (n == 0 || n == 1)
	{
		return m;
	}
	else
	{
		return  jiecheng(n - 1,m*n);
	}
}

int main()
{
	int n = 8;
	while (1)
	{
		scanf("%d", &n);
		int ret = jiecheng(n, 1);
		printf("%d\n", ret);
	}
	return 0;
}

2.汉诺塔问题

#include<stdio.h>
int count = 0;
 hanoi(int n, char A, char B, char C)
{
	if (n == 0)
		return;
	else if (n == 1)
	{
		count++;
		printf("第%d步\n", count);
		printf("%c->%c\n", A, C);
	}
	else
	{
		hanoi(n - 1, A, C, B);
		count++;
		printf("第%d步\n", count);
		printf("%c->%c\n", A, C);
		hanoi(n - 1, B, A, C);
	}

}
int main()
{
	int n = 0;
	scanf("%d", &n);
	hanoi(n, 'A', 'B', 'C');
	printf("总共用了%d步", count);
	getchar();
	main();
	return 0;
}

写出递归函数真不用知道他在计算机中到底是怎么跑的,假设已经写完,再写出他的一个子问题即可。

3.斐波那契数列

#include<stdio.h>
double fib(int n)
{
	if (n <= 2)
	{
		return 1;
	}
	else
	{
		return fib(n - 2) + fib(n - 1);//递归思想
	}
}
int main()
{
	int n = 0;
	double ret = 0;
	scanf("%d", &n);
	ret = fib(n);
	printf("第%d个斐波那契数字是%.0lf",n, ret);
	return 0;
}

尾递归优化


long long fib(long long first,long long second,size_t n)
{
	if(n<2)
	{
		return n;
	}
	if(2 == n)
	{
		return first+second;
	}
	return fib(second,first+second,n-1);
	
}

三.迭代与递归的关系

递归中的基本情况(==0或==1时的情况),就好比迭代中的循环条件;

递归中的一般情况的“递”,不断减一,类似于i--

其它就类比于循环体,像阶乘,斐波那契数列改成迭代都比较简单,但汉诺塔实在也没想明白。

我会不断学习,争取早日填坑。感谢大家的观看和大佬的指点!!!

评论 10
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值