【数据结构】图-图的存储_邻接矩阵(图解、c++、java)

GitHub同步更新(已分类)Data_Structure_And_Algorithm-Review

公众号:URLeisure 的复习仓库
公众号二维码见文末

以下是本篇文章正文内容,下面案例可供参考。


一、概述

图的结构比较复杂,任何两个顶点之间都可能有关系。

  • 顺序存储,则需要使用二维数组表示元素之间的关系,即邻接矩阵(adjacency matrix),也可以使用边集数组,把每条边顺序存储起来。

  • 链式存储,有邻接表、十字链表、多重表和链式前向星等表示方法。

其中,邻接矩阵和邻接表是最简单、最常用的存储方法。(竞赛用链式前向星多)

二、邻接矩阵

1. 存储方法

  • 一个一维数组存储图中顶点的信息。

  • 一个二维数组存储图中顶点之间的邻接关系,存储顶点之间邻接关系的二维数组称为邻接矩阵

2. 表示方法

1). 无向图

  • 在无向图中,如果 Vi 和 Vj,则邻接矩阵 M [ i ] [ j ] = M [ j ] [ i ] = 1 M[i][j] = M[j][i] = 1 M[i][j]=M[j][i]=1,否则 M [ i ] [ j ] = M [ j ] [ i ] = 0 M[i][j] = M[j][i] = 0 M[i][j]=M[j][i]=0

在这里插入图片描述

如图,存储此无向图,其顶点信息和邻接矩阵如图所示。

在这里插入图片描述

特点
  1. 无向图的邻接矩阵是对称矩阵,并且是唯一的;
  2. 第 i 行或第 i 列非零元素个数正好是第 i 个顶点的度。

2). 有向图

  • 在有向图中,如果 Vi 到 Vj 有弧,则邻接矩阵 M [ i ] [ j ] = 1 M[i][j] = 1 M[i][j]=1,否则 M [ i ] [ j ] = 0 M[i][j] = 0 M[i][j]=0

在这里插入图片描述

  • 注意:<Vi,Vj> 表示有序对,(Vi,Vj) 表示无序对。

如图,存储此有向图,其顶点信息和邻接矩阵如图所示。

在这里插入图片描述

特点
  1. 有向图的邻接矩阵不一定是对称的;
  2. 第 i 行非零元素的个数正好是第 i 个顶点的出度,第 i 列非零元素的个数正好是第 i 个顶点的入度。

3). 网

  • 网是带权的图,需要存储边的权值,邻接矩阵表示为:

在这里插入图片描述

  • 其中,Wij 表示边的权值,∞ 表示无穷大。

  • i = j i = j i=j时,Wii 也可以设置为 0。

如图,存储此网,其顶点信息和邻接矩阵如图所示。

在这里插入图片描述

三、实现

  • 做个无向图的邻接矩阵,其他的就不做了,都一样。

1. 邻接矩阵的数据结构

c++代码如下(示例):

#define MaxVnum 100//顶点数最大值
typedef char VexType;//顶点类型
typedef int EdgeType;//边类型
struct AMGraph {
    VexType Vex[MaxVnum];
    EdgeType Edge[MaxVnum][MaxVnum];
    int vexnum, edgenum;//顶点数,边数
};

java代码如下(示例):

private static class AMGraph {
    String vex[] = new String[maxVnum];
    int edge[][] = new int[maxVnum][maxVnum];
    int vexnum, edgenum;
}

2. 算法步骤

算法步骤:

  1. 输入顶点数和边数;
  2. 依次输入顶点信息,存储到顶点数组 Vex[ ] 中;
  3. 初始化邻接矩阵,如果是图,则初始化为 0;如果是网,则初始化为 ∞;
  4. 依次输入每条边依附的两个顶点,如果是网,还要输入该边的权值。
  • 无向图: G . E d g e [ i ] [ j ] = G . E d g e [ j ] [ i ] = 1 ; G.Edge[i][j] = G.Edge[j][i] = 1; G.Edge[i][j]=G.Edge[j][i]=1;
  • 有向图: G . E d g e [ i ] [ j ] = 1 ; G.Edge[i][j] = 1; G.Edge[i][j]=1;
  • 无向网: G . E d g e [ i ] [ j ] = G . E d g e [ j ] [ i ] = w ; G.Edge[i][j] = G.Edge[j][i] = w; G.Edge[i][j]=G.Edge[j][i]=w;
  • 有向网: G . E d g e [ i ] [ j ] = w ; G.Edge[i][j] = w; G.Edge[i][j]=w;

3.代码

c++代码如下(示例):

