【数据结构】图的基本操作——图的构造(邻接矩阵,邻接表),遍历(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;
}