任务描述
本关任务:实现 graph.cpp 里的函数int Graph_DepthFirst(Graph*g, int start, Edge* tree)。 注意遵守约定:编号大的先进栈。
相关知识


图 2 给出了对图 1 的无向图的存储结构图:每个顶点的名称由一个字符串描述,所有字符串的起始地址组织为一个数组,数组的起始地址为vetex;顶点的相邻关系保存在相邻矩阵中,其起始地址为adj,adj[i*n+j]的值为 1 表示i号顶点到j号顶点有边,为 0 表示无边,其中n是顶点个数,i和j是顶点在顶点表中的编号。 将n,vetex,adj组织成结构:
struct Graph {int n;//顶点数char** vetex;int* adj;};
给定指向该结构的指针g,就可以对图进行操作。
深度优先遍历算法(伪代码):
DepthFirst(Graph, start)//输入Graph是图,start是开始顶点的编号//输出:tree_edge[i]=<from,to>是遍历树的一条边//tree_edge[1..n-1]为遍历树的n-1条边//tree_edge[0].to … tree_edge[n-1].to是遍历序列PUSH(<-1,start>)k=0;while(StackNotEmpty) {<a,b>=POP;if (unvisited(b)) {visit(b); //visit b, and set a flag for b.tree_edge[k++]=<a,b>; // add <a,b> to the treefor each <b,c> in the Edge Set {if (unvisited(c)) PUSH(<b,c>); //约定:编号大的先进栈}}}
对图 1 的树运行该算法的结果: 生成树的边是:{<-1,A><A,B><B,D><D,C><B,F><F,E>}; 深度优先遍历的顶点访问次序是:ABDCFE。 ####编程要求 本关任务是实现 graph.cpp 里的函数int Graph_DepthFirst(Graph*g, int start, Edge* tree)。 注意遵守约定:编号大的先进栈。
//Graph.cpp///////////////////////////////////////////////////#include <stdio.h>#include <stdlib.h>#include <string.h>#include "Graph.h"////////////////////////////////////////////////////Graph* Graph_Create(int n){Graph* g=(Graph*)malloc(sizeof(Graph));g->n=n;g->vetex=(char**)malloc(sizeof(char*)*n);int i;for (i=0; i<n; i++) g->vetex[i] = NULL;g->adj=(int*)malloc(sizeof(int)*n*n);int j;for(i=0; i<n; i++) {for(j=0; j<n; j++) {g->adj[i*n+j]=0;}}return g;}void Graph_Free(Graph* g){free(g->adj);int i;for (i=0; i<g->n; i++) free(g->vetex[i]);free(g->vetex);free(g);}int Graph_DepthFirst(Graph*g, int start, Edge* tree)//从start号顶点出发深度优先遍历,(编号从0开始)//返回访问到的顶点数,//tree[]输出遍历树//返回的tree[0]是(-1, start),//真正的遍历树保存在tree[1..return-1], return是返回值//顶点的访问次序依次为tree[0].to, tree[1].to, ..., tree[return-1].to//输入时,tree[]的长度至少为顶点数//返回值是从start出发访问到的顶点数{//在begin和end之间添加你的代码/*****begin*****//*****end*******/}
测试说明
本关的测试过程如下:
- 平台编译 step2/Main.cpp ;
- 平台运行该可执行文件,并以标准输入方式提供测试输入;
- 平台获取该可执行文件的输出,然后将其与预期输出对比,如果一致则测试通过;否则测试失败。
输入输出格式:
输入格式: 输入n,顶点数 输入n个字符串,即n个顶点的名称,其编号按输入次序是:0,...,n-1。 输入若干数字对(a b)或<a b>,(a b)表示无向边,<a b>表示有向边 输入字符x,表示边输入结束 输入一个数start,表示开始顶点的编号
输出格式: 输出生成树的边序列,边的第start个顶点构成的序列应是顶点访问序列
以下是平台对 step2/Main.cpp 的测试样例: 样例输入
6ABCDEF( 0 1 )( 0 2 )( 0 5 )( 1 3 )( 1 5 )( 2 3 )( 4 5 )x0
样例输出
tree edges: <-1,A> <A,B> <B,D> <D,C> <B,F> <F,E>visit sequence: A B D C F E
//Graph
///////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Graph.h"
/////////////////////////////////////////////////////////////
Graph* Graph_Create(int n)
{
Graph* g=(Graph*)malloc(sizeof(Graph));
g->n=n;
g->vetex=(char**)malloc(sizeof(char*)*n);
int i;
for (i=0; i<n; i++) g->vetex[i] = NULL;
g->adj=(int*)malloc(sizeof(int)*n*n);
int j;
for(i=0; i<n; i++) {
for(j=0; j<n; j++) {
g->adj[i*n+j]=0;
}
}
return g;
}
void Graph_Free(Graph* g)
{
free(g->adj);
int i;
for (i=0; i<g->n; i++) free(g->vetex[i]);
free(g->vetex);
free(g);
}
int Graph_DepthFirst(Graph*g, int start, Edge* tree)
//从start号顶点出发深度优先遍历,(编号从开始)
//返回访问到的顶点数,
//tree[]输出遍历树
//返回的tree[0]是(-1, start),
//真正的遍历树保存在tree[1..return-1], return是返回值
//顶点的访问次序依次为tree[0].to, tree[1].to, ..., tree[return-1].to
//输入时,tree[]的长度至少为顶点数
//返回值是从start出发访问到的顶点数
{
/*请在BEGIN和END之间实现你的代码*/
/*****BEGIN*****/
const int MAX=1000;
Edge queue[MAX];
int head=0, tail=0;
#define In__(a,b) {tail=tail+1; queue[tail].from=a; queue[tail].to=b;}/////////
#define Out__(a,b) {a=queue[tail].from; b=queue[tail].to; tail=tail-1;}//
#define QueueNotEmpty (head!=tail?1:0)///////////////////////////////////
#define HasEdge(i,j) (g->adj[(i)*g->n+(j)]==1)
char* visited=(char*)malloc(sizeof(char)*g->n);
memset(visited, 0, sizeof(char)*g->n);
int parent=-1;
int curr=start;
In__(parent, curr);
int k=0;
while(QueueNotEmpty)
{
Out__(parent, curr);
if((HasEdge(parent, curr)||parent==-1)&&visited[curr]!=1)
{
visited[curr]=1;
tree[k].from=parent;
tree[k].to=curr;
k++;
for(int i=g->n-1;i>=0;i--)
if(HasEdge(curr,i)&&visited[i]!=1)
In__(curr,i);
}
}
return k;
#undef In__//////////////////////////////
#undef Out__///////////////////////////////
#undef QueueNotEmpty////////////////////////
#undef HasEdge
/*****END*******/
}
625

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



