【C语言】经典算法

自作多情 提交于 2019-12-23 01:41:24

判断闰年

什么是闰年?能被4整除不能被100整除的是闰年,或者能被4整除并且能被400整除的也是闰年。这样看来,我们就只要if就够了,贴上代码;

#include<stdio.h>
int main()
{
	int n;
	printf("Please input the year:\n");
	scanf("%d", &n);
	if(n % 4 == 0)
	{
		if(n % 100 == 0)
		{
			if(n % 400 == 0)
			printf("%d is leap year\n", n);
			else
			printf("%d is not leap year\n", n); 
		}
		else 
		printf("%d is leap year\n", n);
	} 
	else
	printf("%d is not leap year\n", n);
	return 0;
}

我们来试试用子函数

int intercalary(int year)
{return (year%4==0 && year%100!=0 || year%400==0);
}

int main()
{int n;
	printf("Please input the year:\n");
	scanf("%d", &n);
	if(intercalary(n)) 
		printf("%d is leap year\n",n);
	else printf("%d is not leap year\n",n);
}

最大公约数和最小公倍数

小知识点:两个数的乘积=他们的最大公约数与最小公倍数的乘积

那么就先求最大公约数:(在这里介绍三种方法)

①最经典的方法是辗转相除法

#include<stdio.h>
int main()
{
	int n, m, t,num1,num2;
	printf("Please input two number :\n");
	scanf("%d%d",&num1,&num2);
	n=num1;
	m=num2;
	if(n < m)//保证n不小于m 
	{
		t = m;
		m = n;
		n = t;
	}
	while(n % m)//当余数为0时 退出循环 
	{
		t = n % m;
		n = m;
		m = t;
	}
	printf("利用辗转相除法计算得到的最大公约数是:%d\n",m);
	printf("利用辗转相除法计算得到的最小公倍数是:%d\n",num1*num2/m);
	return 0;
 } 

②最暴力的方法:穷举法

void exp(int num1, int num2) {
		int  x, y, i;
		x = num1;
		y = num2;
		int max = 0;    //最大公约数
		for(i=1; i<=num1; i++) 
			if(num1%i == 0 && num2%i == 0) 
				max = i;
		printf("利用穷举法计算所得最大公约数为:%d\n",max);
		printf("利用穷举法计算所得最小公倍数为:%d\n", x*y/max);	//最小公倍数
	}

③再介绍一种:相减法

	void sub(int num1, int num2) {
		int x, y;  //用于保存num1,num2初始数据
		x = num1;  
		y = num2;
		while(num1 != num2) {           //循环条件为两数不相等
			if(num1 > num2)             //如果第一个数大于第二个数
				num1 = num1 - num2;     //两数相减
			else
				num2 = num2 - num1;
		}
		printf("利用相减法法计算所得的最大公约数为:%d\n",num1);
		printf("利用相减法法计算所得的最小公倍数为:%d\n", x*y/num1);}

冒泡排序

看完了前面两个简单算法,我们来到了排序算法,冒泡排序也是我们最先学的排序算法,他的原理是什么呢?
我们以升序排序为例:每次从最后一个元素开始,往前比较,如果这个元素比前一个元素小,那么他们两个就交换,反之就不交换。
降序排序则相反。我们先来看一个比较好理解的动图:
动态冒泡排序
我们可以看出,如果有n个元素,我们就要进行n-1轮外循环,第一轮要进行n-1次比较,第二轮进行n-2次比较…第 i 轮进行 n-i 次比较,时间复杂度比较大,我们来看看最坏的情况:
在这里插入图片描述
最后,我们贴上升序冒泡排序的代码:

#include<stdio.h>
int main()
{
	int a[5];
	int i, t, j;
	printf("Please input five number : \n");
	for(int i = 0; i < 5; i++)
	scanf("%d", &a[i]);
	for(int i = 0; i < 4; i++)
	for(int j = 4; j > i; j--)
	{
		if(a[j] < a[j - 1])
		{
			t = a[j];
			a[j] = a[j - 1];
			a[j - 1] = t;
		}
	}
	for(int i = 0; i < 5; i++)
	printf("%d ", a[i]);
	return 0;
 } 

选择排序

选择排序是另外一种排序方式,也是我个人比较喜欢的一种排序方式,虽然他们都是O(n2)的算法,但是选择在平均时间复杂度上还是少一点。选择排序
还是以升序为例:第一次选择出所有数中最小的那个,与第一个交换;第二次选择出从第二个数开始到最后一个数中最小的那个,与第二个交换……i 个数需要进行 i-1 轮外循环,每轮循环最多进行 1 次交换
来看看代码吧:

#include<stdio.h>
int main()
{
	int a[5];
	int i,t,min;
	printf("Please input five number : \n");
	for( i = 0; i < 5; i++)
	scanf("%d", &a[i]);
	for( i = 0; i < 5; i++)
	{min=i;//最小的数的下标
	for(int j = i+1; j < 5; j++)
	if(a[min] > a[j])  
	min=j;
	if(min!=i)//如果他不是最小的,就交换
	{
		t= a[min];
		a[min] = a[i];
		a[i] = t;
	}
	}
	for(i = 0; i < 5; i++)
	printf("%d ", a[i]);
	return 0;
 } 

判断素数

这个没有什么好说的,也是模拟吧,值得一提的是,我们不用循环到i-1,只要到根号 i就可以了。为什么是这样呢?可以自行推理一下。

#include<stdio.h>
#include<math.h> 
int main()
{
	int n;
	scanf("%d", &n);
	for(int i = 2; i <=sqrt(n); i++)
	{
		if(n % i == 0)
		{
			printf("%d is not prime number\n", n);
			return 0;
		}
	}
	printf("%d is prime number\n", n);
	return 0;
}

递归求阶乘

递归可能理解起来有点复杂
看代码吧,没什么好说的,简单 递归。

#include<stdio.h>
int fac(int n)
{
	int sum;
	if(n == 1 || n == 0)
	return n;
	sum = n * fac(n - 1);
	return sum;
}
int main()
{
	int n;
	scanf("%d", &n);
	printf("%d", fac(n));
	return 0;
}

这里有一个问题,就是数据范围的问题。如果n小的话还好,如果超过了13就爆int了,用longlong也解决不了多少问题。我们如果想求大数的阶乘,可能就需要用到高精度算法了。
如果想对递归有更深入的了解,不如去看一下汉诺塔问题,这是经典的递归问题。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!