# 算法设计与分析—第五章搜索法作业-必做：图的宽度优先搜索与深度优先搜索(头歌实验)

19 篇文章 11 订阅

## 第1关：实现图的宽度优先遍历

1. struct Graph {
2. int n;//顶点数
3. char** vetex;
4. int* adj;
5. };

1. WidthFirst(Graph, start)
2. //输入Graph是图，start是开始顶点的编号
3. //输出：tree_edge[i]=<from,to>是遍历树的一条边
4. //tree_edge[1..n-1]为遍历树的n-1条边
5. //tree_edge[0].to … tree_edge[n-1].to是遍历序列
6. QueueIn(<-1,start>)
7. k=0;
8. while(QueueNotEmpty) {
9. <a,b>=QueueOut;
10. if (unvisited(b)) {
11. visit(b); // visit b, and set a flag for b.
12. tree_edge[k++]=<a,b>; // add <a,b> to the tree
13. for each <b,c> in the Edge Set {
14. if (unvisited(c)) QueueIn(<b,c>); //约定：编号小的先入队列
15. }
16. }
17. }

1. //Graph.cpp
2. ///
3. #include <stdio.h>
4. #include <stdlib.h>
5. #include <string.h>
6. #include "Graph.h"
7. //
8. Graph* Graph_Create(int n)
9. {
10. Graph* g=(Graph*)malloc(sizeof(Graph));
11. g->n=n;
12. g->vetex=(char**)malloc(sizeof(char*)*n);
13. int i;
14. for (i=0; i<n; i++) g->vetex[i] = NULL;
15. g->adj=(int*)malloc(sizeof(int)*n*n);
16. int j;
17. for(i=0; i<n; i++) {
18. for(j=0; j<n; j++) {
19. g->adj[i*n+j]=0;
20. }
21. }
22. return g;
23. }
24. void Graph_Free(Graph* g)
25. {
26. free(g->adj);
27. int i;
28. for (i=0; i<g->n; i++) free(g->vetex[i]);
29. free(g->vetex);
30. free(g);
31. }
32. int Graph_WidthFirst(Graph*g, int start, Edge* tree)
33. //从start号顶点出发宽度优先遍历，（编号从0开始）
34. //返回访问到的顶点数，
35. //tree[]输出遍历树
36. //返回的tree[0]是(-1, start),
37. //真正的遍历树保存在tree[1..return-1], return是返回值
38. //顶点的访问次序依次为tree[0].to, tree[1].to, ..., tree[return-1].to
39. //输入时，tree[]的长度至少为顶点数
40. //返回值是从start出发访问到的顶点数
41. {
42. const int MAX=1000;
43. Edge queue[MAX];
44. int head=0, tail=0;
45. #define In__(a,b) {queue[tail].from=a; queue[tail].to=b; tail=(tail+1)%MAX;}/
46. #define Out__(a,b) {a=queue[head].from; b=queue[head].to; head=(head+1)%MAX;}//
47. #define QueueNotEmpty (head!=tail?1:0)///
48. #define HasEdge(i,j) (g->adj[(i)*g->n+(j)]==1)
49. char* visited=(char*)malloc(sizeof(char)*g->n);
50. memset(visited, 0, sizeof(char)*g->n);
51. int parent=-1;
52. int curr=start;
53. In__(parent, curr);
54. int k=0; //已经访问的结点数
55. //在begin和end之间实现你的代码
56. /*****Begin*****/
57. /*****End*****/
58. free(visited);
59. return k;
60. #undef In__//
61. #undef Out__///
62. #undef QueueNotEmpty
63. #undef HasEdge
64. }

1. 平台编译 step1/Main.cpp ；
2. 平台运行该可执行文件，并以标准输入方式提供测试输入；
3. 平台获取该可执行文件的输出，然后将其与预期输出对比，如果一致则测试通过；否则测试失败。

1. 6
2. A
3. B
4. C
5. D
6. E
7. F
8. ( 0 1 )
9. ( 0 2 )
10. ( 0 5 )
11. ( 1 3 )
12. ( 1 5 )
13. ( 2 3 )
14. ( 4 5 )
15. x
16. 0

1. tree edges: <-1,A> <A,B> <A,C> <A,F> <B,D> <F,E>
2. 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;
int j;
for(i=0; i<n; i++) {
for(j=0; j<n; j++) {
}
}
return g;
}

void Graph_Free(Graph* g)
{
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];
#define In__(a,b)  {queue[tail].from=a; queue[tail].to=b; tail=(tail+1)%MAX;}

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*****/
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
}

