引言:
瑞士著名的科学家Niklaus Wirth教授曾提出:数据结构+算法=程序。
数据结构是程序的骨 算法是程序的灵魂。在生活中,算法无处不在。每天早上起来,刷牙、洗脸、吃早餐,都在算着时间,以免上班或上课迟到;去超市购物,在资金有限的情况下,考虑先买什么、后买什么,算算是否超额;在家中做饭,用什么食材、调料,具体的烹饪方法和步骤如何,做完了还要品尝一下咸淡,看看是否做熟。所以,不要说你不懂算法其实你每天都在用!
.妙不可言——算法的复杂性
首先看书上一道例题,写一个算法,求一下序列之和:-1,1,-1,1,...,(-1)
当你看到这个题目时,你好怎么想?for语句? while循环?
看计算机算法1
再看计算机算法2
看到这段代码后你可能恍然大悟 可以这样啊?这不就是数学家高斯使用的算法吗?
1787年,10岁的高斯用了很短的时间就算出了结果,而其他孩子却要算很长时间。
可以看出,算法1.1需要运行+1次,如果n= 100 00,就要运行100 01次,而算法1-2仅仅需要运行1次!是不是有很大差别?
高斯的方法我也知道,但遇到类似的题还是 我用的笨办法也是算法吗?
答:是算法。
算法是对特定问题求解步骤的种描述
算法只是对问题求解方法的一种描述,它不依赖于任何一种语言,既可以用自然语言、程序设计语言(C、C++、Java、Python等)描述。也可以用流程图、框图来表示。通常情况下,为了更清楚地说明算法的本质,我们会去除计算机语言的语法规则和细节,采用“伪代码”来描述算法。“伪代码”介于自然语言和程序设计语言之间,它更符合人们的表达方式,容易理解,但它不是严格的程序设计语言。如果要上机调试,则需要转换成标准的计算机程序设计语言才能运行。
算法具有以下特性。
(1)有穷性:算法是由若干条指令组成的有穷序列,总是在执行若干次后结束,不可能永不停止。
(2)确定性:每条语句都有确定的含义,无歧义
(3)可行性:算法在当前环境条件下可以通过有限次运算来实现。
(4)输入/输出:有零个或多个输入以及一个或多个输出。
2.一棋盘的麦子
引入故事:有一个古老的传说。 位国王的女儿不幸落水,水中有很多鳄鱼,国王情急之下下令:“谁能把公主救上来,就把女儿嫁给他。”很多人纷纷退让, 个勇敢的小伙子挺身而出,冒着生命危险把公主救了上来,国王看是个穷小子,想要反悔,说:“除了女儿,你要什么都可以。”小伙子说:“好吧,我只要一棋盘的麦子。您在第1个格子里放1粒麦子,在第2个格子里放2粒,在第3个格子里放4粒,在第4个格子里放8粒,以此类推,每一个格子里麦子的粒数都是前一格子里麦子粒数的两倍。把这64个格子放满了就行,我就要这么多。国王昕后哈哈大笑,觉得小伙子的要求很容易满足,满口答应。结果发现,把全国的麦子都拿来,也填不完这64个格子.国王无奈,只好把女儿嫁给了这个小伙子。
解析
棋盘上的64个格子究竟需要放多少粒麦子?
把每一个格子里需要放的麦子粒数加起来,总和为S,则:
S=1+21+22+23++2831
对式1等号的两边乘以2,等式仍然成立:
2S=21+22+23,+263+2642
用式2减去式①,得:
S=264-1-18 446 744 073 709 551 615
据专家统计,每题麦粒的平均重星约41.9毫克,这些麦粒的总重量为:
18 446 744 073 709 551 615 ×41 9=772 918 576 688 430 212 668.5(毫克)
=7729/000(亿千克)
全世界人口按77亿计算,每人差不多可以分得100000千克(即100吨)
3.神奇的兔子数列
假设第1个月有1对初生的兔子,第2个月进入成熟期,第3个月开始生育兔子,而1对成熟的兔子每月会生1对兔子,兔子永不死去….…那么,由1对初生的兔子开始,12个月后会有多少对兔子呢?
问题分析
不妨拿新出生的1对小兔子分析。
第1个月,小兔子1没有繁殖能力,所以还是1对。
第2个月,小兔子1进入成熟期,仍然是1对。
第3个月,兔子1生了1对小兔子2,于是这个月共有2(1+1=2)对兔子。
第4个月,兔子1又生了1对小兔子3,因此共有3(1+2=3)对兔子。
第5个月,兔子1又生了1对小兔子4,而在第3个月出生的兔子2也生下了1对小兔子⑤,因此共有
5(2+3=5)对兔子。
第6个月,兔子1 2③各生下了1对小兔子,新生的3对兔子加上原有的5对兔子,这个月共有
8(3+5=8)对兔子。
当斐波那契通过兔子繁殖告诉我们这种数学问题的本 字质——随着数列项的增加,前一项与后一项之比越来越逼近黄金分割数0.618时,我被彻底震撼,因为数学可以表达美,这是数学令我们叹为观止的地方。当数学创造出更多的奇迹时,我们会发现数学在本质上是可 换以回归自然的,这样的事例让我们感受到数学的美,就像黄金分割、斐波那契数列,它们如同大自然中的
朵朵小花,散发着智慧的芳香.....
4.算法学习瓶颈
很多人感叹:算法为什么这么难学!
一个原因是,算法本身具有一定的复杂性。另一个原因是,讲得不到位!
算法的教与学有两个困难。
(1)我们学习了那些经典的算法,在惊叹它们奇妙的同时,难免疑虑重重:这些算法是怎么被想到的?这可能是最费解的地方。高手讲,学算法要学它的来龙去脉,包括种种证明。但对菜鸟来说,这简直比登天还难,他们很可能花费很多时间也无法搞清楚。对大多数人来说,这条路是行不通的,那怎么办呢?下功夫去记忆书上的算法?记住这些算法的效率?这样做看似学会了,其实两手空空,遇到新问题时仍无从下手。但这偏偏又是极为重要的,无论是做研究还是做实际工作,计算机专业人士最重要的能力就是解决问题
一解决那些不断从实际应用中冒出来的新问题。
(2)算法作为一门学问,有两条几乎平行的线索。一条是数据结构(数据对象:数、矩阵、集合、申、排列、图、表达式、分布等。另一条是算法策略:责心策略、分治策略、动态规划策略、线性规划策略、搜索策略等。这两条线索是相互独立的:对于同一个数据对象上不同的问题(如单源最短路径和多源最短路径),就会用到不同的算法策略(如贪心策略和动态规划策略);而对于完全不同的数据对象上的问题(如排序和整数乘法),也许就会用到相同的算法策略(如分治策略)
两条线索交织在一起,该如何表述呢?我们早已习惯在一章中完全讲排序,而在另一章中完全讲图论。还没有哪一本算法书能够很好地解决这两个困难,传统的算法书大多注重内容的收录,却忽视思维过程的展示,因此我们虽然学习了经典的算法,却费解于算法设计的过程。
本书从问题出发,根据实际问题分析、设计合适的算法策略,然后在数据结构上操作实现,巧妙地将数据结构和算法策略拧成一条线。全书通过大量实例,充分展现算法设计的思维过程,让读者充分体会求解问题的思路、如何分析、使用什么算法策略、采用什么数据结构、算法的复杂性如何、是否有优化的可能等等。这里,我们培养的是让读者怀着一颗好奇心去思考问题、解决问题,更重要的是—体会学习的乐趣,发现算法的美!
6.忠告
持之以恒地学习,没有什么是学不会的。行动起来,没有什么不可以!