void CreateGraph(AMGraph &G) {
    cout << "输入顶点数和边数:" << endl;
    cin >> G.vexnum >> G.edgenum;
    cout << "输入顶点信息" << endl;
    for (int i = 0; i < G.vexnum; i++) {
        cin >> G.Vex[i];
    }
    memset(G.Edge, 0, sizeof G.Edge);//初始化为 0(网初始化为 ∞)
    cout << "输入每条边依附的两个顶点:" << endl;
    VexType u, v;
    while (G.edgenum--) {
        cin >> u >> v;
        int i = LocateVex(G, u);//查找位置
        int j = LocateVex(G, v);
        if (i != -1 && j != -1) {//存在
            G.Edge[i][j] = G.Edge[j][i] = 1;
        } else {
            cout << "错误!" << endl;
            G.edgenum++;
        }
    }
}

java代码如下(示例):

public static void createGraph(AMGraph g) {
    g.vexnum = sc.nextInt();
    g.edgenum = sc.nextInt();
    for (int i = 0; i < g.vexnum; i++) {
        g.vex[i] = sc.next();
   	}
    for (int i = 0; i < g.vexnum; i++) {
       	for (int j = 0; j < g.vexnum; j++) {
            g.edge[i][j] = 0;
       }
    }
    String u, v;
  	while (g.edgenum-- > 0) {
        u = sc.next();
        v = sc.next();
        int i = locateVex(g, u);
        int j = locateVex(g, v);
        if (i != -1 && j != -1) {
            g.edge[i][j] = g.edge[j][i] = 1;
        } else {
            System.out.println("错误!");
            g.edgenum++;
        }
    }
}

四、完整代码

c++代码如下(示例):

#include<iostream>
#include <cstring>

using namespace std;
#define MaxVnum 100
typedef char VexType;
typedef int EdgeType;
struct AMGraph {
    VexType Vex[MaxVnum];
    EdgeType Edge[MaxVnum][MaxVnum];
    int vexnum, edgenum;
};

int LocateVex(AMGraph G, int x) {
    for (int i = 0; i < G.vexnum; i++) {
        if (G.Vex[i] == x) {
            return i;
        }
    }
    return -1;
}

void CreateGraph(AMGraph &G) {
    cout << "输入顶点数和边数:" << endl;
    cin >> G.vexnum >> G.edgenum;
    cout << "输入顶点信息" << endl;
    for (int i = 0; i < G.vexnum; i++) {
        cin >> G.Vex[i];
    }
    memset(G.Edge, 0, sizeof G.Edge);
    cout << "输入每条边依附的两个顶点:" << endl;
    VexType u, v;
    while (G.edgenum--) {
        cin >> u >> v;
        int i = LocateVex(G, u);
        int j = LocateVex(G, v);
        if (i != -1 && j != -1) {
            G.Edge[i][j] = G.Edge[j][i] = 1;
        } else {
            cout << "错误!" << endl;
            G.edgenum++;
        }
    }
}

void Print(AMGraph G) {
    for (int i = 0; i < G.vexnum; i++) {
        for (int j = 0; j < G.vexnum; j++) {
            cout << G.Edge[i][j] << " ";
        }
        cout << endl;
    }
}

int main() {
    AMGraph G;
    CreateGraph(G);
    Print(G);
}
/*
4 5
a b c d
a b
a c
a d
b d
c d
 */

java代码如下(示例):

import java.util.Scanner;

public class A {
    private static Scanner sc = new Scanner(System.in);
    private static final int maxVnum = 100;

    private static class AMGraph {
        String vex[] = new String[maxVnum];
        int edge[][] = new int[maxVnum][maxVnum];
        int vexnum, edgenum;
    }

    public static int locateVex(AMGraph g, String x) {
        for (int i = 0; i < g.vexnum; i++) {
            if (g.vex[i].equals(x)) {
                return i;
            }
        }
        return -1;
    }

    public static void createGraph(AMGraph g) {
        g.vexnum = sc.nextInt();
        g.edgenum = sc.nextInt();
        for (int i = 0; i < g.vexnum; i++) {
            g.vex[i] = sc.next();
        }
        for (int i = 0; i < g.vexnum; i++) {
            for (int j = 0; j < g.vexnum; j++) {
                g.edge[i][j] = 0;
            }
        }
        String u, v;
        while (g.edgenum-- > 0) {
            u = sc.next();
            v = sc.next();
            int i = locateVex(g, u);
            int j = locateVex(g, v);
            if (i != -1 && j != -1) {
                g.edge[i][j] = g.edge[j][i] = 1;
            } else {
                System.out.println("错误!");
                g.edgenum++;
            }
        }
    }

    public static void print(AMGraph g) {
        for (int i = 0; i < g.vexnum; i++) {
            for (int j = 0; j < g.vexnum; j++) {
                System.out.print(g.edge[i][j] + " ");
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        AMGraph g = new AMGraph();
        createGraph(g);
        print(g);
    }

}
/*
4 5
a b c d
a b
a c
a d
b d
c d
 */

关注公众号,感受不同的阅读体验

请添加图片描述

下期预告:图的存储_邻接表

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

扑腾的江鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值