数据结构笔记下篇

第七章 图

图,是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合。

注意:1,线性表中我们把数据元素叫元素,树中将数据元素叫结点,在图中数据元素,我们称之为顶点。

2,线性表中可以没有数据元素,称为空表;树中可以没有结点,称为空树;但是在图结构中,不允许没有顶点。

3,线性表中,相邻的数据元素之间具有线性关系,树结构中,相邻的两层的结点之间具有层次关系,而图中,任意两个顶点之间都可能有关系,顶点之间的逻辑关系用边表示,边集可以是空的。

各种图的定义

无向边,若顶点vi到vj之间的边没有方向,则称这条边为无向边;如果图中任意两个顶点之间的边都是无向边,则称该图为无向图。

有向边,若顶点vi到vj之间的边有方向,则称这条边为有向边,也称为弧。如果图中任意两个顶点之间的边都是有向边,则称该图为有向图。连接顶点A到D的有向边就是弧,A是弧尾,D是弧头,<A,D>表示弧,不能颠倒。

无向完全图,在无向图中,如果任意两个顶点之间都存在边,则称该图为无向完全图。含有n个顶点的无向完全图有n*(n-1)/2条边。

有向完全图,在有向图中,如果任意两个顶点之间都存在方向互为相反的两条弧,则称该图为有向完全图。共有n*(n-1)条边。

有很少条边或弧的图称为稀疏图,反之称为稠密图。

与图的边或弧相关的数叫做权(weight),这种带权的图通常称为网(network)。

图中顶点之间有邻接点、依附的概念。无向图顶点的边数叫做度,有向图顶点分为入度和出度。

图中顶点间存在路径,两顶点存在路径则说明是联通的,如果路径最终回到起始点则称为环,当中不重复叫简单路径。若任意两顶点都是联通的,则图就是连通图,有向则称强连通图。图中有子图,若子图极大连通则就是连通分量,有向的则称强连通分量。

无向图中连通且n个顶点n-1条边叫生成树。有向图中一顶点入度为0其余顶点入度为1的叫作有向树,一个有向图由若干棵有向树构成生成森林。

图中五种不同的存储结构:

1,邻接矩阵,图的邻接矩阵存储方式是用两个数组来表示图。一个一维数组存储图中顶点信息,一个二维数组存储图中的边或弧的信息。邻接矩阵在边相对于顶点较少的情况下不适用(浪费空间)

2,邻接表,图中顶点用一个一维数组存储,当然,顶点也可以用单链表存储,不过数组可以较容易的读取顶点信息,更加方便。另外,对于顶点数组中,每个数据元素还需要存储指向第一个邻接点的指针,以便于查找该顶点的边信息;图中每个顶点的所有邻接点构成一个线性表,由于邻接点的个数不定,所以用单链表存储。

3,十字链表,十字链表的好处就是因为把邻接表和逆邻接表整合在了一起,这样既容易找到以vi为尾的弧,也容易找到以vi为头的弧。因而容易求得顶点的入度和出度。而且它除了结构复杂一点,其实创建图算法的时间复杂度和邻接表示相同的,在有向图的应用中,十字链表是非常好的数据模型。

4,邻接多重表,

图的遍历

从图中某一个顶点出发访遍图中其余顶点,且使每一个顶点仅被访问一次,这个过程就是图的遍历。

1,深度优先遍历,也叫深度优先搜索DFS,转换成一棵树就是利用树的前序遍历。

2,广度优先遍历,也叫广度优先搜索BFS,类似于树的层序遍历。

最小生成树,把构造连通网的最小代价生成树称为最小生成树。寻找最小生成树的算法有两种,一种是普里姆(Prim)算法,另一种是克鲁斯卡尔(Kruskal)算法。

最短路径

迪杰斯特拉(Dijkstra)算法:一步步求出顶点间的最短路径。

弗洛伊德(Floyd)算法:

拓扑排序

在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,这样的有向图为顶点表示活动的网,我们称为AOV网(Activity  On  Vertex  Network)。

设G=(V,E)是一个具有n个顶点的有向图,V中的顶点序列v1,v2,...vn满足若从vi到vj的一条路径,则在顶点序列中顶点vi必须在顶点vj之前,则我们称这样的顶点序列为一个拓扑序列。

拓扑排序算法,

关键路径

解决工程完成需要的最短时间问题,

