您的位置:首页 > 其它

第七章 图(邻接矩阵和邻接表建立图并实现DFS、BFS)

2017-12-07 22:30 363 查看

邻接矩阵建立图并实现图的深度优先遍历和广度优先遍历

/*
邻接矩阵实现图的广搜和深搜
*/

#include<iostream>
#include<queue>
#define inf 1000000 //假设的无穷大
#define vertex_max_num 100  //设的最大顶点数

using namespace std;

typedef struct {
int v[vertex_max_num];//顶点名称
int adj_matrix[vertex_max_num][vertex_max_num];//邻接矩阵
int v_num, arc_num;//顶点数,弧数
int kind;//图的种类,0有向图,1有向网,2无向图,3无向网
}graph;

int vis[vertex_max_num+1];//标志数组
//标志数组初始化
void init() {
memset(vis, 0, sizeof(vis));
}

//创建有向图
void dir_graph_create(graph &G) {
cout << "请输入要创建的有向图的顶点数和弧数:"; cin >> G.v_num >> G.arc_num;
//结点初始化
for (int i = 1; i <= G.v_num; i++) G.v[i] = i;//对结点编号
for (int i = 1; i <= G.v_num; i++)
for (int j = 1; j <= G.v_num; j++)
G.adj_matrix[i][j] = 0;
cout << "请依次输入邻接可达的成对结点:" << endl;
for (int i = 1; i <= G.arc_num; i++) {
int v1, v2;
cin >> v1 >> v2;
G.adj_matrix[v1][v2] = 1;
}
}

//创建有向网(带权有向图)
void dir_net_create(graph &G) {
cout << "请输入要创建的有向网的顶点数和弧数:"; cin >> G.v_num >> G.arc_num;
//结点初始化
for (int i = 1; i <= G.v_num; i++) G.v[i] = i;//对结点编号
for (int i = 1; i <= G.v_num; i++)
for (int j = 1; j <= G.v_num; j++)
G.adj_matrix[i][j] = inf;
cout << "请依次输入邻接可达的成对结点及弧长:" << endl;
for (int i = 1; i <= G.arc_num; i++) {
int v1, v2,w;
cin >> v1 >> v2 >> w;
G.adj_matrix[v1][v2] = w;
}
}

//创建无向图
void udir_graph_create(graph &G) {
cout << "请输入要创建的无向图的顶点数和弧数:"; cin >> G.v_num >> G.arc_num;
//结点初始化
for (int i = 1; i <= G.v_num; i++) G.v[i] = i;//对结点编号
for (int i = 1; i <= G.v_num; i++)
for (int j = 1; j <= G.v_num; j++)
G.adj_matrix[i][j] = 0;
cout << "请依次输入邻接的成对结点:" << endl;
for (int i = 1; i <= G.arc_num; i++) {
int v1, v2;
cin >> v1 >> v2;
G.adj_matrix[v1][v2] = 1;
G.adj_matrix[v2][v1] = 1;
}
}

//创建无向网(带权无向图)
void udir_net_create(graph &G) {
cout << "请输入要创建的无向网的顶点数和弧数:"; cin >> G.v_num >> G.arc_num;
//结点初始化
for (int i = 1; i <= G.v_num; i++) G.v[i] = i;//对结点编号
for (int i = 1; i <= G.v_num; i++)
for (int j = 1; j <= G.v_num; j++)
G.adj_matrix[i][j] = inf;
cout << "请依次输入邻接的成对结点及弧长:" << endl;
for (int i = 1; i <= G.arc_num; i++) {
int v1, v2, w;
cin >> v1 >> v2 >> w;
G.adj_matrix[v1][v2] = w;
G.adj_matrix[v2][v1] = w;
}
}

