您的位置:首页 > 其它

算法设计与分析——第一篇,写在前面的话

2016-09-24 21:15 183 查看
写在前面的话——

做程序员也有几年了,一直以来都是在有需要的时候,上网查查资料,看看别人写的博客来充实自己,有时候也会想写写随笔,学习笔记什么的,可是空空如也的我,一直以来都没有什么可以写的,不过既然决定重新回到学校,开始一段新的历程,那就还是写写吧,正好学校也开了算法设计与分析这门课,每节课后,老师都会要求写一篇当堂课的相关论文报告交上去,我就把我的每篇作业贴上来吧,不过都是参考书上的东西!

第一篇——

第一次作业比较简陋,主要是对一些简单的题目,写出一个基本的代码,加上一些分析

1,  求1000以内的完数

设计思想:完数的定义为该数的所有真因子之和仍等于其本身,由此可以预先排除掉数字1,而后需要求出所有大于1的数的所有真因子并且求和,当和为其本身的时候,该数为完数。

#include <stdio.h>

int main()
{
intn = 1000;
inti;
for(i= 2; i <= n; i++) {
intj;
intsum = 0;
for(j= 1; j < i; j++) {
if(0== i % j) {//求出所有的真因子
sum+= j;//求出真因子后进行求和
}
}
if(sum== i) {//若所有真因子之和和该数相等,则该数为完数
printf("%d为完数\n",i);
}
}

return 0;
}

2,  求一个输入的正整数的分化数目

设计思想:根据整数划分的思想,设函数Q(n,m)表示整数n的划分中最大加数为m的数目,可以得知:

(1)Q(n,1) =Q(1,m) = 1,因为无论是1的分划还是对于被加数最大为1,其都只有一种分划,即为n个1相加

(2)当n<m时,Q(n,m)=Q(n,n),因为被加数m显然不会超过n

(3)Q(n,m) =Q(n,m-1) + Q(n-m,m),Q(n,m-1)表示Q(n,m)中不包含m的划分,而Q(n,m)中包含m的划分可以通过对n-m进行不超过m的划分数目来取得

(4)当n=m时可以作为(3)的特殊情况,即Q(n,n)= Q(n,n-1) + 1

根据以上结论可以通过递归法求出结果

 

#include <stdio.h>

int Division(int n, int m)
{
if(n < 1 || m < 1) {
return 0;
} else if (n == 1 || m == 1) {//Q(n,1) = Q(1,m) = 1
return 1;
} else if ( n < m) {
return Division(n , n);
} else if ( n == m) {
return Division(n , n - 1) + 1;//Q(n,n) = Q(n,n-1)+ 1
} else {
returnDivision(n , m - 1) + Division(n - m , m);//Q(n,m) = Q(n,m-1) + Q(n-m,m)
}
}

int main()
{
int n;
printf("输入需要分化的整数:");
scanf("%d",&n);

int num = Division(n, n);
if(0 == num) {
printf("输入错误!\n");
} else {
printf("%d的分划数目为%d\n",n ,num);
}

return 0;
}

关于上面特别标了颜色的那条,也就是这个Q(n,m) =Q(n,m-1) + Q(n-m,m),当时百思不得其解,后来想通了,就是这个意思,可以理解为,Q(n,m)这个数字是由两部分组成,Q(n,m-1)代表Q(n,m)中不包含m的部分,那么剩下的就是仅包含m的部分,根据各种百度的说法,所谓求Q(n,m) 中仅包含m的部分,就是求Q(n-m,m),这个以我的能力非常不好解释,只能说看你能不能想到,简单来说,我就是找一个实例,分析,比如Q(6,4),那么4开头的项,是4+2和4+1+1,你可以想到,其实这个数目就是数字2的分划的数目,在看所谓Q(n,m)的m开头的项,其实就是m+(n-m),观察这个项,其实就是左边是m,右边就是n-m的分划,左边都是一样的,而右边的数目就是n-m分划的数目,所以整个是数目就是n-m的分划的数目,这个应该可以理解了吧,但是这个应该只是一种情况,就是Q(n,m)的m项的数目=Q(n-m,n-m),但是我们可以看到,实际上应该是等于Q(n-m,m),那么这个里面还有什么差别呢,呃,我没有研究,所以上面只是启发了一下大概的思考方向,如果要具体弄清楚,要么就是用数学的方法,要么就是找一些实例来验证,找到规律,我就不多说了!

 

 

3,分别使用递归和循环来实现输入一个任意十进制正整数,从低位到高位输出各位上的数字,再实现从高位到低位输出各位上的数字

设计思想:讲一个十进制正整数分拆开得到每一位的数字,首先可以通过对10取余得到个位的数字,然后通过除以10,去掉最后一位,再重复上一步,最终可以得到每一位的数字,但是如果使用循环法,因为不知道确切位数,直接求出最高位再依次得到低位比较麻烦,可以通过从低往高求出各位的数字再通过循环逆向输出,所以使用循环法会用到两次循环,但是如果使用递归法,可以通过调整递归调用和输出函数的位置来实现正向或逆向输出。

 

 

使用循环(从低位到高位):

#include <stdio.h>

int main()
{
intn,index = 1;
printf("输入一个十进制正整数:");
scanf("%d",&n);
if(n< 0) {
printf("输入错误!\n");
return0;
}

while(n> 10) {
printf("第%d位数字是%d\n",index ,n%10);//通过对10取余取出该位的数字
n= n/10;//由于是整型,通过除以10达到降低位数的目的
index++;
}
printf("第%d位数字是%d\n",index ,n%10);

return 0;
}

从高位到低位:

 

#include <stdio.h>

int main()
{
intn,index = 1,a[100] = {0};
printf("输入一个十进制正整数:");
scanf("%d",&n);
if(n< 0) {
printf("输入错误!\n");
return0;
}

while(n> 10) {
a[index]= n%10;
n= n/10;
index++;
}
a[index]= n%10;

inti;
for(i= index; i > 0; i--) {
printf("第%d位数字是%d\n",i,a[i]);
}

return 0;
}

使用递归从低位到高位:

#include <stdio.h>

void Division(int n)
{
if(n< 10) {
printf("最高位为%d\n",n);
}else {
printf("%d\n",n%10);
Division(n/10);
}
}

int main()
{
intn,index = 1,a[100] = {0};
printf("输入一个十进制正整数:");
scanf("%d",&n);
if(n< 0) {
printf("输入错误!\n");
return0;
}

Division(n);

return 0;
}

从高位到低位:

#include <stdio.h>

void Division(int n)
{
if(n< 10) {
printf("最高位为%d\n",n);
}else {s
Division(n/10);//先递归,待逐级返回之后再打印输出,从而实现从高位到低位
printf("%d\n",n%10);
}
}

int main()
{
intn,index = 1,a[100] = {0};
printf("输入一个十进制正整数:");
scanf("%d",&n);
if(n< 0) {
printf("输入错误!\n");
return0;
}

Division(n);

return 0;
}

上面这个题,其实很简单,其实想想,就是循环与递归的对比,从低位到高位输出的时候,没什么太大的区别,但是高位到低位顺序输出的时候,循环方法明显会麻烦一点,所以也体现了一个题选择合适的算法会提高效率避免无意义的循环!

 

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 循环 递归