【数据结构】图的基本操作——图的构造(邻接矩阵,邻接表),遍历(DFS,BFS)

邻接矩阵实现如下:

/*
主题:用邻接矩阵实现 DFS(递归) 与 BFS(非递归)
作者:Laugh
语言:C++

*******************************************
样例输出如下:
请选择图的类型(a - 无向图, b - 有向图):a
请输入总顶点数,总边数:8 9
请依次输入点的信息:a b c d e f g h
输入一条边依附的顶点及权值 (eg: a b 6): 
a b 1
a c 1
b d 1
b e 1
d h 1
e h 1
c f 1
c g 1
f g 1
打印邻接矩阵:
0 1 1 0 0 0 0 0
1 0 0 1 1 0 0 0
1 0 0 0 0 1 1 0
0 1 0 0 0 0 0 1
0 1 0 0 0 0 0 1
0 0 1 0 0 0 1 0
0 0 1 0 0 1 0 0
0 0 0 1 1 0 0 0
请选择遍历方式(1.深度优先搜索; 2.广度优先搜索):
1
DFS:a b d h e c f g

BFS: a b c d e f g h
*/
#include <iostream>
#include <queue>

using namespace std;

#define OK 1 
typedef int Status; 

/* ————图的邻接矩阵存储表示 ————*/
#define MaxInt 32767                                  // 表示极大值
#define MVNum  100                                    // 最大顶点数
bool visited[MVNum];                                  // 访问标志数组,其初值为 “false”
typedef char VerTexType;                              // 假设顶点的数据类型为字符型
typedef int  ArcType;                                 // 假设边的权值类型为整型
typedef struct {
	VerTexType vexs[MVNum];                           // 顶点表
	ArcType arcs[MVNum][MVNum];                       // 邻接矩阵
	int vexnum, arcnum;                               // 图的当前点数和边数 
} AMGraph;

int LocateVex(AMGraph G, VerTexType u) {
	/* 存在则返回 u 在顶点表中的下标;否则返回 -1 */
	for (int i = 0; i < G.vexnum; i++)
		if (u == G.vexs[i])
			return i;
			
	return -1;	
} 

/* ————采用邻接矩阵表示法创建无向网 ————*/
Status CreateUDN(AMGraph &G) {
	int i, j, k;
	char flag;
	ArcType w;
	VerTexType v1, v2;
	
	cout << "请选择图的类型(a - 无向图, b - 有向图):";
	cin >> flag;
	cout << "请输入总顶点数,总边数:";
	cin >> G.vexnum >> G.arcnum;                      // 输入总顶点数,总边数
	cout << "请依次输入点的信息:"; 
	for (i = 0; i < G.vexnum; i++)                    // 依次输入点的信息
		cin >> G.vexs[i];
	for (i = 0; i < G.vexnum; i++)                    // 初始化邻接矩阵,边的权值均置为极大值 MaxInt
		for (j = 0; j < G.vexnum; j++)
			G.arcs[i][j] = MaxInt;
			
	cout << "输入一条边依附的顶点及权值 (eg: a b 6): " << endl;
	for (k = 0; k < G.arcnum; k++) {                  // 构造邻接矩阵 
		cin >> v1 >> v2 >> w;                         // 输入一条边依附的顶点及权值 
		i = LocateVex(G, v1); j = LocateVex(G, v2);   // 确定 v1 和 v2 在 G 中的位置,即顶点数组的下标
		G.arcs[i][j] = w;                             // 边 <v1, v2> 的权值为 w
		if (flag == 'a')
			G.arcs[j][i] = G.arcs[i][j];              // 置 <v1, v2> 的对称边 <v2, v1> 的权值为 w 
	}
	return OK; 
} 

/* 返回顶点v的第一个邻接顶点序号 */
int FirstAdjVex(AMGraph G, int v) {
	for(int i = 0; i < G.vexnum; i++)
		if(G.arcs[v][i] == 1)
			return i;
	return -1;
}
 