## 第2关：实现图的深度优先遍历

1. struct Graph {
2. int n;//顶点数
3. char** vetex;
4. int* adj;
5. };

1. DepthFirst(Graph, start)
2. //输入Graph是图，start是开始顶点的编号
3. //输出：tree_edge[i]=<from,to>是遍历树的一条边
4. //tree_edge[1..n-1]为遍历树的n-1条边
5. //tree_edge[0].to … tree_edge[n-1].to是遍历序列
6. PUSH(<-1,start>)
7. k=0;
8. while(StackNotEmpty) {
9. <a,b>=POP;
10. if (unvisited(b)) {
11. visit(b); //visit b, and set a flag for b.
12. tree_edge[k++]=<a,b>; // add <a,b> to the tree
13. for each <b,c> in the Edge Set {
14. if (unvisited(c)) PUSH(<b,c>); //约定：编号大的先进栈
15. }
16. }
17. }

1. //Graph.cpp
2. ///
3. #include <stdio.h>
4. #include <stdlib.h>
5. #include <string.h>
6. #include "Graph.h"
7. Graph* Graph_Create(int n)
8. {
9. Graph* g=(Graph*)malloc(sizeof(Graph));
10. g->n=n;
11. g->vetex=(char**)malloc(sizeof(char*)*n);
12. int i;
13. for (i=0; i<n; i++) g->vetex[i] = NULL;
14. g->adj=(int*)malloc(sizeof(int)*n*n);
15. int j;
16. for(i=0; i<n; i++) {
17. for(j=0; j<n; j++) {
18. g->adj[i*n+j]=0;
19. }
20. }
21. return g;
22. }
23. void Graph_Free(Graph* g)
24. {
25. free(g->adj);
26. int i;
27. for (i=0; i<g->n; i++) free(g->vetex[i]);
28. free(g->vetex);
29. free(g);
30. }
31. int Graph_DepthFirst(Graph*g, int start, Edge* tree)
32. //从start号顶点出发深度优先遍历，（编号从0开始）
33. //返回访问到的顶点数，
34. //tree[]输出遍历树
35. //返回的tree[0]是(-1, start),
36. //真正的遍历树保存在tree[1..return-1], return是返回值
37. //顶点的访问次序依次为tree[0].to, tree[1].to, ..., tree[return-1].to
38. //输入时，tree[]的长度至少为顶点数
39. //返回值是从start出发访问到的顶点数
40. {
41. //在begin和end之间添加你的代码
42. /*****begin*****/
43. /*****end*******/
44. }

1. 平台编译 step2/Main.cpp ；
2. 平台运行该可执行文件，并以标准输入方式提供测试输入；
3. 平台获取该可执行文件的输出，然后将其与预期输出对比，如果一致则测试通过；否则测试失败。

1. 6
2. A
3. B
4. C
5. D
6. E
7. F
8. ( 0 1 )
9. ( 0 2 )
10. ( 0 5 )
11. ( 1 3 )
12. ( 1 5 )
13. ( 2 3 )
14. ( 4 5 )
15. x
16. 0

1. tree edges: <-1,A> <A,B> <B,D> <D,C> <B,F> <F,E>
2. 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;
int j;
for(i=0; i<n; i++) {
for(j=0; j<n; j++) {
}
}
return g;
}

void Graph_Free(Graph* g)
{
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 stack[MAX];
int top=-1;
#define In__(a,b)  {top++;stack[top].from=a; stack[top].to=b;}
#define Out__(a,b)  {a=stack[top].from; b=stack[top].to;top--;}
#define StackNotEmpty (top>=0?1:0)
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(StackNotEmpty)
{
Out__(parent, curr);
if (visited[curr])
continue;
visited[curr]=1;
tree[k].from=parent;
tree[k].to=curr;
k++;
int j;
for(j=g->n-1;j>=0;j--)
{
if(HasEdge(curr,j)&&!visited[j])
In__(curr,j);
}
}
return k;
#undef In__
#undef Out__
#undef QueueNotEmpty
#undef HasEdge

/*****END*******/
}

• 7
点赞
• 2
收藏
觉得还不错? 一键收藏
• 打赏
• 0
评论
03-04
08-21 692
01-16 626
03-14 223
04-29 3085
12-17 2902
04-17 4万+
11-30 1万+
05-28 6207
09-18 182

### “相关推荐”对你有帮助么？

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

@单纯很吃货

¥1 ¥2 ¥4 ¥6 ¥10 ¥20

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、付费专栏及课程。