1,将链队列的结点改为“双链”结点,即结点中包含next和priou两个指针;
2,修改入队列的操作,插入新的队尾结点时,令其priou域的指针指向刚刚出队列的结点,即当前的队头指针所指结点;
3,修改出队列的操作,出队列时,仅移动队头指针,而不将队头结点从链表中删除。
由于普里姆算法的时间复杂度为O( N的平方),则适于稠密图;而克鲁斯卡尔算法需对e条边按权值进行排序,其时间复杂度为o(eloge),则适于稀疏图。
7.5重(双)连通图和关节点
若从一个连通图中删去任何一个顶点及其相关联的边,它仍为一个连通图的话,则该连通图被称为重(双)连通图。
若连通图中的某个顶点和其相关联的边被删去之后,该连通图被分割成两个或两个以上的连通分量,则称此顶点为关节点。
没有关节点的连通图为双连通图。
关节点的特征:
假设从某个顶点V出发对连通图进行深度优先搜索遍历,则可得到一棵深度优先生成树,树上包含图的所有顶点。
若生成树的根结点,有两个或两个以上的分支,则此顶点(生成树的根)必为关节点;
对生成树上的任意一个“顶点”,若其某棵子树的根或子树中的其它“顶点”没有和其祖先相通的回边,则该“顶点”必为关节点。
如何求关键点:
1)对根结点来说深度优先遍历看count是否小于结点数,如果小于则该根结点为关节点。
2)对生成树上的顶点定义一个函数:
low(v)=Min{visited[v],low[w],visited[k]}(k为和v有回边相通的顶点)
对顶点v,若(在生成树上)存在一个子树根w,且low[w]>=visited[v]则顶点v为关节点
对深度优先遍历算法作如下修改:
1,visited[v]的值改为遍历过程中顶点的访问次序count值
2,遍历过程中求得
low(v)=Min{visited[v],low[w],visited[k]}
3,从子树遍历返回时判别low[v]是否>=visited[v]
7.6两点之间的最短路径问题
从源点到其余各点的最短路径
算法的基本思想:
依路径长度递增的次序求得各条路径
7.7拓扑排序
如何进行拓扑排序
一,从有向图中选取一个没有前驱的顶点(入度为零的顶点),并输出之;
二,从有向图中删去此顶点以及所有以它为尾的弧(弧头顶点的入度减1);
重复上述两步,直至图空,或者图不空但找不到无前驱的顶点为止。
如何求关键活动
“事件(顶点)”的最早发生时间ve(j)=从源点到顶点的最长路径长度;
“事件”的最迟发生时间vl(k)=从顶点k到汇点的最短路径长度;
假设第i条弧为<j,k>则第i项“活动弧“的最早开始时间ee(i)=ve(j);
"活动(弧)"的最迟开始时间el(i)=vl(k)-dut(<j,k>);
算法的实现要点:
求ve的顺序应该是按拓扑有序的次序;而求vl的顺序应该是按拓扑逆序的次序;拓扑逆序序列即为拓扑有序序列的逆序列,因此应该在拓扑排序的过程中,另设一个“栈”记下拓扑有序序列。