赞
踩
任务描述
本关任务:请你实现 graph.cpp 里的int Graph_WidthFirst(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
,就可以对图进行操作。
宽度优先遍历算法(伪代码):
WidthFirst(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是遍历序列
QueueIn(<-1,start>)
k=0;
while(QueueNotEmpty) {
<a,b>=QueueOut;
if (unvisited(b)) {
visit(b); // visit b, and set a flag for b.
tree_edge[k++]=<a,b>; // add <a,b> to the tree
for each <b,c> in the Edge Set {
if (unvisited(c)) QueueIn(<b,c>); //约定:编号小的先入队列
}
}
}
对图1运行该算法的结果: 生成树的边是:<-1,A> <A,B> <A,C> <A,F> <B,D> <F,E>
; 宽度优先遍历的顶点访问次序是:A B C F D E。
编程要求
请你实现graph.cpp
里的int Graph_WidthFirst(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_WidthFirst(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出发访问到的顶点数
{
const int MAX=1000;
Edge queue[MAX];
int head=0, tail=0;
#define In__(a,b) {queue[tail].from=a; queue[tail].to=b; tail=(tail+1)%MAX;}/
#define Out__(a,b) {a=queue[head].from; b=queue[head].to; head=(head+1)%MAX;}//
#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; //已经访问的结点数
//在begin和end之间实现你的代码
/*****Begin*****/
/*****End*****/
free(visited);
return k;
#undef In__//
#undef Out__///
#undef QueueNotEmpty
#undef HasEdge
}
测试说明
本关的测试过程如下:
输入输出格式说明:
输入格式: 输入n
,顶点数; 输入n
个字符串,即n
个顶点的名称,其编号按输入次序是,0,...,n-1
; 输入若干数字对(a b)或<a b>
,(a b)
表示无向边,<a b>
表示有向边; 输入字符x
,表示边输入结束; 输入一个数start
,表示开始顶点的编号。
输出格式: 输出生成树的边序列,边的第start
个顶点构成的序列应是顶点访问序列。
以下是平台对 step1/Main.cpp 的测试样例: 样例输入
6
A
B
C
D
E
F
( 0 1 )
( 0 2 )
( 0 5 )
( 1 3 )
( 1 5 )
( 2 3 )
( 4 5 )
x
0
样例输出
tree edges: <-1,A> <A,B> <A,C> <A,F> <B,D> <F,E>
visit sequence: A B C F D 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_WidthFirst(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出发访问到的顶点数
- {
- const int MAX=1000;
- Edge queue[MAX];
- int head=0, tail=0;
- #define In__(a,b) {queue[tail].from=a; queue[tail].to=b; tail=(tail+1)%MAX;}/
- #define Out__(a,b) {a=queue[head].from; b=queue[head].to; head=(head+1)%MAX;}//
- #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);//memset:作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法
-
- int parent=-1;
- int curr=start;
- In__(parent, curr);
- int k=0; //已经访问的结点数
- /*请在BEGIN和END之间实现你的代码*/
- /*****BEGIN*****/
- while(QueueNotEmpty)
- {
- Out__(parent,curr);//out是输出值,不需要预先给他值,当函数执行完毕后可以从这个变量获取输出的数据
- if(visited[curr])
- continue;
- visited[curr]=1;
- tree[k].from=parent;
- tree[k].to=curr;
- k++;
- int j;
- for(j=0;j<g->n;j++)
- {
- if(HasEdge(curr,j)&&!visited[j])
- In__(curr,j);
- }
- }
- /*****END*******/
- return k;
- #undef In__//
- #undef Out__///
- #undef QueueNotEmpty
- #undef HasEdge
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。