节点的名字一般用数字来表示
邻接表的边只存储指向下一条边,而十字链表的边里还存储节点指针。
1 十字链表用来存储DG,可以看成邻接矩阵的链式存储结构,其实就是拓展了一下邻接表,原来邻接表的一个顶点对应的链表只存储该顶点出发指向的边,现在增加一个域来存储以该顶点为终点的边的点.
2.邻接多重表用来存储UDG
表示边的结构field:mark(是否被搜索过),ivex(顶点i的编号),ilik(指向下一条依附于ivex的边),jvex(顶点j的编号),jlink(指向下一条依附于ivex的边),info()
表示顶点的结构:field data,firstedge(指向依附于该顶点的第一条边)
所有依附于同一个顶点中的边串联在同一个链表中,由于每条边依附于两个顶点,因此每条边出现两次,分别在两个链表中。对于UDG,其邻接多重表和邻接表的区别在于同一条边在邻接表中用两个节点表示,而在邻接多重表中只出现一次。
图的所有存储结构在进行遍历时都会造成节点重复访问,因此会无穷递归,解决的办法是设置标记来记录某个节点是否被访问过。
生成树与生成森林,可能进行完一次DFS后还存在没有被遍历的点,因此就不是一颗生成树,而是生成森林。
深度优先和回溯的区别在于:在深入叶子节点层次加深的过程中,DFS不断输出节点,而回溯是递归到叶子节点往回走的过程中才输出叶子节点。
DFS 代码
bool vistited[MAX];
Status(*visitFunc)(int) 函数指针用来表示对节点的访问方法
void DFSTraverse(Graph G, Status(*visit)(int v))// 函数指针传入访问方法
{
VisitFunc=visit; //全局函数指针被赋值为传入的函数名
for(v=0;v<G.vexnum;++v) visted[v]=false;
for(v=0;v<G.vexnum;++v)
if(!visited[v]) DFS(G,v);
}
递归函数
void DFS(Graph G,int v) // v为节点的名字
{
visited[v]=true;
visitFunc(v); // 用传入的方式来访问该节点,v为该节点的名字,可以随机访问
for(w=firstAdjvex(G,V);w>=0;w=NextAdjvex(G,v,w))
//函数firstAdjvex(G,v)在图G中根据顶点名字v来找到与其相连的第一个顶点
//函数nextAdjvex(G,v,w)在图G中根据顶点名字v来找到与其相连的w顶点(w为该顶点的名字)后的哪个顶点
//v->arc1(w)->p
}
DFS的复杂度分析:
如若用邻接矩阵,则查找所有节点的邻接点需要O(n^2),n为顶点的个数
如果用邻接表,则查找所有节点的邻接点需要O(e)(因为一个节点被访问过后就不会再被访问了,所以访问过的边访问一次就少一个),DFS需要的时间为O(n+e),n为顶点的个数
本文详细介绍了图的深度优先搜索(DFS)在邻接表、十字链表和邻接多重表中的实现。讲解了DFS遍历过程中如何避免节点重复访问,并探讨了生成树、生成森林的概念。此外,还分析了DFS的时间复杂度,指出在邻接矩阵和邻接表中查找邻接点的不同效率。
923

被折叠的 条评论
为什么被折叠?



