课程内容

开篇词 | 为什么我们要学习编程?

为什么需要学习编程?

如今,学习编程的人分为两类,一类是程序员,另一类是期望成为程序员的人。

编程这个事儿,在大多数人眼中还是一种特定领域的、专门的技能,认为学的人都是需要以此谋生的。

其实,作为一个“码龄”超过20年的老程序员,我是这样认为的:在不久的将来(也许三五年,也许十来年之后),编程将从一个职业技能逐步蜕变为职场通用技能

对此,我们可以类比“识字”这个技能来看——

百十年前,大多数老百姓都不认识母语文字。当年具备了“认字”这一技能的人,就可以获得比大多数人更优越的工作环境,报酬更高的职位。那时,识字无疑是一种必备的职业技能。

但到了今天,识字率已经差不多100%了,具备此技能已经不再是职场的加分项了。相反,如果在今天不认字,那恐怕注定只能从事低端工作了。而如今的职场环境,要比之前要求的多,除了基本的电脑办公软件,要求会编程,也在各个互联网公司的面试中开始蔓延开来。

类似的技能还有:

驾驶——汽车工业发展起来后,职业司机越来越少,驾驶逐渐成为人们的通用技能。

在未来,编程就会成为人人都会做的事情,作为势必要踏入职场中的一员,除了要具备听说读写本国语言的能力外,还需要能够读写代码。

不久的将来,职业写代码的人,将越来越少。取而代之的,编程将是每个职业人的必备技能,拥有更多技能的人,就更有拿到好offer,升职加薪的机会。

即便现在一时之间无法达到社会全员编程的地步,至少是朝着这个方向发展,未来3年或5年,编程将成为互联网从业者的必修课。所以,在此我们要把握这个机会,勇敢的迎上新时代的机遇,只有把握先机的人,才会在未来的发展中有一席之地。

点击了解更多《编程算法同步入门》

那么编程的核心是什么?

从语言特征(词汇、语法等)的角度来讲,最复杂的编程语言远比最简单的自然语言简单得多

我们学习各种自然语言是为了日常生活与人交流、收发信息,那么,学习编程语言又是为什么呢?

其实是为了用编程语言来描述事物、概念,以及它们之间的相互关系和运行方式,将我们身处在的大千世界转化为一台计算机能够理解的电信号,驱动硅晶金属构造的计算机部件去完成任务!我们学会了这门语言,用来和计算机交流,在反过来作用于自己,创造更多的价值。

编程的核心在于通过各种各样的算法去实现具体的业务逻辑,把繁杂的过程抽象化、可计算化。

从纯粹软件的角度讲,甚至可以说:算法 + 数据 == 计算机程序。

受过计算机科班教育的人一定上过一门课:数据结构,这门课是计算机科学的基础,它的核心内容就是各式各样的算法,它们是几代计算机科学家从解决现实问题中提取出的套路——这些才是编程的核心。

经得起时间考验的通识技能

计算机技术从诞生起就处在飞速发展之中。编程语言从无到有,从少到多,从最初的01代码,机器语言到后来百花齐放的高级语言,此消彼长,兴衰交替。

各种工具、框架更是日新月异,各领风骚三五年乃至三五月就被淘汰者成百上千。但是经由现实问题中提炼出来的经典算法,却经得起时间的考验。

这些经典算法是计算机发展过程中世界上最聪明的一小撮人千锤百炼出的,解决某些模式问题的方法和策略。

这些方法和策略基于人类几千年文明史的思维积淀,又经历了最严格的数学分析和验证,本身既是人类文明的结晶,同时又是一种有效的思维训练。这种逻辑思维能力,也能用于平时的生活中解决问题,当你的逻辑思维被打通,你会发现没什么难事,都会有解决方法。

用数值表达现实事物,用运算描述任务目标,再通过算法处理数据找到达到目标的最优化路径——这个思维的形成过程,远比学会模型本身更为难得。

经过这种思考训练内化出的思维能力,也是学习者可以相伴终身的助力。

本课讲了些什么?

本课程就带领大家,由编程学算法,以算法促编程。从零开始,同步学习两方面内容:

  • 使用 Python 语言编写程序;
  • 最基础的经典算法。

除此之外,为了帮助大家理解算法,对于计算机的基础运行原理也有介绍。

在大学计算机系课程中,本课程所讲述的内容被拆分在几门课里:

  • 程序设计语言(Python)
  • 数据结构
  • 计算机组成原理和体系结构

不过本课没有像一般大学课程安排那样,将这几部分割裂开,而是融会在一起,按下列顺序进行讲解:

1.从我们熟悉的日常事物开始,讲解软件、程序、算法和编程分别是什么。

2.编程两大要素:控制流程和数据结构。

3.几种最常见的数据结构(数组、链表、树和图)。在此过程中,由数据结构的限制和实现引出现代电子计算机的基础:二进制和冯诺依曼结构。

4.进入算法阶段,从最简单的顺序查找开始,一边讲算法,一边讲它们的编程实现。

  • 详细讲解的经典算法包括:

  • 顺序查找

  • 二分查找

  • 简单排序
    • 选择排序
    • 起泡排序
    • 插入排序
  • 快速排序

  • 编程和 bug 总是难舍难分,为了系统性减少 bug ,就要讲软件工程。

  • 讲算法就离不了策略,分治策略是快速排序的基础,而引申自数学的递归则是分治策略的实现方法……

5.结课前会给出本课之后继续学习算法和编程的方向与方法。

祝大家学习顺利,有所提高!接下来让我们一起,迈入编程的大门!

点击了解更多《编程算法同步入门》

分享交流

我们为本课程付费读者创建了微信交流群,以方便更有针对性地讨论课程相关问题。入群方式请到第 2-1 课末尾添加小助手的微信号,并注明「同步入门」。

阅读文章过程中有任何疑问随时可以跟其他小伙伴讨论,或者直接向作者提问(作者看到后抽空回复)。你的分享不仅帮助他人,更会提升自己。

1-1课:又回到最初的起点:软件和程序

软件和程序

每每提到“编程”这个词,大家都会觉得这是件高端、神秘的事,或者会皱皱眉头,觉得这肯定是个挺难的事儿吧?

基本所有与编程没有打过交道的人,都认为编程似乎被一群秃头的程序员垄断了,是一种旁人无法介入的专属行为。

而就在这一两年里,“少儿编程”的概念又伴随着素质教育、stem 教育迅速崛起。好像一时之间,连小学生、幼儿园小朋友都开始学编程了。而且还有不少幼儿型选手拿了不少编程大奖!

所以,编程到底是个啥玩意儿?是不是真的有这么难呀?

软件是什么

要说编程,首先就要先说一说计算机。计算机大家都不陌生吧,就算是一个完全不懂编程的人,也每天会用到——工作中用来处理资料、文档的台式机、笔记本,看剧的 pad ,日常不离身的智能手机,这些其实都是计算机。

如果我们把计算机拆开,看到的是若干电路和电子元件。把这些东西组合起来,通电开机,就可以用来读新闻、刷抖音、听歌、 写文章、P照片、打游戏、看 idol ,发微博/微信……了。

你有没有想过,计算机能做这么多事,仅仅是因为有那些电子器件吗?当然不是!

我们新买来一个智能手机,上面的 App 少得可怜,最初的时候啥也干不了。需要我们自己去下载各式各样的 App 。

这些 App 又被称作应用软件,这些 App 正是通过编程制作出来的。

手机 App 是软件,台式机上的各种应用(浏览器、文本编辑器、图像处理工具等)是软件,嵌入式系统中的应用(汽车的防锁死刹车系统、核磁共振成像设备、大型固定装置如交通灯、工厂控制器,以及在非智能手机时代曾红极一时的 mp3 机中的播放器和手持 PDA 中的应用等)也是软件。

软件可以简单的被认为是一组程序,这组程序相互配合,通过接受输入、产生输出,来为我们每一个人解决问题或完成任务。

互联网软件

日常生活中,你打开微信,在朋友圈发了一张自拍,并精心配上准备好的文案“今天也要做个精致的猪猪男孩/女孩”这样的文字,然后点击“发表”按钮。

你的朋友圈里就显示出了你刚发的图和文字,你的朋友刷到了你的朋友圈顺手给你点赞评论一条龙。

这几个步骤对你而言可能只要几秒钟,但是在这样一个简单的过程背后,却有多个程序在为你提供服务。

首先你点击“微信”的绿色图标,然后点“发现”->“朋友圈”->朋友圈右上角的小相机图标,到相机选择照片,输入文字,最后点击“发表”。

这个过程看起来是你在干活,其实微信软件也没闲着:

1.微信的前端程序在接受你的输入(每次点击按钮、上传照片和键入文字都是用户输入),将每一次输入记录下来。

2.在你点击了“发表“之后,微信前端将之前的输入打一个数据包,注明这是你新发的朋友圈内容,通过互联网发送给后端程序。

3.后端程序接收到了前端的发来的“发朋友圈”请求之后,会读取数据包,从中取出你的照片和配图文字,把它们记录(存储)下来。

当你点完“发表“返回到朋友圈之后,看起来你并没有再做什么事情,然而这个”进入朋友圈“的动作就表示了你要阅读朋友圈内容。微信又会有一系列动作:

1.微信前端程序又会向后端程序发出一条请求,要求阅读最新的朋友圈内容。

2.后端收到这个命令后,会把最新的朋友圈内容打一个数据包发送回来。

3.前端接收到这个数据包后,会将其中的内容(图片、文字)按特定的格式显示出来。你通过手机屏幕看到的,就是这种显示的结果。

上述过程其实经过了简化,实际情况要复杂得多。

目前,我们暂时掌握前端、后端和通讯的概念就好。几乎所有的互联网应用都涉及到这几个概念。

我们手机上的 App 经常要更新,每次我们更新的都只是前端程序而已,更新前端后,经常会发现新的版本显示文字、图片的样式不同的,新的版本又加入了新的功能(比如新的页面、新的按钮)等变化。

实际上,一般互联网软件后端程序更新得往往比前端更频繁。只不过后端程序部署在开发软件的公司或个人自己的服务器上(或者第三方的云服务器上),更新的过程不被用户察觉而已。

因为内容来自于后端,所以,就算你的手机上有前端程序,如果网络不通,或者后台宕机,也无法使用该软件。

这是我们现在日常用到最多的互联网软件,大概就是这样运作的了。

点击了解更多《编程算法同步入门》

单机版软件

在互联网时代到来之前,我们用的软件基本是单机版软件,比如常用的 Word , PowerPoint , Photoshop 等——当然现在这些工具也互联网化了。

单机版软件需要专门的安装程序(还记得光盘、软盘吗)一次只能安装到一台机器上(单机版软件流行的时候大家基本都在用台式机),软件中所有的程序都在一台机器上运行。

那个时候,软件是要钱的,一张光盘理论上只能安装一台机器,因为你买的是license(安装许可证)——一张光盘都好贵的,当年微软的办公套件一套就要成千上万的。

所以当初在学校和普通家庭里,流行的是盗版和破解版……回首看好像是很久以前了,其实也不过就十来年前而已。

程序又是什么?

到底什么是程序呢?程序接受输入,根据输入完成某些特定任务后产生输出——你有没有发现,这么听起来和软件不是一样嘛?确实,无论程序还是软件,都会接受输入,产生输出。

软件是由若干程序组成的,在多个程序组成的软件中,具体某一个程序都有输入和输出。但往往这个程序接受的不是全部用户输入,或者产生的输出也不是全部用户输出,而是输入或输出某些中间结果,经过几个程序的共同努力,才将原始输入转化成了最终成果展示出来。

打个比方,软件就像一条完整的流水线,能够把原材料加工成最终产品,一个个程序则像其中的一道道工序,这些工序的联合协作,完成了整个生产过程。

如果软件的功能非常简单,一个软件也可以只有一个程序。

理论上讲,其实很多全部功能都安装部署在一台机器上的软件(单机版软件),都可以把所有功能写在一个程序里。

但是在现实当中我们会故意不这样做。原因是,复杂软件的功能太多,如果所有功能都用一个程序来实现,会导致这个程序的源代码过多,程序结构很难清晰,管理和维护起来的成本太高。

等等,这里怎么又出来了一个“程序的源代码“,它和程序不是一回事嘛?且听下回分解啦!

点击了解更多《编程算法同步入门》

分享交流

我们为本课程付费读者创建了微信交流群,以方便更有针对性地讨论课程相关问题。入群方式请到第 2-1 课末尾添加小助手的微信号,并注明「同步入门」。

阅读文章过程中有任何疑问随时可以跟其他小伙伴讨论,或者直接向作者提问(作者看到后抽空回复)。你的分享不仅帮助他人,更会提升自己。

1-2课:安静的程序,淘气的程序和编写程序

静态程序——程序的源代码

上一章我们讲到了程序的源代码,你是不是很好奇它和程序到底是不是一回事儿啊?

严格来讲,“程序”和“程序的源代码”并不是一回事情噢。

程序的源代码是指用编程语言编写出来的程序的逻辑,是静态的文本,我们暂且可以叫 TA 安静的程序,一般被存储为以特定字符串为后缀的文件。

比如下面就是一个 Python 程序(程序员世界中最著名的打印“Hello World”的程序),被保存为FirstProgram.py (py是python文件的特定后缀)。

def main():    print("Hello World")if __name__ == "__main__" :    main()

是不是有点看不懂,没关系,听我给你娓娓道来,这个程序的名字叫做 FirstProgram ,FirstProgram.py 文件里面的内容就叫做 FirstProgram 程序的源代码, FirstProgram 程序源代码的功能是在运行该程序的计算机的显示器屏幕上打印“Hello World”字样。

你可以把上面的代码拷贝到一个文本文件里,然后将该文件存储为“FirstProgram.py"——注意后缀,后面没有“.txt”。

让程序跑起来——运行程序

光有了程序的源代码还不行,因为静止的程序什么都干不了。要让程序干活,就得让它先跑起来。

这时,我们就需要程序的运行环境

涉及到运行环境,不同的编程语言的具体需求不一样,这里又涉及到编译执行、解释执行等概念,不要着急,这些后面会讲到。

在此处,我们只需要知道, Python 的运行环境是一个专门的软件,需要下载安装就可以了。

如果你想和我们一起上这门课,那就一起先来到 Python 的官网下载安装Python的运行环境吧:

点击可下载安装 Python 的运行环境

打开 Python 下载页面你会发现里面有好多版本,我推荐你安装 Python3 最新版。其实任何以 Python3 开头的版本都可以,不过对于这类软件,大家都习惯于去追最新版。

而且最新版就在下载页面最显眼的地方,好找,比如下图是2019年5月的下载页头部,你读到这儿的时候,可能版本已经有所不同,不过最新版的位置总是大同小异:

注意:不要选 Python2 因为 Python2 和 Python3 对源码的要求有些不同。

当然,你如果非要装 Python2 ,别怪我没有提醒你,本课所有的例子都是用 Python3 写的噢,如果装了 Python2 ,部分代码需要改写才能运行,这样会更加麻烦,不如下载 Python3 省事儿噢。

Python 运行环境下载到你自己的台式机或者笔记本后(相信大多数人不会想用手机编程吧哈哈),安装它,设置好环境变量(这个只要根据安装提示进行,不知道怎么设置就什么都不要改,用默认的路径和选项就好)。

然后在命令行下进入 PythonSourceCode 目录(这个目录是自己建立的),把 FirstProgram.py 放到目录下,然后在命令行输入python FirstProgram.py 就能看到效果了:

在我们键入“python FirstProgram.py”到屏幕上显示出“Hello World”,看起来是一瞬间的事情,但实际上,后面却经历了一个“漫长”的过程,你的计算机的各个部件几乎都参与了这个过程:

  • 首先,运行环境将程序代码读入内存,将一个完整的程序描述拆解成指令和数据两部分。
  • 然后,指令被送到CPU,CPU逐条执行指令,对数据产生影响:
  • 在这个过程中,根据程序的逻辑,输入输出设备(I/O设备)可能会接受用户的输入(本程序没有用户输入),并将输出呈现给用户(本程序的将“Hello World”打印到屏幕就是输出);
  • 直到所有指令执行完毕。
  • 最后,所有指令执行完毕后,指令和数据被移出内存。(计算机是不是真的很辛苦,一个小小的动作,背后有这么复杂的步骤)

这些设备、内存、 CPU 之间的信息交换都是通过主板上的总线来实现的。

点击了解更多《编程算法同步入门》

跑动的程序——运行时程序

在程序的运行过程中,那些动态的、临时性存在于计算机核心部件中,并通过外围设备和用户进行交互的指令和数据才是真正的程序!

程序的源代码是一些静态的文字和符号,以文本文件形式存储在计算机的存储部件上。就算是打印或者手抄在普通纸张上也可以,源代码还是源代码,本身不会变化,只是不能直接被运行环境读取运行了而已。

而确切意义上的程序,则是在计算机执行源代码(或者由源代码编译而成的二进制码)的过程中,一个动态的流程和记录。对应到物理世界,程序的实际存在形式是硅晶、金属上流动的电波和不同高低的电压。

不过在日常生活中,“程序”一词往往被用来指代程序源代码,而且指代源代码的机会远比引用它的本意要多。我们也不用故意找别扭,那就干脆约定一下,在下面的课程中我们用“程序”来指代静态的源代码,而用“运行时程序”指代动态的程序

令人激动的环节:编程

编程的步骤

我们已经知道了什么是程序,编程就是从无到有创造出一个可以正常运行的程序的过程

这个过程通常包括一下这几个步骤,一定要看仔细了噢:

Step-1 编写:把程序写出来。

既然要“编写”,自然要涉及到语言文字,否则写什么呢?

就目前而言,在大多数情况下,我们编写程序都使用高级编程语言。既然有高级,当然就有低级,之后我们会有专门将编程语言的章节,在这里就不多说浪费时间啦。总而言之呢,程序是用某种特定的语言描述出来的。

Step-2 编译(*):编译是将编程语言描述的、人类可读的程序源代码(source code, 或简称code)转化为二进制代码(binary code)的过程。

这一步并不是一定要进行,关键是在于你选用的编程语言是编译执行的还是解释执行的,如果是前者,就要进行本步,否则的话是不需要哒。

本课程选用的 Python 语言是后者,用 Python 写的代码是不需要编译的。

