1、数据结构实用教程,学习方式, 听课 (启发式、讨论式) 读书 (预习、复习) 报告 (综合练习),考试成绩,平时成绩 (书面作业、上机练习、综合练习)上机考试期末笔试,内容安排,第一章 绪论第二章 线性表第三章 栈与队列第四章 串第五章 数组与广义表第六章 树,内容安排,第七章 图第八章 查找第九章 内部排序第十章 综合实训,数据结构第一章 绪论,基本概念和相关术语,数据 所有能输入到计算机之中,并能被计算机程序所处理的符号的总称。如数字,字母,标点符号、图形图像 、声音等。数据元素 描述数据的基本单位(数据项)数据对象 性质相同的一类数据元素的集合数据逻辑结构 数据元素之间的组织形式:集合、
2、 线性结构、树形结构 网状结构。,基本概念和相关术语,物理结构 数据在计算机内部的实际存储结构结点 存储在内存中的数据元素域 数据元素中的每个数据项线性存储结构 用物理地址相邻来表示数据元素在逻辑上的相邻关系。链式存储结构 元素之间逻辑上的相邻关系物理地址上不一定相邻,而是通过指针来描述,抽象数据类型,数据类型是和数据结构密切相关的一个概念。不同的数据类型拥有不同的取值范围和允许的操作。从硬件的角度来看,数据类型涉及具体存储单位。如int型占用两个字节的存储空间,float型占用4个字节的存储空间,可以帮助程序开发人员了解内存的使用情况。,抽象数据类型,抽象数据类型(Abstract Data
3、 Type,ADT) 原子类型 固定聚合类型 可变聚合类型 抽象数据类型的组成(三元组 D S P) D表示数据对象 S是D上的数据关系 P表示D的基本操作,算法分析,算法 对特定问题求解步骤的一种描述,然后再依据算法编制程序完成 要求。 特性 有穷性 确定性 可行性 输入 输出 好的算法特性 正确性 可读性 健壮性 高效率 低存储,算法的时间复杂度分析,事后统计法 直接比较运行时间 事先分析法 用数学方法直接对算法的效率进行分析 指令的执行次数 抛弃特定的软硬件配置有关的因素,直接求出算法中加法和乘法的执行次数。,下课了。,追求,休息一会儿。,数据结构第二章 线性表,线性表,定义 具有相同类
4、型的n个数据元素的有限序列。元素之间存在着线性的逻辑关系。,前驱结点和后继结点,以ai为例, ai+1是它的直接后继元素, ai-1是它的直接前驱元素。,线性表顺序存储结构,定义 把线性表存储在一串连续的内存地址的结构叫做线性表的顺序存储结构。优点 只要知道第一个数据元素的位置,就可以很快地找到表中任何一个元素。基本操作 插入、删除、查询,线性表的链式存储结构,链表 一种动态存储结构,在需要插入一个结点时,按结点的类型向系统申请一个结点的存储空间;当删除一个结点时,就将这个结点的存储空间释放,它比顺序存储方式更加灵活、高效。结点 表示数据元素内容的部分称为数据域,表示直接后继元素或直接前驱元素
5、位置的部分称为指针。,单链表,单链表结点由两部分组成:一部分是该结点的数值, 另一部分是指向直接后继结点的指针。,可以将链表画成如下的形式,h是头指针,它指向单链表的第一个结点,是单链表的入口地址访问单链表的任何结点必须由头指针出发。,单链表的基本操作,链表的建立计算表长查询元素插入结点删除结点,循环链表,将单链表的最后一个结点的指针域指向头结点,从而形成一个环状,由此,从表中任意一结点出发都可以访问到表中其他的结点。,循环链表,需要在第一个结点之前附加一个头结点作为标记,头结点的数据域存储任何信息,指针域指向第一个结点。,循环链表的基本操作,循环链表的操作与单链表基本一致,如插入、删除、查找
6、、输出等。区别仅仅在于尾结点的判定条件不同。,双向链表,在需要同时频繁访问前驱和后继结点的时候,定义一种新型的存储结构双向链表。每个结点包含两个指针域:一个指向前驱结点,另一个指向后继结点。,双向链表,双链表为当前结点与它们的前后继结点都建立明确的逻辑关系,这样就解决了链表反方向访问结点的问题。,可以方便地向前访问结点,既不需要像单链表那样重新遍历结点,也不需要像循环链表那样从尾结点“跳回”到头结点 。,双链表的基本操作,双链表的建立插入删除,循环双链表,一种变化的双链表形式。它借鉴了循环链表的思想,将双链表的最后一个结点的后继指针指向头结点,头结点的前驱指针指向最后一个结点。,循环双链表实质
7、上是两个单循环链表的合成,结点类型和基本操作与双链表完全一样,直接采用双链表结点的定义。,循环双链表的基本操作,循环双链表的构造循环双链表的遍历插入删除查找,下课了。,追求,休息一会儿。,数据结构第三章 栈与队列,栈和队列,定义 栈和队列是两种特殊的线性表。插入和删除操作均在对首尾两个元素上进行。因此,从操作的角度上看,它们属于操作受限的线性表。应用背景 铁路调度中需要用到栈,民航机票订购中也会用到队列。另外,栈和队列广泛应用于软件系统中。,栈(stack),定义 限定在表的一端进行插入或删除操作的线性表。相关术语 栈顶 栈底 栈长 空栈,进栈和出栈,a0先进栈,an最后进栈,如图3-1所示。
8、an是栈顶元素,所有出栈、入栈操作都是针对它进行的。a0是栈底元素,最后一个出栈。总之,栈是按后进先出(Last In First Out,LIFO)的原则进行处理的。,栈的顺序存储结构(顺序栈),顺序栈在存储地址上也是连续的,因此可以用数组表示顺序栈中的所有元素。,定义一个整型变量top来存储栈顶元素的下标,其作用相当于栈顶指针。指向最后一个入栈的元素。,顺序栈的基本操作,顺序栈的基本操作计算栈长返回栈顶元素入栈出栈遍历栈,栈的链式存储结构(链栈),栈的链式存储结构是通过单链表实现的。此时表头(第一个结点,非头结点)指针被称为栈顶指针,由栈顶指针指向的表头结点称为栈顶结点。,链栈的基本操作与
9、顺序栈相同,栈的应用,表达式求值 计算两个运算数之间的加、减、乘、除运算数值转换 十进制数和其他数制(比如二进制)之间的转换括号匹配 判断表达式中的括号是否成对出现递归的实现 递归运算满足“后运算先返回”原则,可以利用栈来实 现,队列(Queue),定义 队列也是一种特殊的线性表,和栈相比,队列只允许在一端进行插入操作,而在另一端进行删除操作。 相关术语队尾(Rear):可以插入元素的一端。队头(Front):可以删除元素的一端。,队列,0是队头元素,最早出队;n是队尾元素,最后出队,元素是按照入队顺序出队的。由此可见,队列的特点是先进先出(First in First out,FIFO)。,
10、队列的应用背景,操作系统中的作业排队 在允许多道程序运行的计算机系统中,同时有几个作业运行时,就需要按作业的先后次序进行排队。位于队头的作业先退出队列送入CPU进行处理;当一个任务完毕以后,新队头的作业从队列中出队,进行处理;另外,新的作业被送入到队列的队尾处,等待处理。,队列的顺序存储结构(顺序队列),队列的顺序存储结构和栈类似,也是在连续的存储空间中存储数据元素。因此,可以借助一维数组来表示队列中的元素。,需要设置front和rear 两个指针,并约定front指针在rear指针之前。当两者相等时,队列为空。初始化队列时,令front=rear=-1,此时队列空。为了指示队头和队尾,需要设
11、置front和rear 两个指针,并约定front指针在rear指针之前。,入队,插入新元素到队尾时,尾指针rear加1。在非空队列中,头指针front总是指向当前队头元素的前一个位置;当front=rear时,表示队列为空。,出队,删除队头元素时,指针front加1。,顺序队列的基本操作,入队出队取队头元素遍历队列删除队列,顺序队列的问题,顺序队列因为队尾指针rear越出数组上界而“溢出”,最终导致新元素无法入队。因此,,当队列中rear指针的值等于数字最大值时,新元素无法入队。但实际上,队列中仍然有两个存储空间可供存储,此时的“溢出”并不是真的因为存储空间不够而引的。,循环队列,为了克服这
12、种问题,可以将队列的首尾连接在一起,形成一个环状,如果有元素出队的话,那么进队的元素可以存储到出队的元素位置上,直到数组全部填满为止。在实际的软件系统中,这种队列经常被使用,而顺序队列却很少使用。,循环队列的基本操作,判断循环队列是否为空 以“队头指针front在队尾指针rear的下一个位置上”作为队列是 “满”状态的标志。入队出队计算队长取队头元素,队列的链式存储(链式队列),用链表的形式存储的队列称作链式队列。与顺序队列一样,链式队列也需要定义队头和队尾两个指针(分别称为队头指针和队尾指针),队头指针指向第一个结点,队尾指针指向尾结点。所以,一个表头和一个表尾唯一地确定一个队列。,链式队列
13、的基本操作与顺序队列相同,链式队列的应用,舞会配对(男女配对问题) 先入队的男士或女士亦先出队配成舞伴。因此该问题具有典型的先进先出的特性,可用队列作为算法的数据结构。模拟病人看病 医院看病者先到先看,所以使用队列来实现看病过程,下课了。,追求,休息一会儿。,数据结构第四章 串,第四章 串,定义 串(String)是字符串的简称,它是由有限的字符组 成的序列,一般记为s=“s0s1s2sn-1”。其中,s是串名 ,n是串的长度。双引号括起来的字符序列s0s1s2sn-1 称作串的值。,串,相关术语 串的长度 空串 子串 主串 两个串相等,串的顺序存储结构,串的顺序存储结构用一组连续的存储单元(
14、数组)依次存储串中的字符序列,需要事先定义一个固定长度的存储区域存储字符串(如数组)。,串的顺序存储结构,顺序串的基本操作 字符串的初始化 字符串的复制 字符串的连接 子串的提取 字符串的插入 字符串的删除 字符串的遍历,串的堆存储结构,为了处理在串操作中出现串的长度超过预定义的长度的情况,可以采用堆分配的存储方式。 堆存储方式的特点:仍以一组地址的连续的存储单元存放字符序列,但它们的存储空间是在程序执行过程中动态分配的。在C语言中,存在一个称之为“堆”的自由存储区,可由C语言中的malloc函数和free函数管理,为了处理方便,规定串的长度也作为存储结构的一部分。,串的块链存储结构,串的链式
15、存储结构分为单字符结点链和块链两种。 串的链式存储结构就是把串值分别存放在链表的若干个结点的数据域中。,块链就是每个结点的数据域包括若干个字符,由于串的大小不一定等于结点大小的整数倍,则链表中的最后一个结点不一定全部被串值占满,此时可以补上“#”或其他非串值字符,块链的基本操作,统计块链的长度 统计字符数组的长度 初始化块链 替换操作 提取子串操作 链接操作 块链的遍历,串的模式匹配方法,定义 设s和t是给定的两个串,且s的长度大于t的长度,在s中找到等于t的子串的过程称为串的模式匹配,如果找到,则称为匹配成功,否则,匹配失败。 应用背景 模式匹配是一种重要的串操作,在文字处理等软件中有着广泛
16、的应用。如word。,简单的模式匹配算法(BF算法),主要思想 蛮力算法,从主串的第一个字符开始和模式串的第一个字符开始比较,若相等则继续比较后续字符;否则从主串s的第二个字符开始重新与模式串t的第一个字符比较,按照这个方式,继续下去。如果模式串t和主串s的某一段连续子串相等,则匹配成功,并返回模式串t的第一个字符在主串中的位置;若匹配不成功,则返回-1。,BF算法的缺点,BF算法虽然简单,易于理解,但时间效率低。这是因为在主串和子串已有相当多个字符相等的情况下,只要有一个字符不相等,就需要重新将主串的比较位置后移一位,之前做过的比较工作也需要重新进行。 为了克服这个缺点,D.E.Knuth、
17、J.H.Morris和V.R.Pratt提出了克努特莫里斯普拉特算法,简称KMP算法。 该算法主要消除了主串指针(i指针)的回溯,利用已经得到的部分匹配结果将模式串右滑尽可能远的一段距离再继续比较,从而使算法效率有某种程度的提高,KMP算法,KMP算法,KMP算法中,主串指针i不回溯,由模式串指针j退到某一个位置k上,使模式串中的k之前的(k-1)个字符与主串中的i之前的(k-1)个字符相等,这样可以减少匹配的次数,从而提高效率。所以,KMP算法的关键在于如何找到k。,串的应用,文本编辑程序(如Windows中的notepad程序)是一个面向用户的系统服务程序,应用于程序的修改和输入、书籍的编
18、辑排版等。利用计算机进行编辑工作,是将文本(一段程序、一组数据、一篇文章等)。视为一个有限字符序列,然后可以运用关于串的各种操作对文本进行诸如增、改、删除等操作。,文本编辑器,一段文本程序,文本编辑程序中设立页指针、行指针和字符指针,分别指示当前操作的页、行和字符。 文本的操作:输入文本、插入文本和删除文本。,显示多位数数字字符,实现五位数的数值转换成字符的形式,并显示出来。首先将数值存储到字符型数组中,然后将其转换成整型数;对于计算结果,从高位数开始,依次存入到字符数组中,之后以字符的形式显示出来。,在常用的word文本中,数字都是以字符的形式存储的,因此本实例有实际的价值。,下课了。,追求
19、,休息一会儿。,数据结构第五章 数组与广义表,数组和广义表,定义 数组(Array)是一组由类型相同的数据元素构成的有限序列,且该序列存储在一块地址连续的内存单元中。顺序表、顺序栈和顺序队列都是以这种方式进行存储的。,L=(a1, a2, a3, , ai-1, ai, ai+1, , an),一维数组,二维数组,数组性质,元素个数固定 一旦定义了一个数组,它的维数和维界就不能再改变 只能对数组进行存取元素和修改元素的操作。 元素具有相同的数据类型 每个元素都和唯一的下标对应 随机存储结构 可随机存取数组中的任意数据元素。,一维数组的顺序存储结构,数组中每个元素是有序的,并且每个元素之间的次序
20、是不能改变的。数组只能执行取元素和修改元素操作可以执行,而不能进行插入和删除操作,这也是数组和线性表的重要区别。 数组的存储结构与顺序表则完全一样。,二维数组的顺序存储结构,二维数组在内存中的实际存储单元也是一维结构的。 二维数组有两种存储方式:一种是以列序为主序的存储方式,即先存储第1列数据元素,再存储第2列数据元素,直至所有元素存储完毕,Fortran语言使用这种方式;另一种是以行序为主序的存储方式,即先存储第1行数据元素,再存储第2行的元素,直至所有元素存储完毕,C、Pascal、Basic语言使用这种存储方式。第二种方式最常用。,二维数组的顺序存储结构,二维数组的基本操作,二维数组的显
21、示 读取二维数组中的元素 二维数组的加法 二维数组的减法 二维数组的点乘 二维数组的点除,矩阵的压缩存储,定义 在高级语言(C, C+)编程中,通常用二维数组来存储矩阵元素当矩阵里有很多0或者相同元素时,可以考虑这些相同元素或0元素共用一个存储单元,也就是要进行矩阵压缩。特殊矩阵 对称矩阵、上三角阵、下三角阵和对角阵 稀疏矩阵,特殊矩阵,对称矩阵,对于这种矩阵,可以为每一对对称元素分配一个存储空间,nn个元素的矩阵可以存储到n(n+1)/2个存储空间中。,特殊矩阵,上三角矩阵 只有对角线以上的部分有数值,以下的部分是同一个常数。,上三角矩阵除了要存储上半部分的数据之外,还要额外存储一个常数项,
22、需要用n(n+1)/2+1个存储单元。,特殊矩阵,下三角矩阵 下三角矩阵与上三角矩阵相反,常数位于矩阵的上半部分。,下三角矩阵的压缩存储结构和上三角矩阵一样,区别在于存储的是矩阵的下三角和上三角的常数 ,实现方法和存储空间也和上三角矩阵一样。,特殊矩阵,对角矩阵 只有对角线位置上的元素非0,其余位置的元素均为0。,压缩存储时只需要存储对角线上的非0元素即可,实现最简单。,系数矩阵,定义 非零元素的个数远远低于零元素的个数的矩阵,稀疏矩阵压缩存储时,只存储稀疏矩阵中的非零元素。包含行下标、列下标和数值的三元数组(i, j, value)可以唯一确定非零元素。,系数矩阵的基本操作,三元组的生成 稀
23、疏矩阵的加(减)法 稀疏矩阵的转置 三元组的乘法,广义表,定义 广义表是线性表的推广,也称为列表(Lists),一般记作:,LS=(a1,a2,a3,an),ai可以是单个元素(原子),也可以是广义表(子表)。,相关术语 表头(Head): 广义表中的第一个元素 表尾(Tail): 表中除了表头之外的所有元素 深度(Depth):广义表中括号嵌套的最大层数。,广义表的性质,广义表的元素可以是子表,而子表的元素也可以是子表广义表可用其他广义表来表示广义表可以是一个递归的表,广义表的存储结构,采用链式存储结构。需要两种结构的结点:一种是原子结点,另一种是表结点,用以表示列表。,表结点,原子结点,广
24、义表的基本运算,广义表的建立统计广义表的长度统计广义表的深度递归运算返回广义表表头(尾)广义表遍历,下课了。,追求,休息一会儿。,数据结构第六章 树,树,定义 树是包含n个结点的有限集合。它是一种非线性结构,用于描述数据元素之间的层次关系。,一般树,单结点树,基本术语,结点(Node) 结点的层次(Level)结点的度(Degree) 堂兄弟(Sibling)树的度(Degree of Tree) 树的深度(Depth)分支结点(Branch Node) 无序树(Unordered Tree)孩子结点(Child Node) 有序树(Ordered Tree)双亲结点(Parent Node)
25、 森林(Forest)祖先结点(Brother Node)子孙结点(Ancestor Node),二叉树(Binary Tree),二叉树是n个结点的有限集合。当n=0时,称为空二叉树;反之则为非空二叉树。除根结点以外的其余结点都分为左右两个互不相交的部分,左侧的称为左子树,右侧的称为右子树,两者不能颠倒。,两棵二叉树,二叉树,在一棵二叉树中,如果所有分支结点都存在左、右子树,并且所有叶结点都在同一层上,这样的二叉树称作满二叉树。如果一棵具有n个结点的二叉树的结构与满二叉树的前n个结点的结构相同,这样的树称作完全二叉树,满二叉树,完全二叉树,二叉树顺序存储结构,对于满二叉树而言,结点序号为i的
26、双亲结点,左孩子的结点序号为2i,右孩子的结点序号为2i+1。可以按照这个序号将结点数值存储到一维数组的相应位置处。,对于非完全二叉树来说,需要在非完全二叉树中添加一些并不存在的空结点使之变成完全二叉树,然后再用一维数组顺序存储二叉树。,二叉树链式存储结构,二叉树的每个结点有两个孩子结点,因此,每个结点除了存储自身的数据外,还应当设置两个指针分别指向左、右孩子结点。若要在二叉树中经常寻找某结点的双亲,每个结点还可以增加一个指向其双亲的指针域,包含双亲指针的结点,不包含双亲指针的结点,二叉树链表的基本运算,插入二叉树结点返回 结点数据域内容返回左孩子结点返回右孩子结点统计二叉树深度,遍历二叉树,
27、定义 按某种搜索路径访问树中的每个结点,使得每个结点都只被访问一次。 如果限定先左后右,二叉树遍历可以分为先序遍历、中序遍历和后序遍历。,以左图为例,先序遍历结果是ABDECF。中序遍历结果是 DBEAFC。后序遍历结果是DEBFCA,二叉树遍历的应用,统计二叉树的叶子结点数 复制二叉树 二叉树比较(比较两个二叉树是否完全相同) 二叉树镜像,线索二叉树,线索二叉树结点除了拥有左右孩子指针,同时还能保存按某种次序遍历下的前趋后继结点。,若结点有左子树,则其lchild域指向其左子树,否则指向其前趋;若结点有右子树,则其rchild域指向其右子树否则指向其后继结点。,线索二叉树,以左图为例,它的线
28、索二叉树如下所示。,树和森林,一般树的存储结构 双亲表示法 孩子表示法 孩子兄弟表示法。,森林和二叉树的转换,森林是若干棵树的集合。只要将森林中各棵树的根视为兄弟,每棵树又可以用二叉树表示(左子女右兄弟表示),这样,森林就可以用二叉树表示。森林转化为二叉树 二叉树还原为森林,森林的遍历,先序遍历森林 1. 访问森林中第一棵树的根结点。 2. 先序遍历第一棵树中根结点的子树森林。 3. 先序遍历除去第一棵树之后剩余的树构成的森林。 中序遍历森林 1. 中序遍历森林中第一棵树的根结点的子树森林。 2. 访问第一棵树的根结点。 3. 中序遍历除去第一棵树之后剩余的树构成的森林。,哈夫曼树(Huffm
29、an Tree),定义 哈夫曼树是指n个带权叶子结点构成的所有二叉树中,带权路径长度最小的二叉树。所谓的“路径”,就是从树中的一个结点到另一个结点之间的分支构成的部分,而分支的数目就是路径长度。,左侧三幅带权二叉树的带权路径长度依次是40,37和50。,哈夫曼树的构造,1. 由n个权值的结点构成的集合。2. 在所有结点中选取两个权值最小的结点作为左、右子孩子结点,新根结点的权值为其左、右子树根结点的权值之和。3. 从集合中删除在第2步中选出的两个结点,在从集合中剩余的结点中选取权值最小的结点加入到树种,直到所有的结点都加入到树中为止,此时便得到哈夫曼树。,哈夫曼编码,哈夫曼编码原理与哈夫曼树构
30、造的原理相同,区别在于哈夫曼树中的权值表示为数字通信中的字符出现的概率。,以左图为例,A的编码为0,C的编码为10,D的编码为110,B的编码为111。,下课了。,追求,休息一会儿。,数据结构第七章 图,图,定义 图是一种比线形表和树更加复杂的数据结构。图中的任何元素之间都可能有关系。图G是由非空的顶点集合V和一个描述顶点之间关系的集合E组成。,无向图,有向图,图的基本术语,顶点 权值边 路径长度无向图 简单路径有向图 子图完全图 连通图邻接顶点 连通分量顶点的度 强连通图路径 强连通分量,图的存储结构,邻接矩阵表示法 用矩阵存储图中的顶点信息,表示顶点之间相邻关系,应用于无向图。,以左图为例
31、,它的邻接矩阵表示结果是,图的存储结构,邻接表表示法 图的一种链式存储结构,图中的每一个结点建立一个单链表。每个表结点由两个域组成:一个是邻接点域,用来存储顶点i的序号;第二个是链域,用来将邻接表的所有表结点链接在一起。每个顶点的邻接表需要设置一个表头结点。,表结点,表头结点,图的存储结构,邻接表表示法,以左图为例,它的邻接表表示结果如下所示,图的存储结构,十字链表表示法 多重邻接表表示法,图的遍历,定义 图的遍历是指从指定的某个顶点(初始点)出发,按照一定的搜索方法对图中的所有顶点做一次访问的过程。在这一个过程中,必须记住每一个被访问过的顶点,以免再次访问。遍历方式 深度优先遍历和广度优先遍
32、历,图的遍历,广度优先遍历 类似于对树的按层遍历,其过程如下:首先访问初始顶点,并将其标记为已访问过;接着访问vi的所有未被访问过的邻接点,并做标记,访问次序任意;然后再依次访问这些顶点的邻接顶点,并做标记;以此类推,直到图中所有顶点都被访问过为止。,深度优先遍历 首先访问一个顶点,并将其标记为已经访问过,然后依次搜索该顶点的每一个邻接点,若其中有未被访问过的顶点,则以它为新的出发点继续进行深度优先遍历。依次类推,直到访问完所有的顶点。,生成树,定义 假设一个有若干个顶点的连通图,经由上面两种遍历算法得到的结果,会得到用最少的边来连接所有的顶点,而且不会形成回路,这样的子图是一种树形结构。,无
33、向图,深度优先遍历,广度优先遍历,最小生成树,定义 最小生成树就是所有边的权值总和最小的生成树。 算法 Kruskal算法 Prim算法,最小生成树算法,Kruskal算法 由克鲁斯卡尔(Kruskal)提出。每次选取权值最小的边,不用从某顶点出发,然后检查是否形成回路,形成回路的边需要放弃。最终构成最小成本生成树。,Prim算法 普里姆(Prim)提出了Prim算法来避免回路的检查,方法是从某个顶点vi出发,列出顶点所有邻接点的边,选择最小的边(vi , vj)加入到最小生成树中,然后删除该边,再加入顶点vj除了(vj, vi)之外所有的连接边,再找出最小的边,依次类推。,最短路径,单源点最
34、短路径 狄克斯特拉(Dijkastra)算法:按路径长度递增的顺序逐步产生最短路径的构造算法。 所有顶点对最短路径 弗洛伊德(Floyd)算法:提出了一种更加简单的算法,它在图的邻接矩阵上做n次迭代。第n次迭代后,邻接矩阵上第i行第j列的元素即为i到j的最短路径。,拓扑排序,顶点活动图(AOV图) 形象地反映出整个工程中各个活动,图中的有向边代表工程的先后关系,起点活动是终点活动的前序活动,只有起点活动完成之后,其终点活动才能进行。AOV网中不允许有回路 。,拓扑排序,上图中1、7是需要首先完成的工作,然后才能执行2、5、8等操作。所谓拓扑排序就是把AOV网络中各顶点按照它们相互之间的优先关系
35、排列成一个线性序列的过程。 排序过程: 1. 在有向图中选择一个没有直接前趋的顶点输出。 2. 从图中删除该顶点和所有以它为尾的边。 3. 重复上述步骤,直到全部定点输出为止。,关键路径,通常,用有向图表示一个工程,在这种有向图中,用顶点表示活动,用有向边表示活动必须先于活动。用有向边表示一个工程中的各项活动,用有向边上的权值表示活动的持续时间,用顶点表示事件,则这种有向图叫做用边表示活动的网络,简称AOE(activity on edge)。 完成整个工程所需的时间取决于从源点到汇点的最长路径长度。这条路径长度最长的路径叫做关键路径。,哈夫曼树(Huffman Tree),定义 哈夫曼树是指
36、n个带权叶子结点构成的所有二叉树中,带权路径长度最小的二叉树。所谓的“路径”,就是从树中的一个结点到另一个结点之间的分支构成的部分,而分支的数目就是路径长度。,左侧三幅带权二叉树的带权路径长度依次是40,37和50。,哈夫曼树的构造,1. 由n个权值的结点构成的集合。2. 在所有结点中选取两个权值最小的结点作为左、右子孩子结点,新根结点的权值为其左、右子树根结点的权值之和。3. 从集合中删除在第2步中选出的两个结点,在从集合中剩余的结点中选取权值最小的结点加入到树种,直到所有的结点都加入到树中为止,此时便得到哈夫曼树。,哈夫曼编码,哈夫曼编码原理与哈夫曼树构造的原理相同,区别在于哈夫曼树中的权
37、值表示为数字通信中的字符出现的概率。,以左图为例,A的编码为0,C的编码为10,D的编码为110,B的编码为111。,下课了。,追求,休息一会儿。,数据结构第八章 查找,查找,定义 查找是对数据进行处理时经常用到的一种操作。查找是指在一个数据元素集合中查找出关键字等于某个给点关键字的数据元素。应用背景主要应用于数据处理方面或计算机系统之中,如一般的数据查找、操作系统的文件查找、应用软件的文字查找(例如,word、excel等)、数据库系统的查找等。,静态查找表,顺序表的查找 从表的一端开始扫描线性表,依次将扫描到的数据元素和给定的关键字比较,若相等,则查找成功;若直到扫描结束仍未找到,则查找失
38、败。有序表的查找 在一个循环过程中,将查找区间中心位置上的数据元素和给定关键字进行比较,若两者相等,则查找成功;否则如果前者大于给定关键字,则将查找区域改变成原查找区的前半段,否则改为原查找区的后半段,然后继续这个过程,一直持续到查找区间的上界小于查找区间的下界为止。,静态查找表,索引顺序表的查找 先将表分成几块,块内无序,块间有序,查找时,先确定待查元素所在的块,然后再在块内查找。对于每一个分块建立一个索引项,其中包含关键字项(该块内的最大关键字)和指针项(指示该块的第一个元素在表中的位置)。,动态查找表,二叉排序树,性质:若它的左子树不为空,则左子树上所有结点的值均小于它的根结点的值。2.
39、 若它的右子树不为空,则右子树上所有结点的值均大于它的根结点的值。3. 它的左右子树分别为二叉排序树,二叉平衡树,定义 二叉平衡树是形态匀称的二叉排序树。其任意结点的左、右子树的高度大致相同,平衡二叉树的严格定义是平衡二叉树或者是空树,或者是任何结点的左子树和右子树高度相差最多为1的二叉树。,平衡二叉树,AVL树,每当插入一个结点时,首先检查是否因插入而破坏了树的平衡性,如果是,则找出其中最小不平衡子树,在保持排序树特性的同时,调整最小不平衡子树各结点之间的连接关系,以达到新的平衡。调整子树的四种方式。LL型调整,AVL树,RR型调整,AVL树,LR型调整,AVL树,RL型调整,B-树和B+树
40、,B-树 B-树是一种具有特殊结构的平衡多叉树,它同二叉树和一般树在结点结构上有所不同。和二叉树相比,B-树所有叶子结点都在同一层上。 应用背景 在对文件进行索引时,若以结点作为内存和外存交换的单位,则查找到需要的关键字之前,要对磁盘平均进行log2n次访问,比较浪费时间。为了减少访问外存的次数,需要降低查找树的高度,因此可以采用B-树。B-树常用作索引,在文件系统和数据库系统中有着重要应用。,B-树,查找关键字64的过程如下:首先从根结点开始,根据根结点指针找到a结点,因a结点中只有一个关键字50,且6450,则若关键字64存在,则必在根结点的右子树内;顺指针找到结点c,该结点有两个关键字(
41、58和78),而586478,则若存在必在该结点的左子树中;同样顺指针找到结点g,在该结点顺序查找关键字64,由此,查找成功。,B-树的基本操作,生成B-树的根结点 B-树中插入关键字 插入关键字操作 结点分裂 在B-树中查找关键字,B+树,B+树是B-树的变形。它与B-树的差异在于:所有的叶子结点中包含了全部关键字的信息,及指向这些关键字记录的指针,且叶子结点本身依关键字的大小按照从小到大的顺序连接。所有的非终端结点可以看成是索引部分,结点中仅含有其子树(根结点)中的最大(或最小)关键字。,键树,键树可以用来处理字符串,它是一个多叉树,树中的每一个结点并不代表一个关键字或元素,而只是代表字符
42、串中的一个字符。以下面字符串为例,,a, and, are, be, but, for, from, had, have, her, here,哈希表,如果能在数据元素的存储位置和其关键字之间建立一个确定的对应关系h,把具有关键字key的数据元素存储在h(key)处,那么在查找时,只要集合中存在关键字和key相等的数据元素,则一定在h(key)的存储位置上。,哈希表的构造方法,构造要求 既要便于计算,又能减少冲突,也就是要求关键字经过散列后比较均匀地分散到整个哈希表中。直接定址法除留余数法数字分析法平方取中法折叠法随机数法,处理冲突的方法,开放地执法 线性探测法 二次探查法 随机探查法开散列法
43、,下课了。,追求,休息一会儿。,数据结构第九章 内部排序,内部排序,排序是指将一组数据元素按指定的顺序进行排列的过程。内部排序,指的是待排序元素存储在计算机随机存储器(RAM)中进行排序的过程。,插入排序,直接插入排序 顺序地把待排序的数据元素按其关键字值的大小插入到已排序数据元素子集合的适当位置。子集合的数据元素个数从1开始逐次增加。当子集合大小最终和集合大小相同时完毕。 希尔排序 先将整个待排序元素分割成若干子序列分别进行排序,待整个序列中的元素“基本有序”时,再对全体元素进行一次直接插入排序。,希尔排序,交换排序,交换排序的基本思想是两两比较待排序对象,如果次序与预期次序相反的话,则交换
44、彼此的位置,直到所有对象排好序为止。 冒泡排序 以升序为例,冒泡排序的基本思想是将集合中的元素逐个进行比较,若第一个大于第二个,则交换两者的位置,然后比较第二个元素和第三个元素的大小,依此类推,直到全部元素比较完毕。,快速排序,在待排序的若干个元素中任取一个作为“基准”,将其余元素分为两组,第一组中各记录的关键值均小于或等于基准的关键字,第二组中各记录关键值均大于或等于基准的关键字,而基准就排在这两组之间,这个过程称为一趟快速排序。对所分成的两组分别重复上述方法,直到所有元素都排到了适当的位置上。,快速排序,选择排序,简单选择排序 由若干个元素组成的序列中,选择一个关键字最大或最小的元素输出,
45、然后再从剩余的元素中选择一个关键字最大或最小的元素输出。以此类推,直到排序结束。堆排序 堆是一棵完全二叉树,其中任一非叶子结点的关键字均大于(或小于)等于其孩子结点的关键字。它使用堆结构来完成选择最小(最大)关键字的工作。,归并排序,将两个或多个有序表合并成一个有序表的过程。若将两个有序表合并成一个有序表则称作二路归并,同理,有三路归并、四路归并等。其中,二路归并最简单且常用。 在排序过程中,需要利用一个与待排序数组同样大小的数组作为辅助。 首先把待排序区间中的每一个元素看成是一个有序表。则n个元素构成n个有序表。接着两两归并,即第一个表和第二个表归并,第三个表和第四个表归并,以此类推。,基数排序,主要是通过关键字间的比较和移动记录来实现的,而基数排序不需要进行关键字的比较。先将关键字分解成若干部分,然后通过对各部分分别排序,最终完成对全部记录的排序。,各种排序方法的比较,下课了。,追求,休息一会儿。,数据结构第十章 综合实训,综合实训一,经典的推箱子是一个来自日本的古老游戏,目的是在训练人的逻辑思考能力。在一个狭小的仓库中,要求把木箱从开始位置推放到指定的位置。在仓库有障碍物,稍不小心就会出现箱子无法移动或者通道被堵住的情况,而且箱子只能推,不能拉,所以需要巧妙的利用有限的空间和通道,合理安排移动的次序和位置,才能顺利的完成任务。,