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

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

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

#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;
}
  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值