图相关算法
图的保存形式:
- 邻接表,使用一个链表把图的点之间的链接关系保存起来,一般是所有的元素组成一个数组,数组中每个元素是一个节点,节点内保存当前元素和指向相邻元素的指针。
- 邻接矩阵,图中有n个节点,则矩阵E是n*n的,对于无向图,若i和j有链接关系,则E[i][j]=E[j][i]=1若无连接关系则为0;对于有向图,当i到j有边时候,E[i][j]=1,否则为0.
图的遍历:
- 深度优先遍历(DFS),即对于一个图,不管是矩阵还是邻接表,优先遍历的是孩纸节点,孩子节点遍历完成之后才遍历兄弟节点。
- 广度优先遍历(BFS),优先遍历兄弟节点。
无向图的最小树生成算法:
- Prim算法,任意选取一个点,然后从这个点拓展,每次选择图中权值最小并且不构成回路的那些边加入,直到最后所有的点都在这颗生成树中;
- kruskal算法:从边拓展最小生成树,选取权值小的并且不够成回路的边,直到所有的图中的点都在生成树中为止。
有向图的最短路径问题:
Dijkstra算法Floyd算法,这些算法基本上很多地方都有讲到。
- dijkstra算法是一种单源最短路径算法,主要求一个节点到另一个节点的算法,主要思想是一种广度优先算法,层层遍历,求最小的路径和。
- Floyd算法是一种动态规划算法,也可以作为求有向图的传递闭包。求从i到j的最短路径,不外乎两种情况,从i直接到j,从i经过若干的k到j,假设有i->j的路径比i->k->...->j大,则把i到j的路径设置为从i->k+k->j,循环如此,便可以得到最小的路径。其中上面给出的链接中有详细的解释。
关于Floyd算法的十字相乘法补充:以k为中间点(1)“三条线”:划去第k行,第k列,对角线(2)“十字交叉法”:对于任一个不在三条线上的元素x,均可与另外在k行k列上的3个元素构成一个2阶矩阵,x是否发生改变与2阶矩阵中不包含x的那条对角线上2元素和有关,若二者之和小于x,则用它们的和替换x,对应的Path矩阵中的与x相对应的位置用k来替代。。。
当然,还有一种算法就是A*算法,该算法像Dijkstra算法一样,可以找到一条最短路径;也像BFS一样,进行启发式的搜索。在此算法中,如果以 g(n)表示从起点到任意顶点n的实际距离,h(n)表示任意顶点n到目标顶点的估算距离,那么 A*算法的公式为:f(n)=g(n)+h(n)。 这个公式遵循以下特性:
- 如果h(n)为0,只需求出g(n),即求出起点到任意顶点n的最短路径,则转化为单源最短路径问题,即Dijkstra算法
- 如果h(n)<=“n到目标的实际距离”,则一定可以求出最优解。而且h(n)越小,需要计算的节点越多,算法效率越低。