完整内容见:
点击打开链接
今天收获很大,主要学习了基本数据结构和图论。
基本数据结构分为线形结构和树形结构,关于线形结构,主要就是链表、栈和队列。链表用的比较少,栈一般用来解决表达式求值的问题,有一道等价表达式的noip题目,以后可以做一下,还有就是队列,在bfs中应用很多,关键我要说的是树形结构:
①二叉和N叉哈夫曼树:哈夫曼树也叫最优二叉树,意思就是带权路径长度(WPL)最短,WPL的计算公式:叶节点权值*叶到根的路径长度。主要应用就是Huffman编码,如图就是一个N叉huffman树:
编码:A:0 B:2 0 C:2 2 D:1 E:2 1
②堆:堆是一个特殊的二叉树(也叫优先队列),可以动态的维护最大(小)值,时间复杂度是O(logN)的,比较高效,用于反复调用最大或最小值的问题,而且,堆还可以优化dijstra算法,经典题目:合并果子。
③二叉搜索树:基本操作就是查找元素、构造和删除。时间复杂度一般是O(N*logN)的,若二叉树有序,则是O(N^2)的,原理就是左孩子小,右孩子大的原则。
④并查集:三个操作:1.合并两个不相交的集合。2.判断两个元素是否在同一集合(利用了路径压缩)。3.路径压缩(维护了并查集)。合并集合,就是将一个集合中所有的节点连接到另一个根上。判断:将要判断的元素回溯至根,再判断根是否相同,回去之后要立刻做一做《亲戚》这道题,还可以做一下《银河英雄传说》、《pority》和《关押罪犯》。
基本数据结构分为线形结构和树形结构,关于线形结构,主要就是链表、栈和队列。链表用的比较少,栈一般用来解决表达式求值的问题,有一道等价表达式的noip题目,以后可以做一下,还有就是队列,在bfs中应用很多,关键我要说的是树形结构:
①二叉和N叉哈夫曼树:哈夫曼树也叫最优二叉树,意思就是带权路径长度(WPL)最短,WPL的计算公式:叶节点权值*叶到根的路径长度。主要应用就是Huffman编码,如图就是一个N叉huffman树:

编码:A:0 B:2 0 C:2 2 D:1 E:2 1
②堆:堆是一个特殊的二叉树(也叫优先队列),可以动态的维护最大(小)值,时间复杂度是O(logN)的,比较高效,用于反复调用最大或最小值的问题,而且,堆还可以优化dijstra算法,经典题目:合并果子。
③二叉搜索树:基本操作就是查找元素、构造和删除。时间复杂度一般是O(N*logN)的,若二叉树有序,则是O(N^2)的,原理就是左孩子小,右孩子大的原则。
④并查集:三个操作:1.合并两个不相交的集合。2.判断两个元素是否在同一集合(利用了路径压缩)。3.路径压缩(维护了并查集)。合并集合,就是将一个集合中所有的节点连接到另一个根上。判断:将要判断的元素回溯至根,再判断根是否相同,回去之后要立刻做一做《亲戚》这道题,还可以做一下《银河英雄传说》、《pority》和《关押罪犯》。
下面总结一下图论,图论之前没有很看过,几天算是刚刚接触。图结构有点(V)和边(E),点有度,边有权,是对图的描述吧。图的储存结构一般有4个:1.邻接表。2.邻接矩阵。3.边集数组。4.前向星。还有图的遍历,这个不是很懂:分为bfs和dfs两种。
再说一下生成树问题,主要就是无向图的最小生成树(MST),其所有边的权值之和不会大于任何其他的生成树,就是连接所有点的最低成本路线,其算法原理有4个:环属性、剪切属性、最小边缘则和唯一性,这里有两种算法求最小生成树:
①Prim(普里姆)算法。
②Kruskal(克鲁斯卡尔)算法:要用到并查集的合并与查找。
关于生成树这部分,我听懂了原理,但是不知道具体有什么应用,回来一定要解决这个问题。还有拓扑排序的问题,不是很懂。
我觉得比较重要的就是最短路径的问题了,最短路径有两个属性:
①三角形性质:dis[x]+len[x][y]>=dis[y].
②松弛:不符合三角形性质。if(
dis[x]+len[x][y]<dis[y]
)
dis[y]=
dis[x]+len[x][y].
下面四种不同的求最短路的算法就是利用了这两个性质。
①Dijkstra(迪杰斯特拉)算法:适用于边无负权的问题,可以用堆来优化,时间复杂度为O(N*N),分为三步:选择+标记+扩展。用堆优化后是O(N*logN)。
②Bellman-ford算法:这个算法可以处理边有负权的问题,而且可以判断负环,时间是O(N*E)的,原理就是不断松弛,若N次之后还可以松弛,则有负环。
③SPFA算法:这是对Bellman-ford的一个算法一个改进,时间是O(K*E)的。被松弛过的点x,看x是否可以松弛其他的点,用队列存放x,一般用“循环队列”。
以上三个算法均为求一个顶点到其他顶点的最短路径(单源最短路径)。
④floyed(弗洛伊德)算法:可以求每对顶点间的最短路径,时间O(N*N*N),原理:图的传递闭包思想。
if(d[i][k]+d[k][j]<d[i][j])
d[i][j]=
d[i][k]+d[k][j]. floyed的实质是一种动态规划。
总之对于这四种求最短路的算法,我懂原理,但是实际中我并不会应用到题目中去,代码实践也有问题,包括今天学的树相关的东西。
注意练习!