AOE网:在一个表示工程的带权的有向图中,用顶点表示事件,用有向边表示活动,用边上的权值表示活动的持续时间,这种有向图的边表示活动的网,称之为AOE网(Activity  On  Edge  Network)。

把AOE网中没有入边的顶点,称之为始点或源点,没有出边的顶点称为终点或汇点。所以AOE网只有一个源点一个汇点。我们把路径上各个活动所持续的时间之和称之为路径长度,从源点到汇点具有最大长度的路径叫关键路径,在关键路径上的活动叫关键活动。

关键路径算法:事件的最早发生时间etv,事件的最晚发生时间ltv,活动的最早开工时间ete,活动的最晚开工时间lte,

第八章 查找

查找,就是根据给定的某个值,在查找表中确定一个 其关键字等于给定值的数据元素。

查找概论

查找表是由同一类型的数据元素构成的集合。关键字是数据元素中某个数据项的值,又称为键值。若此关键字可以唯一的标示一个记录,则此关键字为主关键字。对于那些可以识别多个数据元素的关键字,我们称之为次关键字。

查找表按照操作方式分为两大种:静态查找表和动态查找表。

静态查找表:只作查找操作的查找表,主要操作有,查询某个特定的数据元素是否在查找表中;检索某个特定的数据元素和各种属性。

动态查找表:在查找过程中同时插入查找表中不存在的数据元素,或者从查找表中删除已经存在的某个数据元素。有两个操作,查找时插入数据元素;查找时删除数据元素。

为了提高查找效率,我们需要专门为查找操作设置数据结构,这种面向查找操作的数据结构称为查找结构。

顺序表查找

顺序查找又叫线性查找,是最基本的查找技术,它的查找过程是:从表中第一个或最后一个记录开始,逐个进行记录的关键字和给定值比较,若某个记录的关键字和给定值相等,则查找成功,找到所查记录;如果直到最后一个或第一个记录,其关键字和给定值比较都不等时,则表中没有所查的记录,查找不成功。

有序表查找

折半查找技术,又称为二分查找。它的前提是线性表中的记录必须是关键码有序,线性表必须采用顺序存储。折半查找的基本思想:在有序表中,取中间记录作为比较对象,若给定值与中间记录的关键字相等,则查找成功;若给定值小于中间记录的关键字,则在中间记录的左半区继续查找;若给定值大于中间记录的关键字,则在中间记录的右半区继续查找。不断重复上述过程,直到查找成功,或所有查找区域无记录,查找失败为止。

插值查找

插值查找是根据要查找的关键字key与查找表中最大最小记录的关键字比较后的查找方法,其核心就在于插值的计算公式(key-a[low])/(a[high]-a[low])。适用于表比较长,且关键字分布又比较均匀的。

斐波那契查找,利用黄金分割原理来实现的。

线性索引查找

数据结构的最终目的是提高数据的处理速度,索引是为了加快查找速度而设计的一种数据结构。索引就是把一个关键字与它对应的记录相关联的过程,一个索引由若干个索引项构成,每个索引项至少应包含关键字和其对应的记录在存储器中的位置等信息。索引技术是组织大型数据库以及磁盘文件的一种重要技术。索引按照结构可以分为线性索引、树形索引、和多级索引。所谓线性索引就是将索引项集合组织为线性结构,也称为索引表。线性索引又分为稠密 索引、分块索引、倒排索引。

稠密索引:是指在线性索引中,将数据集中的每个记录对应一个索引项。索引项一定是按照关键码有序的排列。索引项有序也就意味着,我们要查找关键字时,可以用到折半、插值、斐波那契等有序查找算法。

分块索引:稠密索引因为索引项与数据集的记录个数相同,所以空间代价很大。为了减少索引项的个数,我们可以对数据集进行分块,使其分块有序,然后再对每一块建立一个索引项,从而减少索引项的个数。

分块有序,是把数据集的记录分成了若干块,并且这些块需要满足两个条件:

1,块内无序,即每一个块内的记录不要求有序。

2,块间有序,例如,要求第二块所有记录的关键字均要大于第一块中所有记录的关键字,第三块的大于第二块的。

分块索引的索引项结构分三个数据项:

最大关键码,它存储每一块的最大关键字,这样的好处就是可以使得在它之后的下一块的最小关键字也能比这一块最大的关键字要大。

存储了块中的记录个数,以便于循环时使用。

用于指向块首数据元素的指针,便于开始对这一块中记录进行遍历。

