一.图的算法


邻接矩阵表示的数据结构

 1 #define INFINITY INT_MAX // 无穷大
2 #define MAX_VERTEX_NUM 20 // 限制顶点最大数值为20个
3 #define MAX_ARC_NUM MAX_VERTEX_NUM * (MAX_VERTEX_NUM - 1) // 由n个顶点,最多可以确定n(n-2)/2条直线,有向图为2倍
4 #define MAX_INFO 20 // 用户输入的弧信息,最多20个字符
5
6 /*数组表示法*/
7 typedef int VRType;
8 typedef char InfoType;
9 typedef char VertexType[5];
10 typedef enum {DG, DN, UDG, UDN} GraphKind;
11
12 typedef struct ArcCell {
13 VRType adj;
14 InfoType *info;
15 }ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
16
17 typedef struct {
18 VertexType vexs[MAX_VERTEX_NUM];
19 AdjMatrix arcs;
20 int vexnum, arcnum;
21 }MGraph;

邻接表表示的数据结构

 1 /*邻接表表示法*/
2 typedef struct ArcNode
3 {
4 int adjvex;
5 int w; // 存储权值,书中的程序没有表示权值的数据成员(书中说用info来存储权值,但是上面的程序又是单独用的adj存权值,为了一致性,info还是用来存储其他信息算了)
6 struct ArcNode *nextarc;
7 InfoType *info; // 用来存储权值以外的有关弧的信息
8 }ArcNode;
9
10 typedef struct VNode
11 {
12 VertexType data;
13 ArcNode *firstarc;
14 }VNode, AdjList[MAX_VERTEX_NUM];
15
16 typedef struct
17 {
18 AdjList vertices;
19 int vexnum, arcnum;
20 int kind;
21 }ALGraph;

1.写出从图的邻接表表示转换成邻接矩阵表示的算法

1 void Convert( ALGraph G, int arcs[][10] )
2 {
3 for ( int v = 0; v < G.vexnum; v++ )
4 for ( ArcNode* p = G.vertices[v].firstarc; p; p->nextarc )
5 arcs[v][p->adjvex] = 1;
6 }

二.图的遍历


说明: 以下图的算法既可以使用邻接矩阵的方式也可以使用邻接表存储的方式,因此每种算法都可以换成另一种存储形式,只需要把MGraph(邻接矩阵存储)换成ALGraph(邻接表存储)即可

基本数据结构:

邻接矩阵下,通用找邻接的函数:

 1 // 第一个邻居
2 int FirstNeighbor( MGraph G, int v)
3 {
4 for ( int i = 0; i < G.vexnum; i++ )
5 if ( G.arcs[v][i] == 1 )
6 return i;
7 return -1;
8 }
9 // 当前的下一个邻居
10 int NextNeighbor( MGraph G, int v, int w )
11 {
12 for (int i = w+1; i < G.vexnum; i++ )
13 if ( G.arcs[v][i] == 1 )
14 return i;
15 return -1;
16 }

邻接表下,通用找邻接的函数:

 1 /*全局变量*/
2 bool Visited[MAX_VERTEX_NUM]; // 记录每个顶点是否被访问过
3
4 // 找到第一个v相邻的顶点,返回它的下标
5 int FirstAdjVex(ALGraph &AL, int v)
6 {
7 ArcNode *p = NULL;
8 p = AL.vertices[v].firstarc;
9 if (p == NULL)
10 return -1;
11 else
12 return p->adjvex;
13 }
14
15 // 找到下一个与v相邻的顶点,返回它的下标
16 int NextAdjVex(ALGraph &AL, int v, int w)
17 {
18 ArcNode *p = NULL;
19 p = AL.vertices[v].firstarc;
20 while (p->adjvex != w) // 找到下标为w的结点
21 p = p->nextarc;
22 p = p->nextarc; // 指针指向下标为w的结点的后面一个结点
23 if (p == NULL)
24 return -1;
25 else
26 return p->adjvex;
27 }

1.广度优先搜索(Breadth-First-Search, BFS)

法一:采用邻接矩阵

 1 bool visited[MAX_VERTEX_NUM] = { false };
2 void BFS( MGraph G, int v );
3
4 void BFSTraverse( MGraph G )
5 {
6 int Q[MAXSIZE];
7 int front = -1, rear = -1;
8 for (int v = 0; v < G.vexnum; v++ )
9 if ( !visited[v] )
10 BFS( G, v );
11 }
12
13 void BFS( MGraph G, int v )
14 {
15 int Q[MAXSIZE];
16 int front = -1, rear = -1;
17 // BFS顶点三连
18 visit( v );
19 visited[v] = true;
20 Q[++rear] = v;
21
22 while ( front != rear )
23 {
24 v = Q[++front];
25 for ( int w = FirstNeighbor( G, v ); w >= 0; w = NextNeighbor( G, v, w ) )
26 {
27 if (!visited[w])
28 {
29 // BFS顶点三连
30 visit( w );
31 visited[w] = true;
32 Q[++rear] = w;
33 }
34 }
35 }
36 }

