书名:Python算法详解
ISBN:978-7-115-50338-1
本书由人民邮电出版社发行数字版。版权所有,侵权必究。
您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。
我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。
如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。
编 著 张玲玲
责任编辑 张 涛
人民邮电出版社出版发行 北京市丰台区成寿寺路11号
邮编 100164 电子邮件 315@ptpress.com.cn
网址 http://www.ptpress.com.cn
读者服务热线:(010)81055410
反盗版热线:(010)81055315
本书循序渐进、由浅入深地讲解Python算法的核心技术,并通过具体实例的实现过程演练各个知识点的具体使用流程。全书共13章,包括算法,数据结构,常用的算法思想、线性表、队列和栈,树,图,查找算法,内部排序算法,经典的数据结构问题,数学问题的解决,经典算法问题的解决,图像问题的解决,游戏和算法等内容。
本书不但适合研究和学习算法的初学者,也适合有一定算法基础的读者,还可以作为大中专院校相关专业师生的学习用书和培训学校的教材。
从程序设计语言实践的角度而言,算法是有志从事信息技术领域工作的专业人员必须学习的一门基础理论课程。无论你采用哪一种程序设计语言编写程序,要使设计的程序能快速而高效地完成预定的任务,算法是一个关键因素。
市面上许多与算法相关的图书会介绍大量的理论或者讲解表达算法的核心概念,但是这类书缺乏完整的程序设计范例,因而对于第一次接触算法的初学者来说,将算法运用于实际应用就成了一道跨不过的鸿沟。为了帮助更多人用比较轻松的方式了解各种算法和各种经典数学问题的求解方法,本书包括了枚举算法、分治算法、贪心算法、试探算法、迭代算法;线性表、队列和栈; 二叉树、霍夫曼树;图的遍历、图的连通性、寻求最短路径;查找算法;内部排序法、插入排序法、交换类排序法、选择排序法、归并排序法、基数排序法;经典的数据结构问题,如约瑟夫环、大整数运算、顺序表的处理、链表的基本操作、基于列表实现二叉树、实现AVL树、使用二维数组生成有向图;经典数学问题的解决,如利用递归算法获取斐波那契数列前n项的值、通过多个进程验证哥德巴赫猜想、百钱买百鸡、素数问题、埃及分数式等。
为了让读者学以致用,每讲一个算法,同时都会给出具体的实例和运行的效果图。同时使用Python实现算法,以期能将各种算法真正应用在学习者将来的程序设计中。因此,这是一本学习算法的入门书。
(1)以“入门到精通”的写作方法构建内容,让读者入门容易。
为了使读者能够完全看懂本书的内容,本书遵循“从入门到精通”基础类图书的写法,循序渐进地讲解算法的知识。
(2)破解语言难点,以“技术解惑”贯穿全书,绕过学习中的陷阱。
为了帮助读者学懂算法,每章都会有“技术解惑”模块,让读者知其然又知其所以然。
(3)书中包含大量典型实例。
书中有大量实例,通过这些实例的练习,读者有更多的实践演练机会。
(4)通过QQ群和网站论坛实现教学互动,形成互帮互学的朋友圈。
本书作者为了方便给读者答疑,特地提供了网站论坛、QQ群等技术支持,并且随时在线与读者互动。让大家在互学互帮中形成一个良好的学习编程的氛围。
本书的论坛是toppr网站(网站后缀名为.net)。
本书的QQ群是292693408。
在编写过程中,本书得到了人民邮电出版社编辑的大力支持,正是各位编辑的敬业和高效,才使得本书能够在这么短的时间内出版。另外,十分感谢我的家人给予的巨大支持。本人水平毕竟有限,书中纰漏之处在所难免,诚请读者提出意见或建议。编辑联系邮箱是zhangtao@ptpress.com.cn。
最后感谢读者购买本书,希望本书能成为读者编程道路上的挚友,祝读者阅读快乐!
作者
本书由异步社区出品,社区(https://www.epubit.com/)为您提供相关资源和后续服务。
本书配套的资源是书中所有实例的源代码。
要获得以上配套资源,请在异步社区本书页面中单击,跳转到下载界面,按提示进行操作即可。注意,为保证购书读者的权益,该操作会给出相关提示,要求输入提取码进行验证。
如果您是教师,希望获得教学配套资源,请在社区本书页面中直接联系本书的责任编辑。
作者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。
当您发现错误时,请登录异步社区,按书名搜索,进入本书页面,单击“提交勘误”,输入勘误信息,单击“提交”按钮即可。本书的作者和编辑会对您提交的勘误进行审核,确认并接受后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。
我们的联系邮箱是contact@epubit.com.cn。
如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。
如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们;有意出版图书的作者也可以到异步社区在线提交投稿(直接访问www.epubit.com/selfpublish/submission即可)。
如果您是学校、培训机构或企业,想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。
如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接发邮件给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值的内容的动力之源。
“异步社区”是人民邮电出版社旗下IT专业图书社区,致力于出版精品IT技术图书和相关学习产品,为作译者提供优质出版服务。异步社区创办于2015年8月,提供大量精品IT技术图书和电子书,以及高品质技术文章和视频课程。更多详情请访问异步社区官网https://www.epubit.com。
“异步图书”是由异步社区编辑团队策划出版的精品IT专业图书的品牌,依托于人民邮电出版社近30年的计算机图书出版积累和专业编辑团队,相关图书在封面上印有异步图书的LOGO。异步图书的出版领域包括软件开发、大数据、AI、测试、前端、网络技术等。
异步社区
微信服务号
算法是程序的灵魂,只有掌握了算法,才能轻松地驾驭程序开发。软件开发工作不是按部就班,而是选择一种最合理的算法去实现项目功能。算法能够引导开发者在面对一个项目功能时用什么思路去实现,有了这个思路后,编程工作只需要遵循这个思路去实现即可。本章将详细讲解计算机算法的基础知识,为读者步入后面的学习打下基础。
自然界中的很多事物并不是独立存在的,而是和许多其他事物有着千丝万缕的联系。就拿算法和编程来说,两者之间就有着必然的联系。在编程界有一个不成文的原则,要想学好编程,就必须学好算法。要想获悉这一说法的原因,先看下面对两者的定义。
算法是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。也就是说,能够对符合一定规范的输入,在有限时间内获得所要求的输出。如果一个算法有缺陷,或不适合于某个问题,执行这个算法将不会解决这个问题。不同的算法可能用不同的时间、空间或效率来完成同样的任务。
编程是让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结果的过程。为了使计算机能够理解人的意图,人类就必须将需要解决的问题的思路、方法和手段通过计算机能够理解的形式“告诉”计算机,使计算机能够根据人的指令一步一步去工作,完成某种特定的任务。编程的目的是实现人和计算机之间的交流,整个交流过程就是编程。
在上述对编程的定义中,核心内容是思路、方法和手段等,这都需要用算法来实现。由此可见,编程的核心是算法,只要算法确定了,后面的编程工作只是实现算法的一个形式而已。
在1950年,算法(Algorithm)一词经常同欧几里得算法联系在一起。这个算法就是在欧几里得的《几何原本》中所阐述的求两个数的最大公约数的过程,即辗转相除法。从此以后,算法这一叫法一直沿用至今。
随着时间的推移,算法这门学科得到了长足的发展,算法应该具有如下5个重要的特征。
为了理解什么是算法,先看一道有趣的智力题。
“烧水泡茶”有如下5道工序:①烧开水,②洗茶壶,③洗茶杯,④拿茶叶,⑤泡茶。
烧开水、洗茶壶、洗茶杯、拿茶叶是泡茶的前提。其中,烧开水需要15min,洗茶壶需要2min,洗茶杯需要1min,拿茶叶需要1min,泡茶需要1min。
下面是“烧水泡茶”的两种方法。
方法1的步骤如下。
第1步:烧水。
第2步:水烧开后,洗刷茶具,拿茶叶。
第3步:沏茶。
方法2的步骤如下。
第1步:烧水。
第2步:烧水过程中,洗刷茶具,拿茶叶。
第3步:水烧开后沏茶。
问题:比较这两种方法有何不同,并分析哪种方法更优。
上述两种方法都能最终实现“烧水泡茶”的功能,每种方法的3个步骤就是一种“算法”。算法是指在有限步骤内求解某一问题所使用的一组定义明确的规则。通俗点说,就是计算机解题的过程。在这个过程中,无论是形成解题思路还是编写程序,都是在实施某种算法。前者是推理实现的算法,后者是操作实现的算法。
众所周知,做任何事情都需要一定的步骤。计算机虽然功能强大,能够帮助人们解决很多问题,但是计算机在解决问题时,也需要遵循一定的步骤。在编写程序实现某个项目功能时,也需要遵循一定的算法。在本节的内容中,将一起探寻算法在计算机中的地位,探索算法在计算机中的基本应用知识。
计算机中的算法可分为如下两大类。
假设存在如下运算:1×2×3×4×5,为了计算上述运算结果,最普通的做法是按照如下步骤进行计算。
第1步:先计算1乘以2,得到结果2。
第2步:将步骤1得到的乘积2乘以3,计算得到结果6。
第3步:将6再乘以4,计算得24。
第4步:将24再乘以5,计算得120。
最终计算结果是120,上述第1步到第4步的计算过程就是一个算法。如果想用编程的方式来解决上述运算,通常会使用如下算法来实现。
第1步:假设定义t=1。
第2步:令i=2。
第3步:把t×i的乘积仍然放在变量t中,可表示为t×i→t。
第4步:把i的值加1,即i+1→i。
第5步:如果i5,返回重新执行步骤3以及其后的步骤4和步骤5;否则,算法结束。
由此可见,上述算法方式就是数学中的“n!”公式。既然有了公式,在具体编程的时候,只需要使用这个公式就可以解决上述运算问题。
再看下面的一个数学应用问题。
假设有80个学生,要求打印输出成绩在60分以上的学生。
在此用n表示学生学号,用ni表示第i个学生的学号;用cheng表示学生成绩,用chengi表示第i个学生的成绩。根据题目要求,可以写出如下算法。
第1步:1→i。
第2步:如果chengi60,则输出ni和chengi,否则不输出。
第3步:i+1→i。
第4步:如果i80,返回步骤2;否则,结束。
由此可见,算法在计算机中的地位十分重要。所以在面对一个项目应用时,一定不要立即编写程序,而是要仔细思考解决这个问题的算法是什么。想出算法之后,以这个算法为指导思想来编程。
算法是计算机处理信息的基础,因为计算机程序本质上就是算法,告诉计算机确切的步骤来执行一个指定的任务,如计算职工的薪水或打印学生的成绩单。通常,当算法在处理信息时,数据会从输入设备读取,写入输出设备,也可能保存起来供以后使用。
著名计算机科学家沃思提出了下面的公式。
数据结构+算法=程序
实际上,一个程序应当采用结构化程序设计方法进行程序设计,并且用某种计算机语言来表示。因此,可以用下面的公式表示。
程序=算法+数据结构+程序设计方法+语言和环境
上述公式中的4个方面是一种程序设计语言所应具备的知识。在这4个方面中,算法是灵魂,数据结构是加工对象,语言是工具,编程需要采用合适的方法。其中,算法是用来解决“做什么”和“怎么做”的问题。实际上程序中的操作语句就是算法的体现,所以说,不了解算法就谈不上程序设计。数据是操作对象,对操作的描述便是操作步骤,操作的目的是对数据进行加工处理以得到期望的结果。举个通俗点的例子,厨师做菜肴,需要有菜谱。菜谱上一般应包括:①配料(数据),②操作步骤(算法)。这样,面对同一原料可以加工出不同风味的菜肴。
在1.2.1节中演示的算法都是通过语言描述来体现的。其实除了语言描述之外,还可以通过其他方法来描述算法。在接下来的内容中,将简单介绍几种表示算法的方法。
流程图的描述格式如图1-1所示。
图1-1 流程图标识说明
再次回到1.2.1节中的问题。
假设有80个学生,要求输出成绩在60分以上的学生。
针对上述问题,可以使用图1-2所示的算法流程图来表示。
图1-2 算法流程图
在日常流程设计应用中,通常使用如下3种流程图结构。
图1-3 顺序结构
图1-4 选择结构
图1-5 循环结构
上述3种基本结构有如下4个特点,这4个特点对于理解算法很有帮助。
(1)只有一个入口。
(2)只有一个出口。
(3)结构内的每一部分都有机会被执行到。
(4)结构内不存在“死循环”。
在1973年,美国学者提出了N-S流程图的概念,通过它可以表示计算机的算法。N-S流程图由一些特定意义的图形、流程线及简要的文字说明构成,能够比较清晰明确地表示程序的运行过程。人们在使用传统流程图的过程中,发现流程线不一定是必需的,所以设计了一种新的流程图,这种新的方式可以把整个程序写在一个大框图内,这个大框图由若干个小的基本框图构成,这种新的流程图简称N-S流程图。
遵循N-S流程图的特点,N-S流程图的顺序结构图1-6所示、选择结构如图1-7所示、循环结构如图1-8所示。
图1-6 N-S流程图的顺序结构
图1-7 N-S流程图的选择结构
图1-8 N-S流程图的循环结构
因为算法可以解决计算机中的编程问题,是计算机程序的灵魂,所以可以使用计算机语言来表示算法。当用计算机语言表示算法时,必须严格遵循所用语言的语法规则。再次回到1.2.1节中的问题:1×2×3×4×5。如果用Python语言编程来解决这个问题,可以通过如下代码实现。
源码路径:daima\第1章\math.py
a = 1
n = 5
for i in range(1,n+1):
a = a * i
print(a)
上述代码是根据1.2.1节中的语言描述算法编写的,因为是用Python语言编写的,所以需要严格遵循Python语言的语法,例如严格的程序缩进规则。
在一些培训班的广告中,到处充斥着“一个月打造高级程序员”的口号,书店里也随处可见书名打着“入门捷径”旗号的书。有过学习经验和工作经验的人们往往深有体会,这些宣传不能全信,学习编程需要付出辛苦和汗水,需要付出相当多的时间和精力。结合作者的学习经验,现给出如下学习建议。
(1)学得要深入,基础要扎实。
基础的作用不必多说,基础的重要性在大学课堂上老师曾经讲过很多次,在此重点说明“深入”。职场不是学校,企业要求你能高效地完成项目功能,但是现实中的项目种类繁多,需要从根本上掌握算法技术的精髓,入门水平不会被开发公司所接受,他们需要的是高手。
(2)要有恒心,不断演练,举一反三。
学习编程的过程是枯燥的,要将学习算法作为自己的乐趣,只有做到持之以恒才能掌握到编程的精髓。另外,编程最注重实践,最害怕闭门造车。每一个语法,每一个知识点,都要反复用实例来演练,才能加深对知识的理解,并且要做到举一反三,只有这样才能对知识有深入的理解。