/* 返回顶点v的相对于w的下一个邻接顶点序号 */
int NextAdjVex(AMGraph G, int v, int w) {
	for(int i = w + 1; i < G.vexnum; i++)
		if(G.arcs[v][i] == 1)
			return i;
	return -1;
}


void DFS(AMGraph G, int v) {
	visited[v]=true;
	cout<<G.vexs[v]<<" ";
	for(int w=FirstAdjVex(G, v); w>=0; w=NextAdjVex(G, v, w))
		if(!visited[w])
			DFS(G, w);
}

/* 深搜 */
void DFSTraverse(AMGraph G) {
	for(int i = 0; i < G.vexnum; i++)
		visited[i] = false;
 
	for(int i = 0; i < G.vexnum; i++)
		if(!visited[i])
			DFS(G, i);
}

/* 广搜,类似于树的层次遍历 */
void BFSTraverse(AMGraph G) {
	for(int i = 0; i < G.vexnum; i++)
		visited[i] = false;
 
	queue<int> q;
 
	for(int i = 0; i < G.vexnum; i++) {
		if(!visited[i]) {
			visited[i] = true;
			q.push(i);
			
			while(!q.empty()) {
				int v = q.front();
				q.pop();
				
				cout << G.vexs[v] << " ";
				for(int w = FirstAdjVex(G, v); w >= 0; w = NextAdjVex(G, v, w)) {
					if(!visited[w]) {
						visited[w] = true;
						q.push(w);
					}
				}
			}
		}
	}
}

int main() {
	AMGraph G;
	
	CreateUDN(G);
	
	cout << "打印邻接矩阵:" << endl;
	for (int i = 0; i < G.vexnum; i++) {
		for (int j = 0; j < G.vexnum; j++) {
			if (G.arcs[i][j] != MaxInt)
				cout << G.arcs[i][j] << " ";
			else cout << '0' << " ";
		}
		cout << endl;
	}
	
	int flag;
	cout << "请选择遍历方式(1.深度优先搜索; 2.广度优先搜索):\n"; 
	cin >> flag;
	
	switch(flag) {
		case 1:
			cout << "DFS:";
			DFSTraverse(G);
			cout << endl;
			break;
		case 2:
		 	cout << "BFS:";
			BFSTraverse(G);
			cout << endl;
	}
	
	return 0;
}

邻接表实现如下:

/*
主题:用邻接表实现 DFS(递归) 与 BFS(非递归)
作者:Laugh
语言:C++

*******************************************
样例输出如下:
请输入顶点数和边数:8 9
请输入顶点:v1 v2 v3 v4 v5 v6 v7 v8
请输入边:
v1 v2
v1 v3
v2 v4
v2 v5
v4 v8
v5 v8
v3 v6
v3 v7
v6 v7
打印邻接表如下:
v1->v3->v2
v2->v5->v4->v1
v3->v7->v6->v1
v4->v8->v2
v5->v8->v2
v6->v7->v3
v7->v6->v3
v8->v5->v4 
请选择遍历方式(1.深度优先搜索; 2.广度优先搜索):1
DFS:v1 v3 v7 v6 v2 v5 v8 v4 
BFS: v1 v3 v2 v7 v6 v5 v4 v8
*/
#include <iostream>
#include <string>
#include <queue>
using namespace std;
 
bool visited[10];
/* 表结点 */ 
typedef struct ArcNode {
	int adjvex;                 // 该弧所指向的顶点的位置
	ArcNode *nextarc;           // 指向下一条弧的指针
} ArcNode;
 
/* 头结点 */ 
typedef struct VNode {
	string data;                // 顶点信息
	ArcNode* firstarc;          // 第一个表结点的地址,指向第一条依附该顶点的弧的指针
} VNode, AdjList[10];
 
typedef struct {
	AdjList vertices;
	int vexnum, arcnum;         // 图的顶点数和弧数
} ALGraph;
 
/* 返回顶点u在图中的位置 */ 
int LocateVex(ALGraph G, string u) {
	for(int i = 0; i < G.vexnum; i++)
		if(G.vertices[i].data == u)
			return i;
	return -1;
}
 