法二:采用邻接表

 1 bool visited[MAX_VERTEX_NUM] = { false };
2 void BFS( ALGraph G, int v );
3
4 void BFSTraverse( ALGraph G )
5 {
6 int Q[MAXSIZE];
7 int front = -1, rear = -1;
8 for (int v = 0; v < G.vexnum; v++ )
9 if ( !visited[v] )
10 BFS( G, v );
11 }
12
13 void BFS( ALGraph G, int v )
14 {
15 int Q[MAXSIZE];
16 int front = -1, rear = -1;
17 // BFS顶点三连
18 visit( v );
19 visited[v] = true;
20 Q[++rear] = v;
21
22 while ( front != rear )
23 {
24 v = Q[++front];
25 for ( int w = FirstNeighbor( G, v ); w >= 0; w = NextNeighbor( G, v, w ) )
26 {
27 if (!visited[w])
28 {
29 // BFS顶点三连
30 visit( w );
31 visited[w] = true;
32 Q[++rear] = w;
33 }
34 }
35 }
36 }

2.BFS算法求解单源最短路径问题

 1 bool visited[MAXSIZE] = { false };
2 unsigned int d[MAXSIZE] = { INFINITE };
3 void BFS_MIN_Distance( ALGraph G, int u )
4 {
5 BiTree Q[MAXSIZE];
6 int front = -1, rear = -1, v, w;
7 // BFS路径三连
8 d[u] = 0;
9 visited[u] = true;
10 Q[++rear] = u;
11
12 while ( front != rear )
13 {
14 v = Q[++front];
15 for ( w = FirstNeighbor( G, v ); w >= 0; w = NextNeighbor( G, v, w ) )
16 {
17 if (!visited[w])
18 {
19 // BFS路径三连
20 d[w] = d[v] + 1;
21 visited[w] = true;
22 Q[++rear] = w;
23 }
24 }
25 }
26 }

3.深度优先搜索(Depth-First-Search, DFS)

 1 bool visited[MAX_VERTEX_NUM] = { false };
2 void DFS( ALGraph &G, int v );
3
4 void DFSTraverse( ALGraph &G )
5 {
6 for ( int v = 0; v < G.vexnum; v++ )
7 if ( !visited[v] )
8 DFS( G, v );
9 }
10
11 void DFS( ALGraph &G, int v )
12 {
13 visit( v );
14 visited[v] = true;
15 for ( int w = FirstNeighbor( G, v ); w >= 0; w = NextNeighbor( G, v, w ) )
16 if ( !visited[w] )
17 DFS( G, w );
18 }

4.设计一个算法,判断一个无向图G是否为一棵树

 1 int visited[MAXSIZE] = { 0 };
2 void DFS( MGraph G, int v, int& Vnum, int& TD );
3
4 bool IsTree( MGraph G )
5 {
6 int Vnum = 0, TD = 0; // TD=total degree总度数
7 DFS( G, 0, Vnum, TD ); // 从第一个顶点开始遍历
8 if ( Vnum == G.vexnum&&TD == 2 * ( G.vexnum - 1 ) )
9 return true;
10 return false;
11 }
12
13 void DFS( MGraph G, int v, int& Vnum, int& TD )
14 {
15 visited[v] = true; Vnum++;
16 for ( int w = FirstNeighbor( G, v ); w >= 0; w = NextNeighbor( G, v, w ) )
17 if ( !visited[w] )
18 DFS( G, w, Vnum, TD );
19 }

5.写出图的深度优先搜索DFS算法的非递归算法

 1 bool visited[MAXSIZE] = { false };
2 void DFS_NON_RC( MGraph G, int v )
3 {
4 int S[MAXSIZE];
5 int top = -1;
6 for ( int i = 0; i < G.vexnum; i++ )
7 visited[i] = false;
8 // 顶点二连
9 visited[v] = true;
10 S[++top] = v;
11
12 while ( top != -1 )
13 {
14 v = S[top--]; visit( v );
15 for ( int w = FirstNeighbor( G, v ); w >= 0; w = NextNeighbor( G, v, w ) )
16 if ( !visited[w] )
17 {
18 // 顶点二连
19 visited[w] = true;
20 S[++top] = w;
21 }
22 }
23 }

6.分别采用基于广度优先遍历和深度优先遍历算法判别以邻接表或邻接矩阵存储的有向图中是否存在由顶点v到顶点u的路径($v\neq u$)