void graph_create(graph &G) {
cout << "************" << endl;
cout << "0-----有向图" << endl;
cout << "1-----有向网" << endl;
cout << "2-----无向图" << endl;
cout << "3-----无向网" << endl;
cout << "************" << endl;
cout << "根据上方菜单,输入相应数字,来创建你想要类型的图" << endl;
cin >> G.kind;
switch (G.kind) {
case 0:dir_graph_create(G); break;
case 1:dir_net_create(G); break;
case 2:udir_graph_create(G); break;
case 3:udir_net_create(G); break;
default:return;
}
}

//图深度优先遍历
void dfs1(graph G, int v) {
if (!vis[v]) {
cout << G.v[v]<<" ";
vis[v] = 1;
}
for (int i = 1; i <= G.v_num; i++)
if (!vis[i] && G.adj_matrix[v][i]==1)
dfs1(G, i);
}

//网深度优先遍历
void dfs2(graph G, int v) {
if (!vis[v]) {
cout << G.v[v]<<" ";
vis[v] = 1;
}
for (int i = 1; i <= G.v_num; i++) {
if (!vis[i] && G.adj_matrix[v][i] != inf)
dfs2(G, i);
}
}

//深度优先遍历
void dfs(graph G, int v) {
init();
cout << "深度优先遍历结果:";
switch (G.kind) {
case 0:
case 2:dfs1(G, v); break;
case 1:
case 3:dfs2(G, v); break;
default:return;
}
cout << endl;
}

//广度优先遍历
void bfs(graph G, int v) {
init();
cout << "广度优先遍历结果:";
queue<int>que;
if (!vis[v]) {
cout << G.v[v] << " ";
vis[v] = 1;
que.push(v);
}
while (!que.empty()) {
int vertex = que.front();
que.pop();
for (int i = 1; i <= G.v_num; i++) {
if (!vis[i]) {
if (((G.kind == 0 || G.kind == 2) && G.adj_matrix[vertex][i] == 1) ||
((G.kind==1 || G.kind==3) && G.adj_matrix[vertex][i]!=inf)) {
cout << G.v[i] << " ";
vis[i] = 1;
que.push(i);
}
}
}
}
cout << endl;
}

int main() {
graph G;
graph_create(G);
dfs(G, 1);
bfs(G, 1);
return 0;
}

/*

下面样例以此图为例
1-3-4
|
6-2-5
|___|

下面输入输出样例已去除文字说明
输入样例
2
6 6
1 2
1 3
2 5
2 6
3 4
5 6
输出样例
1 2 5 6 3 4
1 2 3 5 6 4
*/


邻接表建立图并实现图的深度优先遍历和广度优先遍历

/*
本程序用邻接表实现图的深搜和广搜
以无向网为例,本例子中的无向网如下(边权重没有写):
A-B-C
|
F-D-E
|___|

//下面是基于上面无向网的输入输出样例(这里权重都简为1)

请输入要创建的图的结点数和边数:6 6
========================================
结点信息如下
第1个结点是A
第2个结点是B
第3个结点是C
第4个结点是D
第5个结点是E
第6个结点是F
========================================
边信息如下
请输入第1条边相连的两个结点编号及边的权重:1 2 1
请输入第2条边相连的两个结点编号及边的权重:1 4 1
请输入第3条边相连的两个结点编号及边的权重:2 3 1
请输入第4条边相连的两个结点编号及边的权重:4 5 1
请输入第5条边相连的两个结点编号及边的权重:4 6 1
请输入第6条边相连的两个结点编号及边的权重:5 6 1
邻接表如下:
A→B→D
B→A→C
C→B
D→A→E→F
E→D→F
F→D→E
从各个结点出发深搜结果:
A B C D E F
B A D E F C
C B A D E F
D A B C E F
E D A B C F
F D A B C E
从各个结点出发广搜结果:
A B D C E F
B A C D E F
C B A D E F
D A E F B C
E D F A B C
F D E A B C
*/

#include<iostream>
#include<queue>
using namespace std;

const int vertex_max = 100;
typedef char vertex_type;