Step-3 测试 : 也就是试运行程序。

一方面看看我们写的程序是否可以运行了,另外一方面要看它是不是按照我们最初的设计运行的。这个环节通常令人心情紧张!

Step-4 问题修复(*): 如果上一步发现了问题,也就是程序员们常挂在嘴上的Bug,当然不能放任不管,需要将问题修复才能正式投入使用。

这一步理论上当然也是可选的,如果测试没有发现问题自然就不用修复什么了。

把程序写出来

编程对应的英文可以叫做 Programming ,不过更通常地被叫做 Coding ,这两种叫法很多时候可以通用。有时后者比较偏重强调第一步:程序的编写。

和之前“程序”的静态动态概念混用类似,虽然编程实际上指的是一个从空白到有一个程序正确运行的全过程,但很多时候“编程”会被用来简化地指 Step-1:编写程序

相比于Step2 ~ Step4有许多自动化工具辅助,编写程序这一步基本是纯人工的,这就就是为什么大多程序员自嘲为码农,就是码字的农民了。

程序编辑器

虽然编程语言里一般其中都会包含部分英语单词,但是还是有大量的内容是数字以及各种符号组成的,因此程序代码乍看起来和一般的自然语言文字很不同,更像是编码(Code)——这也就是为什么编程会被叫做Coding的原因。

虽然不同编程语言写出来的程序一般会以不同的后缀名来存储,比如C语言写的程序源码文件是*.c; C++是 *.cpp; C#是.cs; Java是.java; Python是*.py…… 不过说到底,这些其实都是文本文件。

所以理论上,要编程,打开一个 Notepad ,然后直接往里面敲字符,敲完了再存成固定后缀的文件就可以了!

如果你愿意,当然可以用 Notepad :

或者任何你自己喜欢的文本编辑器(比如在 Linux/Unix 圈很流行的 vim 或者 emacs 编辑器)。

这种方法很酷,不过不太方便。

集成开发环境

在这里给大家推荐一类超级好用的软件,新手必备,那就是:IDE(Integrated Development Environment) ——中文名叫作“集成开发环境”

这类软件大多与编程语言绑定的,也就是说某一个IDE主要支持一种语言(当然也不绝对哟)。

IDE 除了提供编辑器,还提供编译运行以及 debug 环境( debug 简单来说就是发现程序有bug以后,能快速找到bug所在位置的过程)。而且,在编写程序的过程中,一般 IDE 会提示有没有语法错误等,对于初学者来说,简直是无敌方便。

流行的语言一般有多种 IDE ,很多人在选编程语言的时候要先站一遍队 (Java vs Python),选语言版本的时候再站一遍队 (Python2 vs Python3),选 IDE 的时候又要站一遍队——也许是觉得在一个名目之下党同伐异好玩吧,但其实,这些都没什么必要~

学习本课的同学应该都是没怎么接触过编程的,想来还没有沾染动不动就“站队“的习气,对 IDE 可能也没有什么认识,不过不要紧啦

在此我就为大家推荐一款:PyCharm 。在其官网: 点击官网地址,就可以下载啦

PyCharm 有付费的专业版和免费的社区版,鉴于我们的课程内容真的非常滴简单,所以免费的就完全ok了。

点击了解更多《编程算法同步入门》

分享交流

我们为本课程付费读者创建了微信交流群,以方便更有针对性地讨论课程相关问题。入群方式请到第 2-1 课末尾添加小助手的微信号,并注明「同步入门」。

阅读文章过程中有任何疑问随时可以跟其他小伙伴讨论,或者直接向作者提问(作者看到后抽空回复)。你的分享不仅帮助他人,更会提升自己。

1-3课:算法究竟是个啥东西?

算法,究竟是什么呢?(令人抓耳挠腮,想不明白)

广义算法

广义而言,做一件事情/解决一个问题的方法,就是算法。

比如:

Case1:烙饼得把面粉加水和成团,擀成片,加油盐后卷成卷切成大面剂子,面剂子封口后擀成圆形,上锅烙,反几次直到两面焦黄,出锅乃成——这是烙饼的“算法“。是不是瞬间Get!

Case2:做条裙子要先量尺寸,再裁布,然后缝纫镶边装拉锁——这是裙子制作的“算法“。

……

所有的算法都体现为一个过程:

  • 这个过程由若干工序(或称为步骤)组成;
  • 这些步骤按照一定的流程来加工某些原料;
  • 最终产生某种结果。

当然,要说起来,万事万物都有过程——一个东西放在那里不动还会生锈老化呢,都有“结果“的产出——比如铁锈。你是不是会想,那是不是万事万物皆为算法呢?

所以不用搞得那么玄妙,算法,原本就是人类创造的概念,四季更迭、万物消长这类“上帝的算法”并不在我们的讨论范围内。

我们关心的是:那些能够为我们完成任务或者解决问题的方法。换言之,我们讨论的算法一定有明确的目标,最终的产出也是为了达到目标

那么总结一下,算法的几个重点要素就是:

1)目标2)流程3)原料4)产出

小贴士:其中的流程是由若干步骤组成的,既然要产出结果,就不能没完没了。所以,流程中的步骤必须是有限的。这一点也叫做算法的有限性

计算机领域的算法

狭义的算法

作为广义算法的一个分支,计算机算法自然也具有前面说的几个要素。

广义算法流程的有限性对与计算机算法同样适用,此外,计算机算法的任何步骤都需要:

  • 有确切的定义 —— 确定性

  • 能够被分解为计算机可执行的基本操作,并且每个操作都能可以在有限时间内完成 ——可行性

计算机算法的流程实则是一个有限的操作序列,具体操作通过计算机指令来实现。

至于原料和产出,计算机处理不了面粉布匹,它能处理的只有数据而已。因此,无论是“原料”还是“产出”,于计算机算法而言,都是数据。

所以对于计算机算法而言,我们将原料称为输入数据,简称输入(Input),产出称为输出数据,简称输出(Output)

那么把上面几点综合起来,计算机算法就是(划重点):

  • 一个有限的、通过计算机指令实现的可执行操作序列;
  • 这个序列接受输入;
  • 对输入数据进行有限步骤的处理;
  • 最终产生确定的输出,用以实现算法的目标。

