算法及数据结构(下)
来源:互联网 发布:晓风软件 编辑:程序博客网 时间:2024/05/22 23:59
一、排序算法
1、冒泡排序
2、选择排序
3、插入排序
4、堆排序
5、归并排序
6、快速排序
{ while (lo < hi) { while ((lo < hi) && (S[lo] ≤ S[hi]) hi--; while ((lo < hi) && (S[lo] ≤ S[hi]) lo++; swap(S[lo], S[hi]); swap(S[lo], S[hi]);} return lo;}
二、数据结构之串结构
1、串模式匹配
2、蛮力算法
3、Knuth-Morris-Pratt算法
在最坏情况下蛮力算法的运行时间为主串、模式串长度的乘积,因此只适用于小规模的串匹配应用。对最坏情况稍加观察即可发现,之所以需要大量的时间,是因为存在大量的局部匹配(每一轮的 m 次比较中,只有最后一次是失败的),实际上,绝大部分的这类字符比较操作都是不必要的,因为关于主串中此前曾经比较成功过的字符,我们已经掌握了它们的所有信息。只要充分利用这些信息,就可以大大提高匹配算法的效率。
如上图所示,用T[i]和P[j]分别表示当前正在接受比较的一对字符。当轮比较进行到最后一对字符并发现失配后,蛮力算法将会让这两个字符指针回退(即令i = i-j+1和j = 0 ),然后从这一位置继续比较。事实上,指针i完全不必回退⎯⎯因为通过前一轮比较我们已经清楚地知道,主串的子串T[i-j..i-1]完全是由字符'0'组成的。因此,在回退之后紧接下来的一轮迭代中,前j-1次比较将注定会成功。既然如此,完全可以让指针i保持不动并且令j = j-1,然后继续比较。请注意,如此将可以省去j-1次比较!
上述“i保持不动并且令 j = j-1”的含义,可以理解为“将 P相对于 T 向右移动一个单元,然后从刚才失配的位置继续比较”。实际上,利用以往的成功比较所提供的信息,不仅可以避免主串字符指针的回退,而且有可能使模式串尽可能大跨度地右移。
当本轮比较中发现T[i] ≠ P[7]失配后,应该将模式串P右移多少个单元呢?有必要逐个单元地右移吗?稍加观察即可发现,在这一情况下,移动一个、两个或三个单元都是徒劳的。事实上,根据以往的比较结果,必然有T[i-7..i] = P[0..7] = "CHINCHI" 。如果在此局部能够实现匹配,则至少在 T[i]左侧的那些字符应该是匹配的⎯⎯比如,当 P[0]与 T[i-3]对齐时,就属于这样的情况。如果再注意到i-3是能够如此匹配的最靠左位置,就可以放心地将模式串右移 7-3 = 4个单元,使 i保持不变,令 j= 3,然后继续比较。
相对于蛮力算法,KMP算法可以避免很多不必要的比较操作,KMP算法的运行时间为O(n+m),其中 n 和 m 分别文本串和模式串的长度。
4、BM算法
KMP算法的思想可以总结为:不断将模式串与文本串比较,一旦局部失配,则利用此前比较给出的信息,尽可能长距离的移动模式串,在比较模式串与文本串时,扫描方向是自左向右,实际上,很多模式匹配算法采用了其他的扫描方向,比如从右向左或者从中间向两边,BM算法采用的就是从右向左的扫描次序,该算法的构思是不断自右向左地比较模式串P与主串T,一旦发现失配,则利用此前扫描所提供的信息,将P右移一定距离,然后重新自右向左扫描比较,该算法有两种启发式策略:借助坏字符和好后缀确定移动的距离,也可将二者结合起来,同时采用。如 图九.7 所示,在自右向左比较模式串P[0..m-1]与主串的子串T[i..i+m-1]的过程中,假设在P[j]处首次发现失配:T[i+j] = 'b' ≠ 'a' = P[j]。此时,我们应该用P中的哪个字符对准T[i+j]并重新自右向左比较呢?我们注意到,若 P 能够与 T 的某一(包括 T[i+j]在内的)子串匹配,则必然也应在 T[i+j] = 'b'处匹配;反之,若与 T[i+j]对准的字符不是'b',则不可能匹配。因此,只需将 P 中的每一字符'b'对准T[i+j],然后重新自右向左比较。为了避免 P 的左移,我们可以选用 P 中最靠右的字符'b'(如果存在的话),将其与 T[i+j]对齐,然后重新做一遍自右向左的扫描比较。具体来说,若 P 中最靠右的字符'b'为 P[k] = 'b',则 P 的右移量为 j - k。
特殊情况:
如 图九.8 所示,P串中不含字符'b',此时可以直接将该串整体移过,用P[0]对准T[i+j+1],然后自右向左继续比较。 另外,即使 P 串中含有字符'b',却也有可能出现的位置太靠右,使得 k = BC['b'] ≥ j。在这一情况下,j-k 将不再是正数,若以此距离进行右移,实际效果将是左移⎯⎯显然,这是不必要的。因此,为处理这一情况,只需简单地将 P 串右移一个字符,然后重新自右向左扫描比较。
②好后缀策略
BM算法的思想,是尽可能的利用此前已进行过的比较所提供的信息,以加速模式串的移动,上述坏字符策略,就很好的体现了这一构思,然而,仔细分析后我们发现,坏字符策略只利用了此前失败的比较所提供的信息,实际上,在失败之前往往还会有一系列成功的比较,他们也能提供大量的信息,我们利用这些信息加速模式串右移,称之为好后缀策略。
三、数据结构之图
若边e = (u, v),则顶点u和v也称作e的端点(End vertices或Endpoints)。如果e是从u指向v的有向边,则u称作起点(Origin)或尾端点(Tail),v称作终点(Destination)或头端点(Head)。我们也称u和v是相邻的(Adjacent),称e与v、u是相关联的(Incident)。顶点v的关联边的总数,称为v的度数(Degree),记作deg(v)。以 图十.1(a)为例,有deg(a) = deg(c) = 3。在有向图中,以u为起点的有向边称作u的出边(Outgoing edge),以v为终点的边则称作v的入边(Incoming edge )。v的出边总数称作v的出度(Out-degree),记作outdeg(v);入边总数称作入度(In-degree),记作indeg(v)。以 图十.1(c)为例,有outdeg(a) = indeg(a) = outdeg(c) = indeg(c) =3。
图中所含的边并不见得能构成一个集合(Set),准确地说它们构成了一个复集(Multiset)⎯⎯其中允许出现重复的元素。比如,若在某对顶点之间有多条无向边,或者两条有向边的起点和终点完全一样,就属于这种情况。这类重复的边也称作平行边(Parallel e dges)或多重边(Multipleedges)。例如,要是用顶点表示城市,用边表示城市之间的飞机航线,则有可能在某一对城市之间存在多条航线。无论是无向图还是有向图,还有另一种特殊情况:与某条边关联的是同一个顶点(如 图十.1 中的顶点a)⎯⎯这样的边称作自环(Self-loop)。在某些特定的应用问题中,这类边的确是有意义的⎯⎯比如在城市交通图中,沿着某条街道,有可能会不经过任何交叉路口而直接返回原处。不过,这些特殊情况通常并不多见。不含上述特殊边的图,称作简单图(Simple graph)。对简单图而言,其中的边必然构成一个集合,而且每条边只能联接于不同的顶点之间。
④图的复杂度
设简单图G包含n个顶点和m条边。若 G 是无向图,则有 m ≤ n(n-1)/2;若 G 是有向图,则有 m ≤ n(n-1)。
⑤子图、生成子图、限制子图
设G=(V,E)和G‘=(V',E'),如果 V' ⊆ V 且 E' ⊆ E,则称 G'是 G 的一个子图,如果 V' = V 且 E' ⊆ E,则称 G'是 G 的一个生成子图,若 U ⊆ V,则在删除 V\U 中的顶点及其关联边之后所得到的 G 的子图,称为 G 限制在 U上的子图,记做 G|U= (U, E|U)。
⑥通路、环路及可达分量
所谓图中的一条通路或路径,就是由(不一定互异的)m+1个顶点与m条边交替构成的一个序列ρ = {v0, e1, v1, e2, v2, ..., em, vm},m ≥ 0,而且 ei= (vi-1, vi),1 ≤ i ≤ m,m称作该通路的长度,长度m≥1的路径,若第一个顶点与最后一个顶点相同,则称之为环路,如果组成通路ρ的所有顶点各不相同,则称之为简单通路,如果在组成环路的所有顶点中,除v0= vm外均各不相同,则称之为简单环路,如果组成通路ρ的所有边都是有向边,而且每一ei都是从vi-1指向vi,1 ≤ i ≤ m,则称ρ为有向通路,类似的也可定义有向环路。在图G=(V,E)中,若记n=|V|,则简单路径长度不超过 n-1;长度为 k 的简单路径的总数不超过 n!/(n-k-1)!,1 ≤ k ≤ n-1,G中简单路径的数目是有限的。
在有向图G中,若从顶点s到v有一条通路,则称v是“从s可达的”,对于指定的顶点s,从s可达的所有顶点所组成的集合,称作s在G中对应的可达分量,记作Vr(G, s)。
⑦连通性、等价类与连通分量
考察图 G = ( V, E)。在顶点 u, v ∈ V 之间,如果既存在一条从 u 到 v 的通路ρ(u, v),也存在一条从v到u的通路ρ(v, u),则称u和v是连通的,记作u ~ v。实际上,若 G 是无向图,则“ρ(u, v)存在”当且仅当“ρ(v, u)存在”。而对于有向图 G 来说,“ρ(u,v)和ρ(v, u)同时存在”即意味着“存在一条同时经过 u 和 v 的环路”。故此,有向图中相互连通的顶点也被称为是互相“强连通的”。在有向图中,由一组相互强连通的顶点构成的极大集合,称作一个强连通分量。若u~v,则必然存在一条经过u和v的环路,而且对于该环路上的任一顶点w,都有w~u和w~v。连通关系“~”满足如下性质:反身性:对于任何顶点 v,都有 v ~ v 成立;对称性:u~v仅当v~u;传递性:对于任何顶点u、v和w,只要u~v且v~w,则必有u~w。
⑧森林、树及无向图的生成树
考察无向图G=(V,E),若G中不含任何环路,则称之为森林,连通的森林(任何两个顶点都是连通的)称作树。若G为由n个顶点与m条边组成一幅无向图,若G是连通的,则m≥n-1,若G是一棵树,则m=n-1,若G是森林,则m≤n-1。若G的某一生成子图G‘为一棵树,则称G’为G的一颗生成树。
⑨有向图的生成树
在有向图G=(V,E)中,若存在某个顶点s满足Vr(G, s) = V(即从s可到达所有顶点)且s到任一顶点的通路唯一,同时G中不含回路,则称G为一颗以s为根的有向树。
⑩带权网络
有些时候,图不仅需要表示元素之间是否存在某种关系,而且还需要表示这一关系的某一细节,以铁路运输为例,可以用顶点表示城市,用顶点之间的边表示城市之间是否有铁路联接,然而,为了更为细致地描述铁路运输网,还需要记录每段铁路的长度、运输成本等信息,为适应这类应用的需求,我们需要为每条边设置相应的数据域,以记录对应的信息,对于任一边 e ∈ E,weight(e)称作 e 的权重 ,引入权重函数之后的图G(V,E,weight()),称作带权图或带权网络,有时也简称为网络。
- 算法及数据结构(下)
- 数据结构及算法-何谓数据结构
- MySQL索引背后的数据结构及算法原理(下)
- 数据结构及算法综述
- 数据结构及算法
- 数据结构及算法
- 数据结构及算法序言
- 常用数据结构及算法
- 数据结构及算法
- 数据结构及算法-算法是什么?
- java数据结构及算法一
- java数据结构及算法二
- java数据结构及算法三
- java数据结构及算法四
- 高级数据结构及算法分类
- 数据结构及算法面试题
- (考研)数据结构及算法
- 算法思想及数据结构 -- 总结
- WINDO查看端口 是否被占用
- 《响应式Web设计-HTML5和CSS3实战》阅读笔记第三章
- 自己常用的linux命令
- DevOps和容器:本地or云端,如何选择?
- unity的一个场景内,多个摄像机之间的切换。
- 算法及数据结构(下)
- Codeforces Round #406 C. Berzerk(搜索)
- 邮件模板里看似为标配的品牌LOGO ,却“别有用心”?
- zookeeper与dubbo的环境搭建
- 关于mesos在mac上的安装问题
- 游戏引擎概念理解
- IP地址
- 对话框程序禁用系统的关闭按钮X
- Android学习路线指南