概述
邻接关系:顶点和顶点间的关系
关联关系:顶点和边的关系
邻接矩阵:n个顶点,则为n×n,元素为1表示顶点间有关联
关联矩阵:n行表示n个顶点,e列表示e条边
枚举点的所有邻居
广度优先搜索
将图划分为若干种等价类(图中的环路圈),同一等价类内各顶点的边不会被采纳,连接相邻等价类顶点的边会被采纳,但是不一定会被采纳。这样能是的图划分为极大无环图,则转换为一棵树,称为支撑树,即BFS树,广度优先搜索等价于树的层次遍历,结点到根结点的最短通路为BFS树中的通路
每个顶点状态变化:UNDISCOVERED–>DISCOVERED–>VISITED
算法过程:栈实现
1.访问结点A,并将A和A的邻点状态由UNDISCOVERED改为DISCOVERED,并全部入栈
2.按一定顺序或者随机访问A的邻点B,并将A和B之间的边纳入BFS Tree。将该邻点B的状态由DISCOVERED改为VISITED,并将B的所有UNDISCOVERED的邻点入栈并该状态为DISCOVERED。
3.访问A的第二个邻点C,如此往复…以生成BFS Tree。
template<typename Tv,typename Te>
void Graph<Tv,Te>::BFS(int v,int clock){
Queue<int> Q;status(v)=DISCOVERED;Q.enqueue(v);
while(!Q.empty()){
int v= Q.dequeue();
dTime(v)=++clock;
for(int u=firstNbr(v),-1<u;u=nextNbr(v,u))//遍历v的所有邻点
{ if(status(u)=UNDISCOVERED){//若v的邻点u尚未被发现,则
status(u)=DISCOVERED;Q.enqueue(u);//发现并将结点入队,访问结点
status(v,u)=TREE;parent(u)=v;//引入树边从而构造BFS Tree
}
else{
status(v,u)=CROSS;//否则u和v之间的边归入跨边,不计入BFS Tree
}
}
status(v)= VISITED;
}
}
复杂度为O(n+e),e为边的个数
总结:(按照字母顺序)访问邻结点并入栈,访问同时将邻结点的邻结点入栈,再按照栈的顺序访问
深度优先搜索
template<typename Tv,typename Te>
void Graph<Tv,Te>::DFS(int v,int clock){
dTime(v)=++clock;
status(v)=DISCOVERED;
for(int u=firstNbr(v),-1<u;u=nextNbr(v,u))//遍历v的所有邻点
{ switch(status(u)){
case UNDISCOVERED:
status(v,u)=TREE;parent(u)=v;DFS(u,clock);break;
case DISCOVERED:
status(v,u)=BACKWORD;break;
default:
status(v,u)=dTime(v)<dTime(u)?FORWORD:CROSS;break;
}
}
status v= VISITED;
}
采用迭代的方式实现:
(1)首先选定一个未被访问过的顶点V作为起始顶点(或者访问指定的起始顶点V),并将其标记为已访问过;
(2)然后搜索与顶点V邻接的所有顶点,判断这些顶点是否被访问过,如果有未被访问过的顶点,则任选一个顶点W进行访问;再选取与顶点W邻接的未被访问过的任一个顶点并进行访问,依次重复进行。当一个顶点的所有的邻接顶点都被访问过时,则依次回退到最近被访问的顶点。若该顶点还有其他邻接顶点未被访问,则从这些未被访问的顶点中取出一个并重复上述过程,直到与起始顶点V相通的所有顶点都被访问过为止。
(3)若此时图中依然有顶点未被访问,则再选取其中一个顶点作为起始顶点并访问之,转(2)。反之,则遍历结束。
总结:
无向图:(按照字母顺序)访问邻结点,如果邻结点无未访问的邻接点则回溯
有向图:优先访问出的邻点,当访问完所有可达域后若还未访问完整个图,则再枚举其他顶点,具体实现方法是对DFS作封装,对未发现的结点再进行DFS算法