文章目录
- 算法基础
- 算法及其特性
- 算法的概念
- 算法与程序
- 算法表示
- 算法的描述
- 自然语言
- 流程图
- 盒图(N-S图)
- 伪代码
- 程序设计语言
- 算法评价
- 算法的衡量标准
- 算法的规模
- 时间复杂度
- 空间复杂度
- 数据结构
- 数据结构的概念
- 数据的逻辑结构
- 数据的存储结构
- 数据的基本操作
- 常用数据结构
- 线性表
- 栈
- 队列
- 树和二叉树
- 图
- 算法分析
- 常用算法
- 递归算法
- 贪心算法
- 分治算法
- 回溯算法
- 分支限界算法
- 动态规划算法
- 经典计算机算法问题
- 哥尼斯堡七桥问题
- 汉诺塔问题
- 哲学家进餐问题
- 旅行商问题
- 补充题
算法基础
算法及其特性
- 算法是为使用计算机解决问题而制定的运算序列,是解决实际问题的方法及步骤;在计算机科学中,算法研究应用计算机程序处理问题的方法及其实现流程,是计算机问题解决方案的完整描述,它是计算机科学的核心研究对象之一。
算法的概念
- 一般认为,算法(algorithm)是一系列有限的解决问题的步骤的集合;算法是指能够对一定的规范的输入,在有限时间内获得所要求的输出。
- 算法的5个基本特征
(1)有穷性(finiteness),指算法的步骤是有限的;
(2)确定性(definiteness),指算法的每一个步骤都是准确定义的、严密的、清晰的,不可以含糊不清、模棱两可,有明确的输入、输出及处理过程;
(3)输入(input),指算法开始运算时给定的初始数据;
(4)输出(output),指与输入相关的运算结果,反映了对输入数据加工后的情况;
(5)可行性(effectiveness),指算法的每一个步骤都是可以通过计算机程序实现的。
算法与程序
- 算法解决的是一类问题的通用方法与步骤,是解题方案的完整描述;
- 程序是为解决某个具体问题而设计的计算机指令序列。
- 将算法应用某种程序设计语言描述并使用计算机解决某个具体问题,就是程序,算法是程序的(方法、流程)基础,程序是算法针对具体问题的(代码)实现。
算法表示
- 算法描述
算法描述部分共分为算法名、算法输入、算法输出、算法流程等内容。 - 算法评价
算法评价主要从算法的正确性、可读性、健壮性(鲁棒性、稳定性),以及算法的时间复杂度(执行算法所需要的计算工作量)和空间复杂度(算法需要消耗的内存空间)等方面考虑。
算法的描述
自然语言
S1:输入N的值
S2:I=2
S3:N被I除,得余数R
S4:如果R=0,表示N能被I整除,则打印N“非素数”,算法结束
S5:I+1→I
S6:如果I≤N-1,返回S3;否则打印N“素数”;算法结束
实际上.N不必被2到N-1的整数除,只需被2到N/2间整数除即可,甚至只需被2到sqrt(N)之间的整数除即可。所以算法可作如下改进:
S6:如果I≤sqrt(N),返回S3;否则打印N“素数”;算法结束。
流程图
盒图(N-S图)
美国学者I.Nassi、B.Shneiderman提出的一种新的流程图,盒图完全去掉了带箭头的流程线,全部算法写在一个矩形框内
伪代码
- (介于自然语言与正规程序设计语言之间的类似程序代码的代码,稍加改造即可转换为规范的计算机程序)
程序设计语言
- 用计算机程序设计语言描述算法就是实际的程序,必须严格遵守所使用的语言的语法规则。
算法评价
算法的衡量标准
- 算法的衡量标准是正确性、可读性、健壮性,以及算法的时间效率和空间效率等。
算法的规模
- 算法分析首先需要确定算法的规模。
- 例如: 列出所有比n小的素数,这里
n
就是算法规模(一般涉及主要变量的大小)。
时间复杂度
详见博客深入理解时间复杂度:算法性能的关键指标
- 一般情况下,算法的时间复杂度指的是基本操作重复执行的次数与问题规模n的某个函数
f(n)
,表示为:
T(n)= O(f(n))
- 注:
T(n)
以f(n)
为上界,即T(n)< = f(n)
,当f(n)
为上确界(最小上界)时,算法最佳
空间复杂度
空间复杂度是指算法执行过程对计算机存储空间的要求。
算法的空间复杂度S(n)= O(f(n))
也是一个与算法规模有关的函数。
数据结构
数据结构的概念
- 数据结构(data structure)是计算机存储、组织数据的方式,是相互之间存在着一种或多种特定关系的数据元素的集合,数据元素相互之间的关系称为结构。
- 数据结构包括:数据的逻辑结构、存储结构(物理结构)、数据的基本操作
- 数据结构有两个要素:一个是数据元素的集合,另一个是关系的集合。在形式上,数据结构通常可以采用一个二元组来表示:
Data Structure = (D, S)
其中,D是数据元素的有限集合,S是该集合中所有元素之间的关系的有限集合。
数据的逻辑结构
- 数据元素间逻辑关系的描述称为数据的逻辑结构。根据数据元素之间关系的不同特性,通常有下列4类基本结构
- 集合结构中的数据元素“同属一个集合”,无直接关系;
- 线性结构中的数据元素存在一对一的关系;
- 树形结构中的数据元素存在一对多的关系;
- 图形结构中的数据元素存在多对多的关系。
数据的存储结构
- 数据结构在计算机中的表示(映像)称为数据的物理结构,又称为存储结构。 它包括数据元素的表示和数据元素之间关系的表示两方面。
- 顺序映像—顺序存储结构:逻辑关系相邻的元素使用相邻的存储单元(物理节点)按顺序存储
- 非顺序映像—链式存储结构:借助于元素存储位置的指针(Pointer)表示元素的逻辑关系,关系与位置无直接关联(存储单元不一定连续,也没有明确的顺序)
数据的基本操作
- 数据的基本操作包括对数据元素的修改、增加、删除、移动等。
- 包含操作的数据结构可采用一个三元组来表示:
Data Structure = (D, S, P)
其中:P—Processing表示某种操作
常用数据结构
线性表
- 线性表(linear list)是最简单的一种数据结构。
- 一个线性表是n个具有相同特性的数据元素的有限序列。
- 线性表的数学表示:有限有序的元素集合,L=(a1,a2,…,ai-1,ai,ai+1,…,an)
- 线性表中的元素个数n称为线性表的长度,n=0时称为空表。
- 线性表可以进行初始化、查找、插入、删除、更新和遍历等多种操作。
- 线性表的存储有顺序存储和链式存储两种结构,称为顺序表和链表。
- 顺序表: 用一组地址连续的存储单元依次存放数据元素,以元素在计算机内“物理位置相邻”表示表中数据元素间的逻辑关系。
存储单元------存储地址------数据元素(三者直接顺序一一对应) - 链表: 不一定连续的存储单元存放线性表,每一个物理节点存储两部分信息:当前数据元素+后继元素的指针
栈
-
栈(stack)是一种受限的线性表,即在栈中规定只能够在表的一端(表尾)进行插入或删除操作。 允许进行插入或删除的这一端称为栈顶(top);另一端则称为栈底(bottom)。不含元素的栈称为空栈。
-
假设栈S=(a1,a2,…,an),则a1为栈底元素,an为栈顶元素。向栈中插入新的元素称为入栈或进栈(push);从栈中删除一个元素时,只能删除当前的栈顶元素,称为出栈或退栈(pop)。
-
进出栈规则:
Last In First Out----LIFO,后进先出
栈的实例:弹夹—先压入弹夹的子弹在弹夹(相对)下面的位置,射击时后发射
队列
- 队列也是一种受限的线性表,和栈相反,队列(queue)是一种
先进先出(First In First Out,FIFO)
的线性表,它只允许在表的一端插入(队尾,rear),而在另一端删除元素(队首,front)。当队列中没有包含数据元素时,称为空队。 - 假设队列为Q=(a1,a2,…,an),那么a1就是队头元素,an则是队尾元素。
树和二叉树
- 树(tree) 是一类重要的非线性数据结构,大多用于描述一对多的关系,树结构的数据元素(结点)之间有分支(节点+分支),并且具有层次关系。
- 树的实例:
- 家族族谱------成员及其血缘关系;
- 中国教育网------各大学子网------子网用户;
一般用空心圆表示节点,用直线段表示分支,树根(唯一)节点在上,树倒置,(a)是有13个结点的树,A是根(root),一棵树有且仅有一个根。
- 二叉树(binary tree) 是最重要的一种树形结构,它的特点是每个结点至多只有两棵子树(即二叉树中不存在度大于2的结点),并且,二叉树的子树有左右之分,其次序不能任意颠倒,如图(b)所示。
- 树的存储方式:双亲表示法、孩子表示法、双亲孩子表示法;
- 树的主要操作:遍历
图
- 图是一种复杂的非线性结构,表示数据元素之间“多对多” 的联系。
- 图(graph) 由顶点和顶点之间边的集合组成,记作G= (V, E)。
- 图中的结点(数据元素)称为顶点(vertex),V是顶点的有穷非空集合;边(edge)是顶点的有序偶对,若两个顶点之间存在一条边,就表示这两个顶点具有相邻关系。E是边的有穷集合。
- 顶点的度: 顶点关联的边的条数,分出度(顶点为起点的边的条数)、入度(顶点为终点边的条数)两种
- 边的权: 长度、距离等可量化的参数
- 图按照边有无方向分为无向图和有向图。
- 图结构可以描述各种复杂的数据结构,如通信线路、交通航线、工序进度计划等。
- 图的存储方法:邻接矩阵、邻接表、十字链表
算法分析
常用算法
递归算法
- 递归算法的主要思想是将一个初始问题重复分解成为比较小的、有着相同形式的子问题,直到子问题足够简单,能够被理解并解决为止,然后将所有子问题的解组合起来得到初始问题的结果。
- 例如,为了计算阶乘,可以使用下面的定义:
贪心算法
- 贪心算法背后隐藏的基本思想是从小的方案推广到大方案的解决方法。它分阶段工作,在每一个阶段总是选择认为当前最好的方案,而不考虑将来的后果。
- 典型的贪心算法的例子是找零钱问题。背包问题、马踏棋盘问题都是典型的贪心算法求解应用问题。
分治算法
- 分治法的思想就是,将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。
回溯算法
- 回溯算法是一种满足某些约束条件的穷举搜索法。
- 回溯算法最典型的例子是n皇后问题。迷宫问题、旅行售货员问题、装载问题等都可以应用回溯算法求解。
分支限界算法
- 回溯算法的求解目标是找出T中满足约束条件的所有解,而分支限界算法的求解目标是找出满足约束条件的一个解,或是在满足约束条件的解中找出使用某一目标函数值达到极大或极小的解,即在某种意义下的最优解。
动态规划算法
- 适合用动态规划求解的问题,经分解得到子问题往往不是互相独立的。 若用分治算法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。如果我们能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。我们可以用一个表来记录所有已解的子问题的答案。不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。这就是动态规划算法的基本思路。
- 工程耗费问题、求最短路径算法等都是动态规划算法的典型应用。
经典计算机算法问题
哥尼斯堡七桥问题
- 17世纪的东普鲁士有一座哥尼斯堡城,城中有一座奈佛夫岛,普雷格尔河的两条支流环绕其旁边,并将整个城市分成北区、东区、南区和岛区4个区域,全城共有7座桥将4个城区相连起来
- 通过这7座桥到各城区游玩,提出的问题是:寻找走遍这7座桥的路径,要求过每座桥只许走一次,最后又回到原出发点。
问题提出后,很多人对此很感兴趣,纷纷进行试验,但在相当长的时间里,始终未能解决。而利用普通数学知识,每座桥均走一次,那么这七座桥所有的走法一共有7!=5040种,如果要一一试验,这将会是很大的工作量。但怎么才能找到成功走过每座桥而不重复的路线呢?因而形成了著名的“哥尼斯堡七桥问题”。
- 七桥问题引起了著名数学家列昂纳德•欧拉(Leonhard Euler)的关注。1736年,在经过一年的研究之后,欧拉提交了《哥尼斯堡七桥》的论文,圆满解决了这一问题,同时开创了数学新分支——图论。
欧拉解决问题的方法为抽象的方法。根据“寻找走遍这7座桥,且只许走过每座桥一次,最后又回到原出发点的路径”的问题,抽象出问题本质的东西,忽视问题非本质的东西。
汉诺塔问题
- 汉诺塔问题是源于印度一个古老传说。上帝创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按大小顺序摞着64片黄金圆盘。上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
- 汉诺塔是一个只能采用递归方法进行计算的问题,时间复杂度为指数级。递归在可计算性理论与算法设计中都有很重要的地位。
哲学家进餐问题
- 哲学家进餐问题涉及到五个哲学家,共用一张放有五把椅子的餐桌,每人坐在一把椅子上,桌子上有五个碗面和五根筷子,每人两边各放一根筷子。哲学家们是交替思考和进餐,饥饿时便试图取其左右最靠近他的筷子
- 当哲学家思考时,他不和其他人交谈。当哲学家饥饿时,他将拿起和他相邻的两根筷子进行进餐,但他很可能仅拿到一根,此时旁边的另一根正在他邻居的手中。只有他同时拿到两根筷子时他才能开始进餐。完成进餐后,他将两根筷子分别放回原位,然后再次开始思考。由此,一个哲学家的生活进程可表示为:
S1:思考问题;
S2:饿了停止思考,左手拿一只筷子(拿不到就等);
S3:右手拿一只筷子(拿不到就等);
S4:进餐;
S5:放右手筷子;
S6:放左手筷子;
S7:重新回到思考问题状态S1。
如何协调5个哲学家的生活进程,使每一个哲学家最终都可以进餐。 - 哲学家进餐问题实际上反映了计算机程序设计中多进程共享单个处理机资源时的并发控制问题。 要防止这种情况发生,就必须建立一种机制,既要让每一个哲学家都能吃到面条,又不能让任何一个哲学家始终拿着一根筷子不放。
旅行商问题
- 旅行商问题(Traveling Saleman Problem,TSP)又译为旅行推销员问题、货郎担问题,简称为TSP问题,是最基本的路线问题,该问题是在寻求单一旅行者由起点出发,通过所有给定的需求点之后,最后再回到原点的最小路径成本。
补充题
著名的计算机科学家尼·沃思提出了( ) 。
- 数据结构+算法=程序
数据的存储结构包括顺序、( )、索引和散列四种基本类型。
- 链式
数据的存储结构可以分为顺序存储和链式存储两种。
- 是
二叉树中不存在度大于2的结点。当某个结点只有一棵子树时,无所谓左、右子树。
- 答案: F
-
顺序表相对于链表的优点有(随机访问)和(空间利用率高)。
-
在求表达式值的算符优先算法中使用的主要数据结构是(栈)。
-
二分搜索法是(分治)算法的应用。
-
- 回溯法是一种满足某些(约束条件)的穷举搜索法。
-
数据的存储结构包括顺序、、索引和散列四种基本类型。
- D. 逻辑和存储结构
-
对于线性表,以下情况应采用链表表示。
- C. 需要经常插入和删除元素