// 采用BFS的方法
bool visited[MAXSIZE] = { false };
bool Exist_Path_BFS( MGraph G, int v, int u )
{
int Q[MAXSIZE];
int front = -1, rear = -1;
visited[v] = true;
Q[++rear] = v;
while ( front != rear )
{
v = Q[++front];
for ( int w = FirstNeighbor( G, v ); w >= 0; w = NextNeighbor( G, v, w ) )
{
if (!visited[w])
{
if ( w == u ) return true;
visited[w] = true;
Q[++rear] = w;
}
}
}
return false;
}
 1 // 采用DFS的方法
2 bool visited[MAXSIZE] = { false };
3 bool Exist_Path_DFS( MGraph G, int v, int u )
4 {
5 if ( v == u ) return true;
6 visited[v] = true;
7 for ( int w = FirstNeighbor( G, v ); w >= 0; w = NextNeighbor( G, v, w ) )
8 {
9 if ( !visited[w] )
10 {
11 if ( Exist_Path_DFS( G, w, u ) ) return true;
12 }
13 }
14 return false;
15 }

7.拓扑排序:判断并输出有向图的拓扑序列

 1 bool Topological( MGraph G, int indegree[] )
2 {
3 int S[MAXSIZE];
4 int top = -1, Vnum = 0, v = 0;
5 for ( v = 0; v < G.vexnum; v++ )
6 {
7 if ( indegree[v] == 0 )
8 {
9 visit( v );
10 Vnum++;
11 S[++top] = v;
12 }
13 }
14 while ( top != -1 )
15 {
16 v = S[top--];
17 for ( int w = FirstNeighbor( G, v ); w >= 0; w = NextNeighbor( G, v, w ) )
18 {
19 indegree[w]--;
20 if ( indegree[w] == 0 )
21 {
22 visit( w );
23 Vnum++;
24 S[++top] = w;
25 }
26 }
27 }
28 if ( Vnum == G.vexnum )
29 return true;
30 return false;
31 }

2.拓扑排序(DFS):有向无环图的拓扑排序

 1 bool visited[MAXSIZE] = { false };
2 int time = 0, finishTime[MAXSIZE] = { 0 };
3 void DFS( MGraph G, int v );
4
5 void Topological_DFS( MGraph G )
6 {
7 for ( int v = 0; v < G.vexnum; v++ )
8 if ( !visited[v] )
9 DFS( G, v );
10 for ( int t = time - 1; t >= 0; t-- )
11 visit( finishTime[t] );
12 }
13
14 void DFS( MGraph G, int v )
15 {
16 visited[v] = true;
17 for ( int w = FirstNeighbor( G, v ); w >= 0; w = NextNeighbor( G, v, w ) )
18 if ( !visited[w] )
19 DFS( G, w );
20 finishTime[time++] = v;
21 }

最新文章

  1. centos6环境下搭建irc服务器
  2. HDU 4314 Save the dwarfs (DP) ---转载
  3. 《理解 ES6》阅读整理:函数(Functions)(二)Unnamed Parameters
  4. 字符编码浅识:关于Unicode与UTF-8
  5. 微信浏览器如何禁止iPhone手机上下滑动网页
  6. button按钮在IE6、7、8、9、10中处理方式并不相同[转]
  7. cf B. I.O.U.
  8. Lintcode--009(单词切分)
  9. Django 模板中引用静态资源(js,css等)
  10. Codeforces Round #256 (Div. 2) D. Multiplication Table(二进制搜索)
  11. 数据市中心全省中国mysql脚本
  12. Spring注解定时器使用
  13. SQLSERVER列出所有用户权限
  14. (23)socket多进程并发
  15. ZooKeeper Administrator&#39;s Guide A Guide to Deployment and Administration(吃别人嚼过的馍没意思,直接看官网资料)
  16. mybatis插入一个对象后获取表中自增的主键Id并且传入到插入的的对象中,方便将对象中其他属性赋值给其他以前表主键Id作为非空字段的表
  17. Linux报错:bash: pip: command not found
  18. python ctypes 探究 ---- python 与 c 的交互
  19. shiro+SpringMVC 项目 配置404页面
  20. 《GPU高性能编程CUDA实战》第六章 常量内存

热门文章

  1. php中的list方法
  2. 七 Kafka Streams VS Consumer API
  3. ubuntu 14.04使用root登陆出现错误“Error found when loading /root/.profile”解决
  4. WP10通过StreamSocket连接C++服务器
  5. MyBatis多表映射demo
  6. HTTP直接请求webService
  7. System.Security.Cryptography.CryptographicException: 出现了内部错误。
  8. java中FILE类常用API介绍
  9. 如何判定Unity已破解成功
  10. Game Develop Books