8-9 试扩充深度优先搜索算法,在遍历图的过程中建立生成森林的左子女-右兄弟链表。算
法的首部为 void Graph::DFS ( const int v, int visited [ ], TreeNode<int> * t ) 其中,指针 t
指向生成森林上具有图顶点 v 信息的根结点。(提示:在继续按深度方向从根 v 的某一未
访问过的邻接顶点 w 向下遍历之前,建立子女结点。但需要判断是作为根的第一个子女还
是作为其子女的右兄弟链入生成树。)
【解答】
为建立生成森林,需要先给出建立生成树的算法,然后再在遍历图的过程中,通过一
次次地调用这个算法,以建立生成森林。
te mplate<Type> void Graph<Type> :: DFS_Tree ( const int v, int visited [ ], TreeNode<Type> *t ) {
//从图的顶点 v 出发, 深度优先遍历图, 建立以 t (已在上层算法中建立)为根的生成树。
Visited[v] = 1; int first = 1; TreeNode<Type> * p, * q;
int w = GetFirstNeighbor ( v ); //取第一个邻接顶点
while ( w != -1 ) { //若邻接顶点存在
if ( vosited[w] == 0 ) { //且该邻接结点未访问过
p = new TreeNode<Type> ( GetValue (w) ); //建立新的生成树结点
if ( first == 1 ) //若根*t 还未链入任一子女
{ t->setFirstChild ( p ); first = 0; } //新结点*p 成为根*t 的第一个子女
else q->setNextSibling ( p ); //否则新结点*p 成为*q 的下一个兄弟
q = p; //指针 q 总指示兄弟链最后一个结点
DFS_Tree ( w, visited, q ); //从*q 向下建立子树
}
w = GetNextNeighbor ( v, w ); //取顶点 v 排在邻接顶点 w 的下一个邻接顶点
}
}
下一个算法用于建立以左子女-右兄弟链表为存储表示的生成森林。
template<Type> void Graph<Type> :: DFS_Forest ( Tree<Type> & T ) {
//从图的顶点 v 出发, 深度优先遍历图, 建立以左子女-右兄弟链表表示的生成森林 T。
T.root = NULL; int n = NumberOfVertices ( ); //顶点个数
TreeNode<Type> * p, * q;
int * visited = new int [ n ]; //建立访问标记数组
for ( int v = 0; v < n; v++ ) visited[v] = 0;
for ( v = 0; v < n; v++ ) //逐个顶点检测
if ( visited[v] == 0 ) { //若尚未访问过
p = new TreeNode<Type> ( GetValue ( v ) ); //建立新结点*p
if ( T.root == NULL ) T.root = p; //原来是空的生成森林, 新结点成为根
else q-> setNextSibling ( p ); //否则新结点*p 成为*q 的下一个兄弟
q = p;
DFS_Tree ( v, visited, p ); //建立以*p 为根的生成树
}
}
8-10 用邻接表表示图时,顶点个数设为 n,边的条数设为 e,在邻接表上执行有关图的遍历
操作时,时间代价是 O(n*e)?还是 O(n+e)?或者是 O(max(n,e))?
【解答】