//边
typedef struct edge_node {
int vertex;//边所指向的结点编号
struct edge_node *next;//下一条边
}edge;

//结点
typedef struct vertex_node {
vertex_type e;//结点名字
edge *side;
}vertex;

typedef struct Graph {
vertex adj_list[vertex_max+1];//邻接表
int w[vertex_max+1][vertex_max + 1];//边权重
int v_num, e_num;//结点数、边数
}graph;

bool vis[vertex_max + 1];
void init() {
memset(vis, 0, sizeof(vis));
}

//建立图
void graph_create(graph &G) {
cout << "请输入要创建的图的结点数和边数:";
cin >> G.v_num >> G.e_num;
cout << "========================================" << endl;
cout << "结点信息如下"<<endl;
for (int i = 1; i <= G.v_num; i++) {
cout << "第" << i << "个结点是"; cin >> G.adj_list[i].e;
G.adj_list[i].side = nullptr;
}
cout << "========================================" << endl;
cout << "边信息如下" << endl;
for (int i = 1; i <= G.e_num; i++) {
cout << "请输入第" << i << "条边相连的两个结点编号及边的权重:";
int x, y,weight;
cin >> x >> y >> weight;
G.w[x][y] = G.w[y][x] = weight;
edge *p_edge = new edge;
edge *q_edge = new edge;
p_edge->next = nullptr; p_edge->vertex = y;
q_edge->next = nullptr; q_edge->vertex = x;
edge *tmp1 = G.adj_list[x].side;
edge *tmp2 = G.adj_list[y].side;
//把x结点指向y结点
while (tmp1) {
if (tmp1->next == nullptr) break;
tmp1 = tmp1->next;
}
if (tmp1 == nullptr) G.adj_list[x].side = p_edge;
else tmp1->next = p_edge;
//把y结点指向x结点
while (tmp2) {
if (tmp2->next == nullptr) break;
tmp2 = tmp2->next;
}
if (tmp2 == nullptr) G.adj_list[y].side = q_edge;
else tmp2->next = q_edge;
}
}

//打印邻接表
void adj_list_print(graph G) {
for (int i = 1; i <= G.v_num; i++) {
cout << G.adj_list[i].e;
edge *tmp = G.adj_list[i].side;
while (tmp) {
cout <<"→"<< G.adj_list[tmp->vertex].e;
tmp = tmp->next;
}
cout << endl;
}
}

//深搜(从某结点出发搜索)
void dfs1(graph G, int v) {
if (!vis[v]) {
cout << G.adj_list[v].e << " "; vis[v] = true;
}
edge *p = G.adj_list[v].side;
while (p) {
if (!vis[p->vertex]) dfs1(G, p->vertex);
p = p->next;
}
}
//深搜(从各个结点出发搜索)
void dfs(graph G) {
for (int i = 1; i <= G.v_num; i++) {
init();
dfs1(G, i);
cout << endl;
}
}

//广搜(从某个结点出发搜索)
void bfs1(graph G,int i) {
init();
queue<int>que;
if (!vis[i]) {
cout << G.adj_list[i].e << " ";
que.push(i);
vis[i] = 1;
}
while (!que.empty()) {
int ii = que.front();
que.pop();
edge *p = G.adj_list[ii].side;
while (p) {
if (!vis[p->vertex]) {
cout << G.adj_list[p->vertex].e << " ";
que.push(p->vertex);
vis[p->vertex] = 1;
}
p = p->next;
}
}
}
//广搜(从各个结点出发搜索)
void bfs(graph G) {
for (int i = 1; i <= G.v_num; i++) {
bfs1(G, i);
cout << endl;
}
}

int main()
{
graph G;
graph_create(G);
cout << "邻接表如下:" << endl; adj_list_print(G);
cout << "从各个结点出发深搜结果:" << endl; dfs(G);
cout << "从各个结点出发广搜结果:" << endl; bfs(G);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: