算法的表达
好的,让我们来一起探讨如何向别人介绍我们的算法。说话很简单,但要把话说清楚,说明白就不那么容易了。同样的道理,能够通俗易懂,直观清晰和严谨地描述一个算法,也是一项具有挑战性的任务。接下来,让我们一起尝试,用生动有趣的方式,让算法的表达更加清晰易懂。
自然语言
先看一个例子,用自然语言描述从1开始的连续N个奇数求和的算法。
(1)确定一个N值。
(2)初始化总和sum=0,第一个奇数i=1。
(3)如果i<=N时候,执行第四步,否则执行第七步。
(4)总和sum自身加上i的值。
(5)i自身加上2。
(6)重新执行第三步。
(7)输出总和sum的值,算法结束。
从上面的描述中,我们可以发现用自然语言来阐述算法其实相当直接,就像是编写操作指南,一步步把过程详细列出。但这种方法也有它的短板:它往往不够简洁,而且由于每个人的表达习惯和方式不同,容易造成混淆和误解。所以,我们需要找到一种更加精确、统一的方式来描述算法,这样才能确保我们的算法被正确理解和执行。
流程图
首先来看流程图是怎样描述上面的例子,如图所示。
流程图的优势是形象直观,容易理解。另外大家要注意,流程图里面的矩形,菱形不是随意画的,每一个图形都有特定的意思,这样的设计能够避免歧义。下图列举了常用流程图图标的意义。
一般流程图我们可以用Word,PPT等办公软件去画,如果要画较复杂的流程图,建议使用专门的软件去设计。例如微软的Visio,也可以使用在线应用,如processon等。
伪代码
伪代码是一种超级实用的工具,它是用类似英语的句子和简单的符号来搭建起自然语言与计算机语言之间的桥梁。通常情况下,程序员会在真正开始敲代码之前,用伪代码来梳理他们的思路。拿上面的例子来说,用伪代码来描述的话,大概会是这个样子:
(1)Begin(程序开始)。
(2)input(输入)N。
(3)sum=0;i=1。
(4)while(如果)i<=N。
(5)begin(开始循环)。
(6)sum=sum+i;i=i+2。
(7)end while (结束循环)。
(8)output(输出)sum。
(9)End(结束程序)。
从上面例子可以看到,伪代码已经非常接近代码了,多在技术文档和科学出版物中出现,非常直观清晰地表达程序员的想法。由于没有固定程序语言的形式限制,这样可以让使用不同编程语言的程序员都能理解。
练手:这个月有多少天
下面使用自然语言和流程图来描述求解某个月份有多少天的算法。我们知道每个月的天数变动有以下6个规律。
(1)有31天的月份有:1,3,5,7,8,10,12。
(2)有30天的月份有:4,6,9,11。
(3)闰年2月是29天。
(4)非闰年2月是28天。
(5)闰年是一般年份能被4整除,如1996年是闰年,1997不是闰年。
(6)世纪闰年的年份能被400整除,如1900年不是世纪闰年,2000年是世纪闰年。
首先我们使用自然语言来描述这个算法。
(1)输入年份year和月份month。
(2)如果year>0并且1<=month<=12,进行第(3)步,否则到第(12)步。
(3)如果month是1,3,5,7,8,10,12,进行第四步,否则到第(5)步。
(4)输出31天。
(5)如果month是4,6,9,11,进行第(6)步,否则到第(7)步。
(6)输出30天。
(7)如果year整除100,进行第(8)步,否则到第(11)步。
(8)如果year整除400,那么到第(9)步,否则到第(10)步。
(9)输出29。
(10)输出28。
(11)如果year整除4,那么到第(9)步,否则到第(10)步。
(12)输出“输入有误”。
然后通过流程图来描述算法,具体如图所示。
有兴趣的读者可以尝试用程序去实现这个算法。在Python里面有标准库calendar模块,专门解决日期问题,可以用它来验证算法是否正确。
import calendar
print(calendar.monthrange(2000,2)[1]) # 输出 29
print(calendar.monthrange(1999,2)[1]) # 输出28
print(calendar.monthrange(2019,7)[1]) # 输出31
更多内容
想获取完整代码或更多相关图的算法内容,请查看我的书籍:《数据结构和算法基础Python语言实现》