汉诺塔以及C语言练手经典题

本文介绍了C语言中常见的算法问题,包括汉诺塔、斐波那契数列、数字金字塔、大小写字母转换和素数判断。通过递归方法解决汉诺塔和斐波那契数列,强调了递归可能导致的效率问题,并提供了非递归解决方案。此外,还展示了数字金字塔的生成和大小写字母转换的代码实现,以及如何通过ASCII码差值进行转换。最后,详细解释了素数判断的算法,用布尔类型表示结果。
摘要由CSDN通过智能技术生成

目录

前言 (很重要)

  ​​​​​​递归求汉诺塔问题

 递归求斐波那契数列

 数字金字塔

大小写字母的转换

  ​编辑 

 判断是否为素数

结束语 


前言 (很重要)

        大家好,这里是小张,今天是五一劳动节,小张在这里祝大家劳动节快乐,然后今天给大家带来的是C语言入门经典题目详解。

         另外有很多小伙伴们在学习算法的时候,只去学习一些关于算法理论的知识,并不知道自己的代码实战能力如何,也不清楚到底对该算法的了解有多深,所以在这里小张给大家推荐一个很棒的平台,在这里有很多的面试和算法题,也有很多的面试和求职的机会,大家可以点击下方链接进入牛客网刷算法真题,提高自己代码实战能力,早日拿到满意的offer!
点击这里进入牛客网刷算法面试真题提高实战能力

  ​​​​​​递归求汉诺塔问题

汉诺塔(Tower of Hanoi),又称河内塔,是一个源于印度古老传说的益智玩具大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。

当只有一个盘子的时候可以直接从A移动到C:A->C
64fe0d6475a75956eda092da06f0ad86.gif

当有两个盘子的时候,就需要借助中转站B:A->B A->C B->C

b92c952b976bd09f1c13eb5a7b5297a2.gif

 当有三个盘子的时候,就需要借助中转站B和C:A->C A->B C->B A->C B->A B->C A->C

581b6c9f27f0609a6cd9c22b52c3b4bb.gif

思路 

  1. 将 n-1个环先放到B柱子上
  2. 将A柱子上的最后一个环移动到C柱子上
  3.  将n-1个环从B柱子移动到C柱子上

既然我们知道了思路那么我们来试试运用代码来实现:

#include<iostream>
using namespace std;
void move(char pos1,char pos2)
{
	cout << "     从" << pos1 << "移动到" << pos2 << endl;
}
void hanoi(int n,char pos1, char pos2, char pos3)
{
	if (n == 1)
	{
		move(pos1, pos3);
	}
	else
	{
		hanoi(n - 1, pos1, pos3, pos2);//把n-1个从起始位置pos1移动到pos2,pos3不就成了中转站//中转站:负责将两个位置的汉诺塔进行换位置以至于移动到预期的位置
		move(pos1, pos3);
		hanoi(n - 1, pos2, pos1, pos3);//再把n-1个从起始位置pos2移动到pos3,pos1不就成了中转站
	}
}
int main()
{
	int n = 0;
	cout << "请输入您要进行几个汉诺塔的移动" << endl;
	cin >> n;
	cout << "现在开始进行移动" << endl;
	hanoi(n, 'A', 'B', 'C');
	return 0;
}

 运行结果如下:
 2656207b29014ccc8f1ee908c4d7c654.png 

 递归求斐波那契数列

        那么什么叫做斐波那契数列呢,斐波那契数列指的是这样一个数列:1,1,2,3,5,8,13,21,34,55,89...这个数列从第3项开始,每一项都等于前两项之和。

 意思就是说数列的前两项都是1,后面的都是前两项之和,那么我们知道了原理,现在就开始写求斐波那契数列的代码:

int fin(int n){if (n == 2 || n == 1)//如果此时n为1或者n为2那么它的斐波那契数列就是1{return 1;}else{return fin(n- 1) + fin(n - 2);//如果不是前两项,那么它就返回前两项之和}}

 这一块是运用了递归进行求解

整体代码如下:

#include<iostream>
using namespace std;
int fin(int n)
{
	if (n == 2 || n == 1)//可以改成if(n<=2)
	{
		return 1;
	}
	else
	{
		return fin(n- 1) + fin(n - 2);
	}
}
int main()
{
	int n = 0;
	cin >> n;
	int sum = fin(n);
	cout << sum << endl;
	return 0;
}

递归的话好理解,但是计算机要执行多次重复的计算,会使工作量大大的增加,比如此时的斐波那契数列的递归,如果输入的值过大,那么就会计算很长时间,例如输入60,我的电脑就要至少计算十分钟左右,很长时间出不来结果:

 7d2d1a866b71432893c0a34d989827b7.png 

于是我们对于斐波那契数列可以使用非递归的方法,代码如下:
 

#include<iostream>
using namespace std;
int main()
{
	int i = 0, j = 0, n = 0, sum = 0, a = 0, b = 0;
	cin >> n;
	if (n <= 2)
	{
		sum = 1;
	}
	else if (n > 2)
	{
		a = 1;
		b = 1;
		for (i = 0; i < n - 2; i++)
		{
			sum = a + b;
			a = b;
			b = sum;
		}
	}
	cout << sum << endl;
	return 0;
}

 此时就能大大的提高计算的效率

 aff0f91ed9514f5995eebd4be0e76c70.png  

 数字金字塔

    1
   1 1
  1 1 1
 1 1 1 1
1 1 1 1 1

我们首先来观察这个金字塔,在第一行的1前面有四个空格,在第二行1的前面有三个空格,在第三行1的前面有二个空格,在第四行1的前面有一个空格,在第五行1的前面有0个空格。于是根据等差数列的通项公式可以得到在第i行有5-i个空格,那么这块的代码如下:
 

int j = 0;for (j = 0; j < 5-i; j++){cout << " ";//打印空格}

此时再来观察1的个数,在第一行有一个1,在第二行有两个1,在第三行有三个1,在第四行有四个1,在第五行1有五个1,于是在第n行的话就有n个1,这一块的代码如下:

for (j = 0; j < i; j++){cout << n<<" ";//打印数字}

 总体代码如下:
 

#include<iostream>
using namespace std;
int main()
{
	int i = 0, n = 0;
	cin >> n;
	for (i = 1; i <= 5; i++)
	{
		int j = 0;
		for (j = 0; j < 5-i; j++)
		{
			cout << " ";
		}
		for (j = 0; j < i; j++)
		{
			cout << n<<" ";
		}
		cout << endl;
	}
	return 0;
}

 运行结果如下:
 8f876fc06af1485ea945c740ec3dcb6d.png 

大小写字母的转换

  c5a8f5f329864b029e8dc59049d58b6b.png 

这是一张ASCII码表,我们不难看出大小写字母之间的差值为32,所以我们就可以利用这个差值来进行大小写字母的转换:
代码如下:

#include<iostream>
using namespace std;
int main()
{
	char arr[100];
	gets_s(arr);
	int i = 0, count = 0;
	while (arr[i] != '\0')
	{
		count++;
		i++;
	}
	for (i = 0; i < count; i++)
	{
		if (arr[i] >= 'a'&&arr[i] <= 'z')
		{
			arr[i] = arr[i] - 32;
			cout << arr[i] ;
		}
		else if (arr[i] >= 'A'&&arr[i] <= 'Z')
		{
			arr[i] = arr[i] + 32;
			cout << arr[i];
		}
	}
	return 0;
}

 其中的EOF是一个计算机术语,为End Of File的缩写,在操作系统中表示资料源无更多的资料可读取。资料源通常称为档案或串流。通常在文本的最后存在此字符表示资料结束。在控制台中可以通过CTRL+Z再按回车健结束

运行结果如下:

 a5e8d117125040859beb32e9afef7e4a.png 

 判断是否为素数

首先我们应该知道什么是素数,“素数一般指质数。质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。” 我们现在知道了素数的原理,那我们现在就开始写代码。

首先应该判断是否为素数,代码如下:

bool is_prime(int i)//布尔类型{int j = 0;for (j = 2; j < i; j++)//从二到它自身进行遍历{if (i%j == 0){return false;//不是素数,返回false}}if (j == i){return true;//是素数,返回true}}

这一块的代码是运用了布尔类型判断一个数是否为素数,如果一个数从二到自身前一个数都不能被整除的话,那么它就是素数,此时布尔类型返回true。

到了这里可能会有小伙伴不太理解什么是布尔类型,那我们就在此解释一下吧:

在c99种引入了布尔类型( bool)

  1. 布尔类型只有两个值,false 和 true。
  2. 通常用来判断条件是否成立。
  3. C语言语法规定,如果变量值为 0 就是 false,否则为 true,布尔变量只有这两个值。 

整体代码如下:

#include<iostream>
using namespace std;
bool is_prime(int i)
{
	int j = 0;
	for (j = 2; j < i; j++)
	{
		if (i%j == 0)
		{
			return false;
		}
	}
	if (j == i)
	{
		return true;
	}
}
int main()
{
	int i = 0;
	while (cin >> i)
	{
		if (is_prime(i))
		{
			cout << i << "是素数" << endl;
		}
		else if (!is_prime(i))
		{
			cout << i << "不是素数" << endl;
		}
	}
	return 0;
}

运行结果如下:
  5589a900eb1540f0b3e1b242889807d3.png  

结束语 

         到了这里今天的全波内容就已经全部的结束了,希望小张的这些题目的讲解可以给大家带来帮助,同时也希望大家可以多多支持支持小张,小张在这里提前谢谢大家啦!

b3d1ec2fa19547b58f4d46c278396fd6.png

评论 160
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小张﹉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值