今天,小江同学为大家带来5个亲测的干货初级C语言练习题。看完,练完,保证你的C语言跟上一层楼!
1. 排序问题
1.1 题目
请将 arr[10]={9,5,8,2,10,3,1,4,7,6}这一乱序的数组,编写一个函数 void bubble_sort(int arr[ ],int sz) ,该函数接收一个数组和字符个数为参数,并排成升序数组,并打印出来。
1.2 分析
这里,我们会使用冒泡排序。
1.2.1 冒泡排序
冒泡排序大致流程:
从数组下标0开始,依次比较相邻的2个下标所对应的数字,正序则不交换,倒序则交换,如此循环往复,直到数组有序(升序or倒序)为止。
例如,以下列数据为例,想得到升序数组:
先将下标0和1对应的数字3和2比较:3 > 2 ——> 交换
再将下标1和2对应的数字3和7比较:3 < 7 ——> 不交换
不断重复循环,直到第一次将7排到最后:
切记!7已经是最大的了,下一次排序不考虑和7排序了
............
以此类推,直到排序成功:(总共排序4次)
5个数字;排序4趟;第1趟排4次;第2趟排3次;第3趟排2次;第4趟排1次;
结论:设有n个数字,需要排序(n-1)趟,每一趟需要排(n-对应趟数);
1.3 代码实现
1.3.1 方法1:冒泡排序
#include<stdio.h>
void bubble_sort(int arr[], int sz)
{
//确定排序趟数
int i = 0;
for (i = 0; i < sz - 1; i++)
{
//每一趟排序次数
int j = 0;//表示下标
for (j = 0; j < sz - 1 - i; j++)//eg.i=0,排第一趟,排10-1-0=9趟;i=1,排第二趟,排10-1-1=8趟
{
if (arr[j] > arr[j + 1])
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
int main()
{
int arr[10] = { 9,5,8,2,10,3,1,4,7,6 };
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);//10
//对arr进行排序,排成升序
//arr是数组,对数组arr传参,实际上只传数组arr首元素的地址 &arr[0]
bubble_sort(arr, sz);//冒泡排序函数
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
输出界面
如果只传参arr[ ],会造成以下结果:
#include<stdio.h>
void bubble_sort(int arr[])
{
int sz = sizeof(arr) / sizeof(arr[0]);//10
printf("%d\n",sz);
}
int main()
{
int arr[10] = { 9,5,8,2,10,3,1,4,7,6 };
int i = 0;
//对arr进行排序,排成升序
//arr是数组,对数组arr传参,实际上只传数组arr首元素的地址 &arr[0]
bubble_sort(arr);//冒泡排序函数
return 0;
}
输出界面
1.3.2 方法2:冒泡排序进阶
由于冒泡排序效率低,计算量大,我们可以进一步优化:
#include<stdio.h>
void bubble_sort(int arr[], int sz)
{
//确定排序趟数
int i = 0;
for (i = 0; i < sz - 1; i++)
{
int flag = 1;//假设这一趟排序的数据已经有序
//每一趟排序次数
int j = 0;//表示下标
for (j = 0; j < sz - 1 - i; j++)//eg.i=0,排第一趟,排10-1-0=9趟;i=1,排第二趟,排10-1-1=8趟
{
if (arr[j] > arr[j + 1])
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
flag = 0;//本趟排序的数据其实不完全有序
}
}
if (flag == 1)
{
break;
}
}
}
int main()
{
int arr[10] = { 9,5,8,2,10,3,1,4,7,6 };
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);//10
//对arr进行排序,排成升序
//arr是数组,对数组arr传参,实际上只传数组arr首元素的地址 &arr[0]
bubble_sort(arr, sz);//冒泡排序函数
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
输出界面
2. 生兔子问题
2.1 题目
假定一对大兔子每月能生一对小兔子,且每对新生的小兔子经过一个月可以长成一对大兔子,具备繁殖能力,如果不发生死亡,且每次均生下一雌一雄,问一年后共有多少对兔子?
2.2 分析
首先,分2种情况:
1.一开始一对大兔子
2.一开始一对小兔子
大:i
小:j
这里涉及到斐波那契数列:
斐波那契数列指的是这样一个数列:1,1,2,3,5,8,13,21,34,55,89...
这个数列从第3项开始,每一项都等于前两项之和。
结论:i = i + j ; 现 i = 原 i + 原 j
j = i - j ;现 j = 现 i - 原 j
ps:这只是小江的思路哦,其他的也可以
2.3 代码实现
1.一开始一对大兔子
#include<stdio.h>
#include<string.h>
//开始是一对大兔子
int main()
{
int big = 1;
int small = 0;
for (int i = 1; i <= 12; i++)
{
big = big + small;
small = big - small;
}
printf("1年后总共%d对兔子\n",small+big);//377对
return 0;
}
输出界面
2.一开始一对小兔子
#include<stdio.h>
#include<string.h>
//开始是一对小兔子
int main()
{
int big = 0;
int small = 1;
for (int i = 1; i <= 12; i++)
{
big = big + small;
small = big - small;
}
printf("1年后总共%d对兔子\n", small + big);//233对
return 0;
}
输出界面
3.二分法查找问题
3.1 题目
请用二分法查找数组arr[10]={1,2,3,4,5,6,7,8,9,10}中的任意一个数字(数字不在数组中也可以),找到输出数字对应的下标,没找到输出没找到。
3.2 分析
3.2.1 二分法查找
以此类推,直到找到数字,或者循环结束
3.3 代码实现
#include<stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int k = 7;
int left = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
int right = sz - 1;
while (left <= right)//限制条件,如果left>right,出现错误
{
int mid = (left + right) / 2;//mid要在循环中定义,mid需要多次计算
if (arr[mid] < k)
{
left = mid + 1;
}
else if (arr[mid] > k)
{
right = mid - 1;
}
else
{
printf("找到了,%d的下标是%d\n", k, mid);
break;
}
}
if (left > right)
{
printf("找不到");
}
return 0;
}
输出界面
4.计算阶乘之和问题
4.1 题目
请计算1!+2!+3!+4!的和,并输出结果。
4.2 分析
1!+2!+3!+4!=1 * 1 + 2 * 1 + 3 * 2 * 1 + 4 * 3 * 2 * 2 * 1
4.3 代码实现
4.3.1 方法一
#include<stdio.h>
int main()
{
//求n的阶乘
int n = 0;
//1*2*3*4*5=120
int i = 0;
int ret = 1;//求n的阶乘,要*,所以ret不能=0
int sum = 0;//求n的阶乘的和,要+,所以sum=0
for (n = 1; n <= 4; n++)
{
ret = 1;//每次循环都需要从ret=1开始,否则ret的值会累积前面的阶乘值
for (i = 1; i <= n; i++)
{
ret = ret * i;
}
sum = sum + ret;
}
printf("%d \n", sum);
return 0;
}
输出界面
4.3.2 方法2(方法1的改进)
4!= 4 * 3 * 2 * 1
5!= 5 * 4 * 3 * 2 * 1 = 4!* 5
#include<stdio.h>
int main()
{
//求n的阶乘
int n = 0;
//1*2*3*4*5=120
int i = 0;
int ret = 1;//求n的阶乘,要*,所以ret不能=0
int sum = 0;//求n的阶乘的和,要+,所以sum=0
for (n = 1; n <= 4; n++)
{
ret = ret * n;
}
sum = sum + ret;
printf("%d \n", sum);
return 0;
}
输出界面
5. 2个数的最大公约数问题
5.1 题目
给定2个数,求2个数的最大公约数。
5.2 分析
最大公约数:即两个数据中公共约数的最大者。 求解的方式比较多,暴力穷举、辗转相除法、更相减损法、Stein算法算法 此处主要介绍:辗转相除法 思路: 例子:18和24的最大公约数 第一次:a = 18 b = 24 c = a%b = 18%24 = 18 循环中:a = 24 b=18 第二次:a = 24 b = 18 c = a%b = 24%18 = 6 循环中:a = 18 b = 6 第三次:a = 18 b = 6 c=a%b = 18%6 = 0 循环结束 此时b中的内容即为两个数中的最大公约数。
5.3 代码实现
#include<stdio.h>
int main()
{
int a = 32;
int b = 48;
int c = 0;
while (b % a)
{
c = b % a;
a = c;
b = a;
}
printf("%d", a);
return 0;
}
输出界面
PS:小江目前是个新手小白,目前,自己就总结了这些自己觉得有意义的题目。欢迎大家在评论区讨论哦!有问题也可以讨论的!