/* 构造无向图 */ 
void CreateUDG(ALGraph &G) {
	string v1, v2;
	int i, j, k;
	
	cout << "请输入顶点数和边数:";
	cin >> G.vexnum >> G.arcnum;
 
	cout << "请输入顶点:";
	for(i = 0; i < G.vexnum; i++) {
		cin >> G.vertices[i].data;
		G.vertices[i].firstarc = NULL;
	}
 
	cout << "请输入边:";
	cout << endl;
	for(k = 0; k < G.arcnum; k++) {
		cin >> v1 >> v2;
		i = LocateVex(G, v1);
		j = LocateVex(G, v2);
 
		/* 插入v1的邻接表,为了提高效率,总在表头插入结点 */ 
		ArcNode *arc = new ArcNode;
		arc->adjvex = j;
		arc->nextarc = G.vertices[i].firstarc;
		G.vertices[i].firstarc = arc;
 
		/* 插入v2的邻接表,为了提高效率,总在表头插入结点 */ 
        arc = new ArcNode;
		arc->adjvex = i;
		arc->nextarc = G.vertices[j].firstarc;
		G.vertices[j].firstarc = arc;
	}
}
 
/* 打印邻接表 */ 
void Print(ALGraph G) {
	cout<<"打印邻接表如下:" << endl;
	
	
	/* 遍历每个顶点的邻接表 */ 
	for(int i = 0; i < G.vexnum; i++) {
		cout << G.vertices[i].data;
		ArcNode *p = G.vertices[i].firstarc;
		
		while(p) {
			cout << "->" << G.vertices[p->adjvex].data;
			p = p->nextarc;
		}
		cout<<endl;
	}
}

/* 返回顶点v的第一个邻接点序号 */ 
int FirstAdjVex(ALGraph G, int v) {
	
	ArcNode *p=G.vertices[v].firstarc;
	if(p)
		return p->adjvex;
	else
		return -1;
}

/* 返回顶点v的相对于w的下一个邻接点序号 */ 
int NextAdjVex(ALGraph G, int v, int w) {
	ArcNode* p = G.vertices[v].firstarc;
	while(p) {
		if(p->adjvex == w)
			break;
		p = p->nextarc;
	}
 
	if(p->adjvex != w || !p->nextarc)//如果没找到w或者w是最后一个邻接点
		return -1;
	return p->nextarc->adjvex;
 
}

void DFS(ALGraph G, int v) {
	visited[v] = true;
	cout << G.vertices[v].data << " ";
	for(int w = FirstAdjVex(G, v); w >= 0; w = NextAdjVex(G, v, w))
		if(!visited[w])
			DFS(G, w);
}
 
void DFSTraverse(ALGraph G) {
	for(int i = 0; i < G.vexnum; i++)
		visited[i] = false;
 
	for(int i = 0; i < G.vexnum; i++)
		if(!visited[i])
			DFS(G, i);
}
 
void BFSTraverse(ALGraph G) {
	queue<int> q;
	for(int i = 0; i < G.vexnum; i++)
		visited[i] = false;
 
	for(int i = 0; i < G.vexnum; i++) {
		if(!visited[i]) {
			q.push(i);
			visited[i] = true;
			while(!q.empty()) {
				int v = q.front();
				q.pop();
				
				cout << G.vertices[v].data << " ";
				for(int w = FirstAdjVex(G, v); w >= 0; w = NextAdjVex(G, v, w)) {
					if (!visited[w]) {
						q.push(w);
						visited[w] = true;
					}
				}
			}
		}
	}
}
 
int main()
{
	ALGraph G;
	CreateUDG(G);
	Print(G);
 
	int flag;
	cout << "请选择遍历方式(1.深度优先搜索; 2.广度优先搜索):\n"; 
	cin >> flag;
	
	switch(flag) {
		case 1:
			cout << "DFS:";
			DFSTraverse(G);
			cout << endl;
			break;
		case 2:
		 	cout << "BFS:";
			BFSTraverse(G);
			cout << endl;
	}
	
	return 0;
}

 

posted @ 2018-11-02 17:43  laugh12321  阅读(152)  评论(0编辑  收藏  举报