这个定义这么看起来貌似有点乱。没关系,我们可以从内外两个方面来直观地了解一下算法是什么。

小贴士:从现在开始,我们所说的“算法”,如无特殊说明,指的都是计算机算法。

点击了解更多《编程算法同步入门》

从外面看,一个算法就像一个黑盒

这个黑盒能够解决某一类问题。我们把需要解决的问题作为输入扔到黑盒里面去,里面叮叮哐哐操作一番,过了一段时间之后,从里面倒出来一些输出。这些输出就是对输入对应问题的解答。

比如:

Case:这个黑盒是用来计算矩形面积的,那么我输入对应一个矩形的长和宽的两个数字,等待片刻(当然,这个片刻短到察觉不到),就得到了一个输出的数字,这就是这个矩形的面积值。

上面这个算法很简单。算法也可以很复杂,比如:

Case: 输入一个用户的个人信息(性别、年龄、所在地、职业、学历等),输出为针对这个用户定制的新闻页面或推荐商品目录或广告列表;

Case:输入用户当前位置和目的地位置,输出一条或多条到达目的地的路线规划和预计时间;

Case:输入一张人脸照片,输出这个人的身份信息;

……

复杂算法的背后可能实际是分成若干更小规模的算法协作实现的。

但无论如何,从外面看起来,总不过是输入问题->运作->输出答案而已。

从内里看,算法 = 数据结构 + 控制流程

数据结构 & 控制流程——又来了两个新名词啊。后面也会有专门的章节分别讲解它们,现在我们只是简单的形象化描述一下而已。

【1】数据结构

我们的算法既然是用来解决一类问题的,那么想必不能够只处理一份数据。

比如:

计算矩形面积的算法,肯定是可以计算长、宽为任意值的矩形的面积的。

不能只会计算长为10宽是5的矩形面积,当改成长为37宽为82的时候,它就不会算了。

同样一个算法,要能处理许多“份”数据,那么在算法内部描述对数据的处理时,就不能用确定的数值,而需要用一系列名称来指代各数据——这些用来指代的名称,这个我们叫做变量

例如:

在计算矩形面积的算法里,我们用变量 length 表示长,用另一个变量 width 表示宽。

那么算法内部,我们只需要计算这两个变量的乘积就可以了——计算的时候,我们不是写 5 x 10,或者 37 x 82,而是写成 length x width。

一个变量一次只能代表一个数吗?

假设:

我们有个算法,计算一个人在一段时间内花费钱财的总和的。

现在我要计算某一户人家在2018年12月的花费。

一看:这些天里爸爸总共花了76笔钱;妈妈花了569笔;儿子花了13笔。

对应到算法里面,我们怎么来利用变量呢?

用一个变量来指代具体的一笔钱吗?那处理妈妈花费的时候,我们要用569个变量吗?

真要这样的话,要统计妈妈一年的花费怎么办?如果妈妈一年花了73982笔钱,我们也用73982个变量?那计算她十年,二十年,五十年的花费怎么办?

所以这个时候,如果我们能有一种方法来指代“一串”数就好了。这个串可长可短,不管它多长,算法只要把里面的数一个挨着一个的加在一起就行了。

我们用一个变量来指代这个数字“串”,那么花费计算算法里只用一个变量就可以了!

这个时候,我们实际上就规定了一种数据的组织方式——许多具体的数值按照一定的相对位置和相互关系组合起来。比如,在这个花费“串”里,每一笔花费按照时间顺序一个接一个排成一队。

数据的组织方式,就叫做数据结构

数据结构有很多种,有简单有复杂。上面例子里的结构非常简单,一个个数字排成序列就好了。

上面算法根据这个序列,不仅能算这些花费的总额,还能算平均花销,还可以把单次最高消费找出来。

可是,如果我们要完成的任务变成:

找到单次最高消费是在哪天花的。

就没办法了,因为现有的数据里没有时间信息。

为找到消费对应的时间,可以把每笔钱花出去的日期也“告诉”算法,但是如何告知呢?可以有多种方案,比如:

  • 方案-1:用两个序列;第一个是数字序列,每一个数字代表一笔花销,第二个是时间序列,每一个时间表示花费一笔钱的时间点;这两个序列中的元素按照在序列中的位置一 一对应。

  • 方案-2:只采用一个序列,不过这个序列中每个元素包含两个部分:时间和金额。

上述两个方案所对应的数据结构就是不同的。

如果我们还想看到:

每笔钱花在了什么地方?给了哪个商家?购买了什么产品或者服务?

那就需要把更多的信息“告诉”算法,采用的数据结构也就会更加复杂。

【2】控制流程

回到前面的花销计算算法:计算“一个人在一段时间内花费钱财的总和”,选定用一个数字序列作为数据结构。

这个算法:

  • 接受一个数字序列作为输入;
  • 把这个序列里面的数字一个个“拿出来”;
  • 将拿出来的数值累加在一起;
  • 将最终的累加和结果输出出来。

整个过程有始有终,运行的顺序清晰明确,这就是控制流程。

控制流程的定义很简单:程序运行的步骤历程,就是控制流程。

对应不同的数据结构,当然有不同的处理方法。

算法的控制流程往往和数据结构有关系。换言之,同样目标的算法,因为所采用的数据结构不同,很可能会造成运行、求值的步骤顺序的不同。

点击了解更多《编程算法同步入门》

分享交流

我们为本课程付费读者创建了微信交流群,以方便更有针对性地讨论课程相关问题。入群方式请到第 2-1 课末尾添加小助手的微信号,并注明「同步入门」。

阅读文章过程中有任何疑问随时可以跟其他小伙伴讨论,或者直接向作者提问(作者看到后抽空回复)。你的分享不仅帮助他人,更会提升自己。

1-4课:程序、编程和算法之间到底有什么三角关系?

算法与程序

在之前我们给大家科普过了,算法 = 控制流程 + 数据结构

数据结构是数据的组织形式。在描述算法的时候,我们并不知道实际要用这个算法来处理的数据是什么(其实也本没有必要知道),我们只需要知道将来要处理的数据是如何组织的就可以了。

基于数据的组织形式,定义一个运算/操作的历程,这就是算法的实现。算法实现的结果,就是程序。