倒排索引:最简单最基础 的搜索技术。

索引项的通用结构是,次关键码和记录号表。其中记录号表存储具有相同次关键字的所有记录的记录号,这样的方法就是倒排索引。

二叉排序树:又称二叉查找树,它或者是一棵空树,或者是具有下列性质的二叉树,若它的左子树不空,则左子树上所有结点的值均小于它的根结构的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结构的值;它的左右子树也分别为二叉排序树。

平衡二叉树(AVL树)

平衡二叉树是一种二叉排序树,其中每一个节点的左子树和右子树的高度差至多等于1。

我们将二叉树上结点的左子树深度减去右子树深度的值称为平衡因子BF。那么平衡二叉树上所有结点的平衡因子只可能是-1、0和1。只要二叉树上有一个结点的平衡因子的绝对值大于1,则该二叉树就是不平衡的。

判定一个二叉树是不是平衡二叉树,首先要判断是不是二叉排序树,然后再看左右子树的高度差绝对值是否大于1.

调整二叉树为平衡二叉树,采用左旋,右旋操作使每一个子树到达平衡。

多路查找树(B树)

多路查找树,其每一个结点的孩子数可以多于两个,且每一个结点处可以存储多个元素。4种特殊形式:2-3树、2-3-4树、B树和B+树。

2-3树,是这样的一棵多路查找树:其中的每一个结点都具有两个孩子(我们称它为2结点)或三个孩子(我们称它为3结点)。一个2结点包含一个元素和两个孩子(或没有孩子),且与二叉排序树类似,左子树包含的元素小于该元素,右子树包含的元素大于该元素。不过,与二叉排序树不同的是,这个2结点要么没有孩子,要有就有两个,不能只有一个孩子。一个3结点包含一小一大两个元素和三个孩子(或没有孩子),如果某个3结点有孩子,则左子树包含小于较小元素的元素,右子树包含大于较大元素的 元素,中间子树包含介于两元素之间的元素。

2-3-4树,就是在2-3树上的一个扩展。增加一个4结点,包含小中大三个元素和四个孩子(或没有孩子),如果右孩子的话,左子树包含最小元素的元素;第二子树包含大于最小元素,小于第二元素的元素;第三子树包含大于第二元素,小于最大元素的元素;右子树包含大于最大元素的元素。

B树,是一种平衡的多路查找树,2-3树和2-3-4树都是B树的特例,结点最大的孩子数目称为B树的阶,因此,2-3树是3阶B树,2-3-4树是4阶B树。B树的数据结构就是为内外存的数据交互准备的。

B+树是应文件系统所需而出的一种B树的变形树,

一棵m阶的B+树和m阶的B树的差异在于:有n棵子树的结点中包含有n个关键字;所有的叶子结点包含全部关键字的信息,及指向含这些关键字记录的指针,叶子结点本身依关键字的大小自小而大顺序链接;所有分支结点可以看成是索引,结点中仅含有其子树的最大(或最小)关键字。

散列表查找(哈希表)

我们只需要通过某个函数f,使得存储位置=f(关键字),那样我们可以通过查找关键字不需要比较就可以获得需要的记录的存储位置。这就是一种新的存储技术--散列技术

散列技术是在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使得每个关键字key对应一个存储位置f(key)。我们把这种对应关系f称为散列函数,又称为哈希函数。采用散列技术将记录存储在一块连续的存储空间中,这块连续的存储空间称为散列表或哈希表。散列技术即是一种存储方法,也是一种查找方法。它与线性表、树、图等结构不同的是,前面几种结构,数据元素之间都存在某种逻辑关系,可以用连线图示表示出来,而散列技术的记录之间不存在什么逻辑关系,它只与关键字有关。因此,散列主要是面向查找的存储结构。

散列技术最适合的求解问题是查找与给定值相等的记录。

散列函数的构造方法

遵循两个原则:计算简单;散列地址分布均匀。

1,直接定址法,取关键字的某个线性函数值为散列地址,即f(key) = a*key + b;

2,数字分析法,通常适合处理关键字位数较大的情况,如果事先知道关键字的分布,且关键字的若干位分布较均匀,就可以考虑用这个方法。

3,平方取中法,比较适合于不知道关键字的分布,而位数又不是很大的情况。

4,折叠法,折叠法是将关键字从左到右分割成位数相等的几部分,然后将这几部分叠加求和,取后几位作为散列地址。这种方法适合事先不知道关键字的分布,适合关键字位数较多的情况。

5,除留余数法,对于散列表长为m的散列函数公式为:f(key) = key mod p(p <= m);

6,随机数法,

处理散列冲突方法

定址法,就是一旦发生冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入。

再散列函数法,

链地址法,

公共溢出区法

第九章 排序

排序:假设含有n个记录的序列为{r1,r2,....,rn},其相应的关键字分别为{k1,k2,...........,kn},需要确定1,2,.....,n的一种排序p1, p2, ......., pn,使其相应的关键字满足kp1<=kp2<=......<=kpn(非递减或非递增)关系,即使得序列称为一个按关键字有序的序列{rp1, rp2, .... ,rpn },这样的操作就称为排序。

多个关键字的排序最终都可以转化为单个关键字的排序。

排序的稳定性

假设ki=kj(1<=i<=n,1<=j<=n,i != j),且在排序前的序列中ri领先于rj(即i<j)。如果排序后ri仍领先于rj,则称所用的排序方法是稳定的;反之,若可能使得排序后的序列中rj领先于ri,则称所用的排序方法是不稳定的。

内排序和外排序

内排序是在排序整个过程中,待排序的所有记录全部被放置在内存中。外排序由于排序的记录个数太多,不能同时放置在内存,整个排序过程需要在内外存之间多次交换数据才能进行。

内排序,排序算法的性能主要受3个方面的影响,时间性能,辅助存储空间,算法的复杂性。

在内排序中主要进行两种操作,比较和移动。比较指关键字之间的比较,移动指记录从一个位置移动到另一个位置,总之,高效率的内排序算法,应该是具有尽可能少的关键字比较次数和尽可能少的记录移动次数。

根据内排序中算法本身的复杂度,可以把内排序分为,插入排序、交换排序、选择排序和归并排序。

本章一共讲解七种排序的算法,按照算法的复杂度分为两大类,冒泡排序、简单选择排序和直接插入排序属于简单算法,而希尔排序、堆排序、归并排序、快速排序属于改进算法。

冒泡排序(Bubble Sort),是一种交换排序,它的基本思想是,两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止。

简单选择排序(Simple Selection Sort),基本思想是每一趟在n-i+1(i=1,2,....,n-1)个记录中选取关键字最小的记录作为有序序列的底i个记录。就是通过n-i次关键字的比较,从n-i+1个记录中选出关键字最小的记录,并和第i(1<=i<=n)个记录交换。

直接插入排序(Straight Insertion  Sort),基本操作是将一个记录插入到已经排好序的有序表中,从而得到一个新的,记录数增1的有序表。

希尔排序(Shell Sort),原理:将原本有大量记录数的记录进行分组,分割成若干个子序列,此时每个子序列待排序的记录个数就比较少了,然后在这些子序列内分别进行直接插入排序,当整个序列都基本有序时,再对全体记录进行一次直接插入排序。所谓的基本有序,就是小的关键字基本在前面,大的基本在后面,不大不小的基本在中间。

为了保证在子序列内分别进行直接插入排序后得到的结果是基本有序而不是局部有序,我们需要对原始数据采取跳跃分割的策略,将相距某个“增量”的记录组成一个子序列。(不是一个稳定的排序算法)

堆排序(Heap Sort),是对简单选择排序进行的一种改进。

堆是具有下列性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。

堆排序的基本思想:将待排序的序列构造称一个大顶堆。此时,整个序列的最大值就是堆顶的根结点。将它移走(其实就是将其与堆数组的末尾元素交换,此时末尾元素就是最大值),然后将剩余的n-1个序列重新构造成一个堆,这样就会得到n个元素中的次小值,如此反复执行,便能得到一个有序序列了。

归并排序(Merging  Sort),就是利用归并的思想实现的排序方法。它的原理是假设初始序列含有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,,,如此重复,直至得到一个长度为n的有序序列为止,这种排序方法称为2路归并排序。

归并排序是一种比较占用内存,但却效率高且稳定的算法。(由于归并排序大量引用了递归,尽管在代码上比较清晰,容易理解,但这会造成时间和空间上的性能损耗,可以将引用递归的归并排序转换为迭代的归并排序。)

快速排序(Quick Sort),基本思想是,通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序的目的。

转载于:https://my.oschina.net/ykduan/blog/1503016

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值