当我们有了具体的数据要处理的时候,就要:

1)运行已经编写好的,实现了算法的程序(静态);2)将具体数据按照既定的数据结构组织好,作为输入传输给运行时程序(动态)。

运行时程序会按照既定的步骤处理接收到的输入数据,产生运算结果,并输出。

如此说来,也可说算法是静态程序的内容,而算法 + 数据 = 动态程序

算法与编程

算法和编程,又是怎样的关系呢?其实,很简单一句话就能给大家说明白那就是所谓编程,就是实现算法的过程!!!

对编程的误解

很多同学在开始有意向学习编程的时候,很粗糙的认为学习编程就是学编程语言,以为学会了编程语言的句法、语法就会编程了。

NO!这样想就错了,这里有一个很重大的误解,就是简单地把编程语言等同于自然语言了。

大家都有学习外语的经历吧,回头想想,中小学学英语的时候,我们要做的事情不过就是:认字母,背单词,记语法——什么时态、语态、主格、宾格、定语从句、状语从句等等。

每每被动词变形、虚拟语气,和英语阅读时半篇儿不认识的单词搞得七荤八素的时候,就觉得:记住了足够多的单词和语法,自然就会用英语听说读写了。

至于听说读写的内容,我们并不用操心,反正我们每天中文也要说话、阅读、写作,学会了英语,不过就是用哇哩哇啦的发音和曲里拐弯的字母来代替声韵母、方块字做同样的事情罢了。

中文英文(或者任何一种自然语言)最基础的部分都是用来应对日常生活的。我们每个人都对自己的日常生活十分熟悉,对于需要输入(听、读)输出(说、写)的内容早已掌握。而自然语言的形式又特别复杂,所以在学习外语的初中级阶段,大都会将绝大部分精力放在词汇语法上。

但是编程语言这种东西,它的作用不是用来日常聊天或者生活用语的。

虽然不管那种语言第一个程序都是 “Hello World” ,但那是运行环境因为自己能够正常实现功能而对世界发出的欢呼,并不是人与人之间打招呼。

那么多编程语言,无论学其中哪一种,我们都不是为了去问邻居“吃了吗”,跟超市导购讨价还价,或者撩哪个心仪的妹子/汉子……

点击了解更多《编程算法同步入门》

学习编程的目的

那我们学编程是用来干什么的呢?

从微观角度说,计算机能够处理的“物料”是数据,所有计算机能做的事情,都要通过数据的变化来体现。因此,如果我们编写程序的目的不是为了让数据发生变化那就毫无意义。

让数据发生变化就需要运算,而运算的过程就是算法。

从宏观角度说,算法是对解决某类问题/完成某类任务的方法的描述。人类发明计算机是用来解决问题的,如果写出来的程序不能解决问题,这个程序就不应该存在。

因此,任何有存在价值程序,必然都实现了算法。我们学编程就是为了实现算法的。

算法是编程的核心!

经典算法

说到这里,有些人可能要抬杠了:

人类要解决的问题无穷无尽,我堆砌一些符合编程语言词法句法的代码,让它们能在运行时跑起来。然后就说这个程序解决的就是让我能写出一个程序的问题,它不也是个算法吗?

人生苦短,文字游戏在这里玩不通,也没必要去制造悖论~

固然人类要解决的问题千奇百怪,有些问题事到临头也许确实要做点明知徒劳也不得不为之的处理。但毕竟我们现在是在学习阶段嘛,学习阶段就应该珍惜时光,尽量在最短的时间内学会能处理计算机世界中最常遇到的问题的算法

计算机从被发明出来到现在半个多世纪的时间里,虽然它能够提供的服务日益翻新,但其实有一些逻辑层面的基础问题,在大多数应用领域都会用到。许多应用层繁多的花样,最终对应的都是共同的基础问题

计算机领域的科研人员、开发者,在几十年的工作中,针对一些历史悠久,应用广泛,经常高频出现的问题,研发出了对应的精致、高效的算法。这些算法我们称为经典算法

本门课程要学习的就是这些算法中的一部分。

经典算法著作

计算机专业讲述算法的经典书籍主推下面这两部:

1. 《编程的艺术》

《编程的艺术》,书名英文 The Art of Computer Programming,简称为TAOCP。

作者Donald Knuth,中译高德纳,是1974年图灵奖得主。目前隐居深山,专注写作本书。

本书预计出版七卷,到目前为止只出版了前三卷(各一册),和第四卷的 A 分卷(第四卷计划分为ABCD四个分卷),A分卷又包括0-4五个分册。

第一卷首次出版于1968年,第四A卷的五个分册已经在2005- 2011陆续出版。目前只有第一卷有中译本。

这是一本算法的集大成之作,虽然还未完成,但已经被列为20世纪最佳12部学术专著之一, 与“量子力学”、 “相对论”、 “博弈论”等重要著作并列经典。

如果立志研究计算机算法,这部著作是经典中的经典无疑。即使是职业程序员,能够通读第一卷也是凤毛麟角,真能把第一卷读下来,都学会,在工业界差不多就可以算是算法大拿了。

这部书对于初学者并不合适,不过既然要学习计算算法,总要知道它。

关于本书还有个有意思的事情:

高德纳宣布任何发现书上的错误并写信告知他的人,都能得到256美分——刚好是十六进制的一美元 (one hexadecimal dollar)。

高德纳确实履行了他的诺言,每位发现错误并指出的读者,都能得到一张2.56美元(或其倍数,如果能同时发现不止一个错误的话),有高德纳签名的支票。

在现今已经50岁往上的那代程序员里,高德纳的支票是一种很酷的收藏品,也是自身能力的背书。作者的一位前老板就有这样一张支票,他把它放在一个镜框里,摆在自己办公桌上。

2.《算法导论》

《算法导论》,英文名 Introduction to Algorithms,首次出版于1990年,此后又出版了第二版(2001)和第三版(2009)。

三版都有中译本:

原本预计2014年要出第四版,不过被推迟到了2019年。

本书在首版发行后的二十多年中 ,迅速成为了美国许多大学算法课的课本,并在学术论文中被引用了超过万次!

第一版的作者是三个人: Cormen , Leiserson , Rivest ,再版时又加上了第四位作者Stein,他们的姓氏首字母缩写CLRCLRS已经成了一个业界术语,专门用来指代本书的作者。

《算法导论》不仅讲解了经典算法,算法的数学性质,还介绍了这些算法的设计技术和应用领域。具体的算法过程用伪代码书写,避免了和某一种编程语言的绑定。

无论是用做学习算法的教材,还是在实际工作中应用算法的参考,都是极好的。

不过原版1300多页,中译本780页——这样的砖头读一遍还是蛮辛苦的。另外,正是因为没有和具体的编程语言绑定,如果要实现其中算法,则需要能够自己编写实际的代码,也就是要预先具备编码能力再读本书为好。

对于编程和算法都是零基础的入门者,本书还是有些艰深。

小贴士:虽然本书各章自成体系,可以作为独立的学习单元,但如果一个人能够直接选出基础重点章节进行自学,那就不是零基础了,是吧~

点击了解更多《编程算法同步入门》

分享交流

我们为本课程付费读者创建了微信交流群,以方便更有针对性地讨论课程相关问题。入群方式请到第 2-1 课末尾添加小助手的微信号,并注明「同步入门」。

阅读文章过程中有任何疑问随时可以跟其他小伙伴讨论,或者直接向作者提问(作者看到后抽空回复)。你的分享不仅帮助他人,更会提升自己。

1-5课:妈妈告诉我学编程到底有啥用啊?

学习算法和编程的用处

学习算法和编程,到底有什么用?就目前而言,大致有如下几种用处:

【1】是入行程序员的基本技能

这一点不用说了,程序员的日常工作就是编程,程序员面试考的就是算法。要想成为程序员,编程+算法是最最基础要学习的东西。

【2】了解计算机技术和程序员思维的捷径

在互联网公司,有些岗位,虽然自己不需要编程,却总是难免要和程序员打交道,最典型的例如:产品经理。

这样的角色,如果对计算机技术和程序员的思维方式缺乏最根本的了解,日常工作也就无法进行了。学习基础编程和算法则是对这两者有所了解的最快途径。

【3】非技术岗位员工可以用来解决日常问题

不过随着计算机硬件的普及,编程语言和软件工程的不断发展,各类教育资源的普及化和多样化(例如知识付费的出现),编程这件事情已经变得越来越触手可及了。

大多数人都能通过写代码解决部分工作生活中遇到的问题的情形,已然成为可能。

特别是Python这种拥有大量支持库的语言,各种各样的功能都已经被封装成库函数,只要具备最基本的编码能力,会调库函数,写爬虫、处理数据、做数据分析都很方便。而这些,已经成为越来越多注入市场、运营类职位的必须。

另:随着人工智能技术的发展,大量通用模型被封装成基础服务,可以用过调用远程接口使用。会写代码,了解最基础的原理,就可以拥抱人工智能,开发AI产品了!听起来是不是双眼一亮觉得很赞!

【4】锻炼思维能力,提升逻辑能力

就算不打算写代码,学习算法也是一种对思维能力的绝佳训练。

算法的两大要素:

  • 控制流程描绘事物发生发展的过程;
  • 数据结构对事物组织的形式高度抽象。

这都是逻辑思维的最基础。算法的学习过程相当于一种思维体操,可以有效锻炼我们“思维的肌肉”。让你的大脑灵活的运转过来。

【5】与K12教育接轨

2017年,国务院发布《新一代人工智能发展规划》,明确指出在中小学阶段设置人工智能相关课程,逐步推广编程教育。

浙江省已经在尝试将编程纳入高考体系。虽然离全面覆盖为时尚早,但编程、算法正在逐步渗入K12教育已经明确为大势所趋。

一则,咱们大学都毕业了,总不能连中小学生会的都不会吧。再则,大家就算不是为了自己,为将来的儿女着想,也该自学点编程。要不然到时候,怎么跟自己的儿女有共同话题呢!

点击了解更多《编程算法同步入门》

掌握算法的五个层次

不同的人对某一事物了解、掌握的程度是不同的,同一个人在不同时期对同一事物的了解和掌握也很可能是不同的。

对于算法的掌握,大致可以分为5个层次(见下图):

这五个层次所对应的程度如下(其中涉及到一些专业名词和术语,这些在今后的章节里都会讲解,此处先知道一下):

Level-1 听说

  • 知道算法名
  • 知道算法功能

Level-2 了解

  • 知道算法原理(自然语言描述)
  • 知道算法优缺点

Level-3 理解

  • 知道算法的过程和细节
  • 能够描述算法的控制流程和数据结构
  • 知道算法的时空复杂度

Level-4 实现

  • 能够用编程语言编写出无逻辑错误的算法

Level-5 应用

  • 能够应用算法解决实际问题

这五个层次,自上而下,由浅入深。

对应不同层次的讲解方法

现在讲解算法的书籍层出不穷,大家到任何一家网上书店或者卖书的电商网站,输入“算法”两个字,都能搜出几十页的书籍列表。但是不同的书,讲解的深度是不同的。

我们前面介绍过的《编程的艺术》和《算法导论》从内容上详细剖析了算法细节及其背后的数学属性,如果真的能够学通学透,应该可以达到Level-4的水平。

Level-4也是纸上谈兵的最高境界——真的到现实中去运用,将理论知识转化为实践经验,就不是仅仅依靠书本可以做到的了。必须要实践!

现在有不少看起来很Cute的算法书,里面有很多插图、漫画,多了许多亲和力,比如这本现在就很火:

其中介绍了26个算法,绝大部分描述是用图来表示的,确实简洁易懂。

不过,正因为全部都是直观描述,实际上,只是介绍了算法原理,并没有严格的流程和细节。对应Level-1和Level-2的程度,另有部分Level-3层面的介绍(例如时间复杂度),但作为编程的依据恐怕就不够了。

当然,这本《我的第一本算法书》应该说是算法书中的特例,其他很多虽然图画很萌很Q的书,也是描述了算法细节的。

不同算法书,各有侧重。还有些书籍名称虽然不含有“算法”两个字,但其实主要内容讲得也是算法。比如这本:

这本书是作者上学时专业课的课本,那门专业课的名称就叫做“数据结构”,不过大部分内容讲的是经典算法。

算法驱动编程

市面上的书都已经那么多了,那么本课程又有什么不同之处呢?

第一,本课所讲授的算法数量,比任何一本书里介绍的算法数量都要少!仅限最最基础的部分:顺序查找、二分查找、选择排序、冒泡排序、插入排序和快速排序。

第二,本课所讲授的每一个算法都已经到达细节阶段,真的学会的话一定可以编写出正确的实现算法的程序,是不是期待的搓搓手(Level-4)。

第三,本课预先不要求任何编程基础,我们是编程和算法一起学的。我们是以算法来驱动编程的!

算法少而程度深,是希望大家立足于最最最基础,打捞基础,才有往后走的可能性“不怕千招会,就怕一招熟” —— 吃透6个算法,达到别人一提名字就完全凭空写出代码的程度;相较于能将几十个算法作为谈资,但却一个都写不出来,无论是对于职业发展还是脑力锻炼,显然都是前者对大家更有帮助。

以算法驱动编程,就是说我们会沿着Level-1到Level-4的顺序,在介绍一个算法的时候,先讲一下它是做什么用的,有什么优缺点,原理是什么(怎么能够达到目标功效的),然后再通过画流程图、写程序代码的方式展现算法的全部细节。

在学习算法细节的过程中,自然而然地接触编程语言和程序编写,和算法同步学习编程语言语法、词法等。

算法的难点:从原理到实现

如果以后反正不想编程,就算要学算法,是不是只要会用自然语言描述就可以了?不用写成代码了吧?

的确,算法本身是一个方法,它可以用自然语言直观地描述(Level-2),也可以用编程语言来形式化地表达(Level-4)。然而,即使所指向的标的相同,不同的表达方式所揭露的深度和难度却大有不同。

因此,我认为:就算是仅仅为了把算法学清楚,也有必要写代码

本课只介绍六个算法,整体都比较简单。特别是第一个顺序查找,如果单看原理,简直简单得不像话!大家可能会觉得:这也配叫算法?即使到了本课最后一个算法快速排序,仅仅论及原理,一句话就能讲完。

不要说本课讲的这些,就是很多非常复杂高效的算法,只是简单概括原理,也不过就是一句话——自然语言的概括性也正体现于此。

可是就是看起来这么简单,其运作原理可以用自然语言一言以蔽之的算法,等到真的用编程语言写出来,我怕大家会觉得不认识了——这几行字符是什么意思?这是快速排序吗?它们在干什么呀?

算法的难点恰恰在于:如何从概括性的原理,转换为与具体数据结构结合可以一步步实施并直接对应为计算机指令的控制流程。

这一难点,正是本课的核心所在!

对每个算法,我们不仅(1)要讲抽象原理,还要(2)将其拆解成数据结构+控制流程(3)详细推演整个运行过程的细节,(4)将整个流程写成代码,然后(5)在运行环境中执行

为了能够完成对所学算法的形式化表达,我们会:

  • 先学习纯粹理论层面的控制流程和数据结构知识,不涉及编程。

  • 之后简单了解一下编程语言,和Python编程的一点点内容。

  • 然后再按照我们规划的六个算法,一边学算法一边学编程。

让我们一起加油吧~学会这些,你就不是小白啦,只有打牢基础,才能向大牛进发!

点击了解更多《编程算法同步入门》

分享交流

我们为本课程付费读者创建了微信交流群,以方便更有针对性地讨论课程相关问题。入群方式请到第 2-1 课末尾添加小助手的微信号,并注明「同步入门」。

阅读文章过程中有任何疑问随时可以跟其他小伙伴讨论,或者直接向作者提问(作者看到后抽空回复)。你的分享不仅帮助他人,更会提升自己。

2-1课:万事的抽象:控制流程
2-2课:用最最简单的结构表达复杂的过程:控制结构的排列和嵌套
2-3课:万物的抽象:数据结构
2-4课:从最最最最简单的数据结构开始:数组和链表
2-5课:计算机是咋运行的:冯诺依曼结构
2-6课:预留给货物的固定货架:内存中的数组
2-7课:见缝插针地摆放货物:内存中的链表
2-8课:复杂些的数据结构:树和图
2-9课:树和图的现实意义、区别与联系
3-1课:从最简单的算法开始学:顺序查找
3-2课:为啥有的算法好?有的算法坏?
3-3课:跟你的计算机聊会儿天:编程语言
3-4课:各种花式编程语言大放送
3-5课:一条可爱的小蟒蛇:Python语言
3-6课:让 Python小蟒蛇动起来
3-7课:彰显地位的缩进和作为限制的类型
3-8课:数字为什么长这样儿:说说进位制
3-9课:货物不能乱堆放:数据的占位和溢出
3-10课:迈出看似简单的一步:字面量、常量、变量和赋值
3-11课:Python中的类型系统和“数组”
3-12课:从流程图到程序:用Python编写顺序查找算法
4-1课:即使罹患阿尔茨海默病,程序员也不该忘记的算法:二分查找
4-2课:二分查找:从原理到流程图
4-3课:用Python小蟒蛇编写一个小游戏
4-4课:为什么每个程序员都要拜四阿哥?要解决bug(八阿哥)
4-5课:和bug的斗智斗勇
4-6课:听起来很高深的“软件工程”是做什么?
4-7课:计算机程序里的函数
4-8课:二分查找的变形记
4-9课:以二分查找为例,讲述掌握一个算法的过程
5-1课:人生处处排行榜:认识排序算法
5-2课:超级简单的排序方法:选择排序
5-3课:函数的参数和变量
5-4课:纸牌屋里喝可乐:起泡排序和插入排序
5-5课:与二分查找共组双子星座:快速排序
5-6课:像“贪吃蛇”一样“吃掉”自己——递归,再说说分治和动态规划策略
5-7课:递归函数,以及递归的快速排序算法
5-8课:非递归的快速排序算法和优化的分区函数
6-1课:教你一招学会算法
6-2课:碰到读不懂的代码应该怎么办?
6-3课:碰到读不懂的代码应该怎么办?示例:用编程解决实际问题

阅读全文: http://gitbook/gitchat/column/5ce3a4a43481b33762ae038f

更多推荐

编程算法同步入门