文章目录

  • 一、邻接矩阵
  • 二、邻接表

一、邻接矩阵

1. 定义

  • vexs[](存储顶点)和 arcs[][](存储边关系,叫邻接矩阵)集合。因此,用一个一维数组存放图中所有顶点数据;
  • 用一个二维数组存放顶点间关系(边或弧)的数据,这个二维数组称为邻接矩阵
  • 无向图邻接矩阵是一个对称矩阵。
  • 用邻接矩阵表示图,很容易确定图中任意两个顶点是否有边相连。
  • 前一天的基础知识讲了:有权的图被称为网。无向图比有向图更为特殊。

2. 数据结构

  • 邻接矩阵,C语言数据结构
#define MAX_VEX 20
typedef enum {DG, UDG};
typedef int InfoType;
// 弧结点与矩阵的类型
typedef struct ArcCell {int adj; // 图--0,1;网--权值InfoType * Info; //与弧相关的信息的指针,如:权值
}ArcCell, AdjMatrix[MAX_VEX][MAX_VEX];
//  图的类型
typedef struct {        char vexs[MAX_VEX]; // 顶点向量,一维矩阵 AdjMatrix arcs; // 邻接矩阵,二维矩阵 int vexnum, arcnum; // 顶点数,边数GraphKind kind; // 图类型
}MGraph;
  • Java代码

图的接口:(1.因为要写的数据结构较多,邻接矩阵,邻接表,十字链表,多重链表。但我们要实现的功能差不多,我们就可以把图的基本操作集成为一个接口。2.尝试多种方式开发,不拘泥。)

package graph;/*** 邻接矩阵图的接口* * @author 己千之* @time 2022/2/8/16:32 (tuesday)*/
public interface IGraph {/*** 获取顶点的个数* * @return 顶点的个数*/int getNumOfVertex();/*** 获取边的个数* * @return*/int getNumOfArc();/*** 插入顶点* * @param String v* @return boolean*/boolean insertVex(String v);/*** 删除顶点* * @param String v* @return boolean*/boolean deleteVex(String v);/*** 定位顶点的位置* * @param String v* @return 顶点的位置*/int indexOfVex(String v);/*** 定位指定位置的顶点* * @param v 顶点的位置* @return E*/String valueOfVex(int v);/*** 插入边* * @param v1     顶点的位置* @param v2     顶点的位置* @param weight* @return boolean*/boolean insertEdge(int v1, int v2, int weight);/*** 删除边* * @param v1 顶点的位置* @param v2 顶点的位置* @return boolean*/boolean deleteEdge(int v1, int v2);/*** 查找边,获取权值* * @param v1 顶点的位置* @param v2 顶点的位置* @return*/int getEdge(int v1, int v2);/*** @深度优先搜索遍历 * 从第v个顶点位置开始,深度优先搜索遍历* * @param v 顶点的位置* @return eg: v1->v2-v3*/void DFSTraverse();/*** @广度优先搜索遍历 * 从第v个顶点位置开始,广度优先搜索遍历* * @param v 顶点的位置* @return eg: v1->v2-v3*/void BFSTraverse();/*** 查找源点到其它各个顶点的最短路径* * @param v* @return int[] 源点到其它各个顶点的最短路径*/public int[] dijkstra(int v);} // IGraph

Java邻接矩阵:

package graph;import java.util.Arrays;/*** 邻接矩阵 存储图* * @author 己千之* @MGraph Matrix Graph*/
public class MGraph implements IGraph {/*** @INF 无穷大 private static final int INF=Integer.MAX_VALUE;*/public static final int INF = 99; // 最大值/*** 存储图的顶点的一维数组*/String[] vexs;/*** 存储图的边的二维数组*/int[][] arcs;/*** 顶点的实际数量*/int vexNum;/*** 边数*/int arcNum;/*** 顶点的最大数量*/int vexMax;/*** 构造函数* * @param vexMax int型*/public MGraph(int vexMax) {this.vexMax = vexMax;this.arcs = new int[vexMax][vexMax];this.vexs = new String[vexMax];}/*** 构造函数* * 直接传入一个矩阵,作为邻接矩阵* * @param AdjMatrix*/public MGraph(int[][] AdjMatrix) {vexMax = AdjMatrix.length;this.arcs = new int[vexMax][vexMax];for (int i = 0; i < vexMax; i++) {for (int j = 0; j < vexMax; j++) {arcs[i][j] = AdjMatrix[i][j];}}this.vexs = new String[vexMax];for (int i = 0; i < vexMax; i++) {int t = i + 1;vexs[i] = "node" + t;}}/*** 深度遍历* * toString() arcs[][]*/public String toString() {return Arrays.deepToString(arcs);}@Overridepublic int getNumOfVertex() {// 得到顶点的数目return this.vexNum;}@Overridepublic int getNumOfArc() {// 得到边的数目int edgeNum = 0;for (int i = 0; i < vexNum; i++) {for (int j = 0; j < vexNum; j++) {if (this.arcs[i][j] != INF && arcs[i][j] != 0) {edgeNum++;}}}return edgeNum;}@Overridepublic boolean insertVex(String v) {// 插入顶点if (this.vexNum >= this.vexMax) {return false;}vexs[this.vexNum++] = v;return true;}@Overridepublic boolean deleteVex(String v) {// 删除顶点for (int i = 0; i < vexNum; i++) {if (vexs[i] == v) {for (int j = i; j < vexNum - 1; j++) {vexs[j] = vexs[j + 1];}vexs[vexNum - 1] = "0";for (int col = i; col < vexNum - 1; col++) {for (int row = 0; row < vexNum; row++) {arcs[col][row] = arcs[col + 1][row];}}for (int row = i; row < vexNum - 1; row++) {for (int col = 0; col < vexNum; col++) {arcs[col][row] = arcs[col][row + 1];}}vexNum--;return true;}}return false;}@Overridepublic int indexOfVex(String v) {// 定位顶点的位置for (int i = 0; i < vexNum; i++) {if (vexs[i] == v)return i;}return -1;}@Overridepublic String valueOfVex(int v) {// 定位指定位置的顶点if (v < 0 || v >= vexNum)return "0";return vexs[v];}@Overridepublic boolean insertEdge(int v1, int v2, int weight) {// 插入边if (v1 < 0 || v2 < 0 || v1 >= vexNum || v2 >= vexNum)throw new RuntimeException("位置错误!");arcs[v1][v2] = weight;if (arcs[v1][v2] != INF) {arcNum++;}
//      arcs[v2][v1] = weight; 这句是加上,就是构造无向图return true;}@Overridepublic boolean deleteEdge(int v1, int v2) {// 删除边if (v1 < 0 || v2 < 0 || v1 >= vexNum || v2 >= vexNum)throw new RuntimeException("位置错误!");arcs[v1][v2] = 0;arcs[v2][v1] = 0;return true;}@Overridepublic int getEdge(int v1, int v2) {// 查找边if (v1 < 0 || v2 < 0 || v1 >= vexNum || v2 >= vexNum)throw new RuntimeException("位置错误!");return arcs[v1][v2];}@Overridepublic void DFSTraverse() {// TODO 自动生成的方法存根}@Overridepublic void BFSTraverse() {// TODO 自动生成的方法存根}@Overridepublic int[] dijkstra(int v) {// TODO 自动生成的方法存根return null;}/*** 打印邻接矩阵*/public void printMGraph() {System.out.println("邻接矩阵:");// 输出int t = 0;for (int i = 0; i < arcs.length; i++) {for (int j = 0; j < arcs.length; j++) {System.out.printf("%2d", arcs[i][j]);t++;if (t % arcs.length == 0) {System.out.println();} else {System.out.print("  ");}}}}/*** 测试* * @param args*/public static void main(String[] args) {MGraph mgraph = new MGraph(3);mgraph.insertVex("A");mgraph.insertVex("B");mgraph.insertVex("C");// 有向图mgraph.insertEdge(0, 1, 1);mgraph.insertEdge(1, 2, 1);mgraph.insertEdge(2, 0, 1);System.out.println("一、顶点个数:" + mgraph.getNumOfVertex());System.out.println("a的位置:" + mgraph.indexOfVex("A"));System.out.println("b的位置:" + mgraph.indexOfVex("B"));System.out.println("c的位置:" + mgraph.indexOfVex("C"));System.out.println("1这个位置的顶点:" + mgraph.valueOfVex(1));System.out.println("查找边,a->b权值::" + mgraph.getEdge(0, 1));System.out.println("邻接矩阵::" + mgraph.toString());mgraph.printMGraph();System.out.println("边数:" + mgraph.arcNum);}} // MGraph

效果图:



二、邻接表

1. 定义

  • 是图的一种链式储存结构。

  • 在邻接表中,对图中的每个顶点建立一个单链表。

  • 每一个顶点构造一个数据结构——命名为结点,分3个域。

  • 为了随机访问任一顶点,每一个表结点前,设置了表头结点。因为表头结点可以以顺序结构的形式存储。

    • 有向图,n个顶点,e条边,需要n个头结点,e个表结点。
  • 无向图,n个顶点,e条边,需要n个头结点,2e个表结点。

  • 表结点:

  1. 邻接点域:vi,adjvex
  2. 链域:下一条弧的结点,nextarc
  3. 数据域:储存弧相关的信息,如权值,info
  • 表头结点:
  1. 数据域:data
  2. 链域:firstarc


2. 数据结构

  • 邻接表,C语言数据结构
#define MAX_VEX 20
typedef enum
{DG, // 有向图UDG // 无向图
}GraphKind;
typedef struct ArcNode
{int adjvex; // 顶点的位置下标struct ArcNode * nextarc; // 指向下一条弧的指针InfoType * Info; //与弧相关的信息的指针,如:权值,可省略 -
}ArcNode;
typedef struct VexNode
{char data;ArcNode * firstarc;
}VexNode, AdjList[MAX_VEX];
typedef struct
{AdjList vertices; // 挂接了链表的顶点数组int vexnum;int arcnum;GraphKind kind;
}ALGraph;
  • 图例

  • Java代码

结点:

 /*** 弧结点,表结点*/class arcNode {int index;int weight;arcNode nextNode;}/*** 顶点,表头结点*/class vexNode {char data;arcNode firstArc;}/*** 边关系* * @static:测试方法中,用到了Edge数组 Edge是个内部类,你要用,只能: 1.把Edge作为参数,可以用 2.吧Edge设为静态调用*/static class Edge {char start;char end;int weight;public Edge(char start, char end, int weight) {this.start = start;this.end = end;this.weight = weight;}}

构造方法,构造有向图

 /*** 构造方法,构造有向图* * @param vertex* @param edge*/public ALGraph(char[] vertex, Edge[] edge) {// 1.设置顶点数组大小vexs = new vexNode[vertex.length];// 2.初始化数组for (int i = 0; i < vexs.length; i++) {vexs[i] = new vexNode();vexs[i].data = vertex[i];vexs[i].firstArc = null;}// 3.链接for (int i = 0; i < edge.length; i++) {// 3.1由new Edge('A', 'B', 10)来链接char start = edge[i].start;char end = edge[i].end;int index1 = indexOfVex(start);int index2 = indexOfVex(end);// 3.2构造一个新的arcNode类型的结点arcNode node = new arcNode();node.index = index2;node.weight = edge[i].weight;// 3.3尾插法,有向,不是无向linkedLast(index1, node);}} // stucture

方法:

 /*** 获取顶点元素位置* * @param v* @return*/public int indexOfVex(char v) {// 定位顶点的位置for (int i = 0; i < vexs.length; i++) {if (vexs[i].data == v)return i;}return -1;} // indexOfVex/*** 尾插法* * @param index* @param node*/public void linkedLast(int index, arcNode node) {if (vexs[index].firstArc == null) {// 关键代码vexs[index].firstArc = node;} else {arcNode tempNode = vexs[index].firstArc;while (tempNode.nextNode != null) {tempNode = tempNode.nextNode;}// 关键代码tempNode.nextNode = node;}} // linkedLast/*** 像邻接表一样打印*/public void printALGraph() {System.out.println("邻接表存储的图:");for (int i = 0; i < vexs.length; i++) {// 1.打印顶点System.out.print(vexs[i].data + "--->");// 2.打印挂接链表// 2.1 tempNode.nextNode != nullarcNode tempNode = vexs[i].firstArc;while (tempNode.nextNode != null) {System.out.print(vexs[tempNode.index].data + "-->");// 2.1.1 后移tempNode = tempNode.nextNode;}// 2.2 tempNode.nextNode = nullSystem.out.print(vexs[tempNode.index].data);System.out.println();}} // printALGraph

测试方法:

 /*** 测试* * @param args*/public static void main(String[] args) {// 1.顶点集char[] vexs = { 'A', 'B', 'C', 'D', 'E' };// 2.边集Edge[] edges = {new Edge('A', 'B', 10), new Edge('A', 'D', 10), new Edge('B', 'A', 20),new Edge('B', 'C', 20),new Edge('B', 'E', 20), new Edge('C', 'B', 30), new Edge('C', 'D', 30), new Edge('C', 'E', 30), new Edge('D', 'A', 40),new Edge('D', 'C', 40),new Edge('E', 'B', 40),new Edge('E', 'C', 40)};ALGraph graph = new ALGraph(vexs, edges);// 打印图的邻接表graph.printALGraph();}

效果图:
例子:还是上面的那个无向图


源码:

package graph;/*** 邻接表* * Adjacency List Graph* * @author 己千之* @time 2022/2/16(周三)*/
public class ALGraph {/*** 弧结点,表结点*/class arcNode {int index;int weight;arcNode nextNode;}/*** 顶点,表头结点*/class vexNode {char data;arcNode firstArc;}/*** 边关系* * @static:测试方法中,用到了Edge数组 Edge是个内部类,你要用,只能: 1.把Edge作为参数,可以用 2.吧Edge设为静态调用*/static class Edge {char start;char end;int weight;public Edge(char start, char end, int weight) {this.start = start;this.end = end;this.weight = weight;}}/*** 顶点数组*/vexNode[] vexs;/*** 构造方法,构造有向图* * @param vertex* @param edge*/public ALGraph(char[] vertex, Edge[] edge) {// 1.设置顶点数组大小vexs = new vexNode[vertex.length];// 2.初始化数组for (int i = 0; i < vexs.length; i++) {vexs[i] = new vexNode();vexs[i].data = vertex[i];vexs[i].firstArc = null;}// 3.链接for (int i = 0; i < edge.length; i++) {// 3.1由new Edge('A', 'B', 10)来链接char start = edge[i].start;char end = edge[i].end;int index1 = indexOfVex(start);int index2 = indexOfVex(end);// 3.2构造一个新的arcNode类型的结点arcNode node = new arcNode();node.index = index2;node.weight = edge[i].weight;// 3.3尾插法,有向,不是无向linkedLast(index1, node);}} // stucture/*** 获取顶点元素位置* * @param v* @return*/public int indexOfVex(char v) {// 定位顶点的位置for (int i = 0; i < vexs.length; i++) {if (vexs[i].data == v)return i;}return -1;} // indexOfVex/*** 尾插法* * @param index* @param node*/public void linkedLast(int index, arcNode node) {if (vexs[index].firstArc == null) {// 关键代码vexs[index].firstArc = node;} else {arcNode tempNode = vexs[index].firstArc;while (tempNode.nextNode != null) {tempNode = tempNode.nextNode;}// 关键代码tempNode.nextNode = node;}} // linkedLast/*** 像邻接表一样打印*/public void printALGraph() {System.out.println("邻接表存储的图:");for (int i = 0; i < vexs.length; i++) {// 1.打印顶点System.out.print(vexs[i].data + "--->");// 2.打印挂接链表// 2.1 tempNode.nextNode != nullarcNode tempNode = vexs[i].firstArc;while (tempNode.nextNode != null) {System.out.print(vexs[tempNode.index].data + "-->");// 2.1.1 后移tempNode = tempNode.nextNode;}// 2.2 tempNode.nextNode = nullSystem.out.print(vexs[tempNode.index].data);System.out.println();}} // printALGraph/*** 测试* * @param args*/public static void main(String[] args) {// 1.顶点集char[] vexs = { 'A', 'B', 'C', 'D', 'E' };// 2.边集Edge[] edges = {new Edge('A', 'B', 10), new Edge('A', 'D', 10), new Edge('B', 'A', 20),new Edge('B', 'C', 20),new Edge('B', 'E', 20), new Edge('C', 'B', 30), new Edge('C', 'D', 30), new Edge('C', 'E', 30), new Edge('D', 'A', 40),new Edge('D', 'C', 40),new Edge('E', 'B', 40),new Edge('E', 'C', 40)};ALGraph graph = new ALGraph(vexs, edges);// 打印图的邻接表graph.printALGraph();}
}

Java数据结构——邻接矩阵+邻接表相关推荐

  1. java怎么建立邻接表,java实现邻接表

    图的邻接表表示和实现 7.3 图的遍历 8.3.4 构造链地址法的散列表 8.4.1 二叉排序树 10.2 实现迭代器 Vertex AdjListGraph AbstractGraph Hash.. ...

  2. 【数据结构】邻接表的储存结构 建立图的邻接表算法

    [数据结构]邻接矩阵及其实现 一个图的邻接矩阵的表示是唯一的,但其邻接表表示不唯一,这是因为在邻接表结构中,各便表结点的链接次序取决于建立邻接表时的算法以及输入的次序. 一般而言邻接矩阵适合存储稠密图 ...

  3. 图的存储 邻接矩阵+邻接表+链式前向星

    图的存储 - 邻接矩阵 在树的问题中,邻接矩阵是空间.时间的极大浪费. 假设树的结点个数为 N = 100000. 建立邻接矩阵需要空间为 1e5*1e5 但是由于只有 N - 1 条边,所以在邻接矩 ...

  4. Python邻接矩阵邻接表转换

    tags: Python GT 写在前面 学图论当然要学其中的算法, 学算法的基础在数据结构, 当然也少不了程序. 虽然不是专门研究图论, 但是能根据算法写出代码, 才算是真正掌握了这些概念了吧. 下 ...

  5. 数据结构复习 ---- 邻接表

    一.邻接表的定义 邻接表是一种数组与链表相结合的存储方式:用一个一维数组取存放图的顶点,记做顶点表:该数组中的每一个顶点的所有邻接点构成一个链表,无向图称该链表为该顶点的边表,有向图称该链表为该顶点作 ...

  6. HDU 1285 确定比赛名次 拓扑排序(邻接矩阵 邻接表

    确定比赛名次 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Description ...

  7. Java数据结构之线性表(2)

    从这里开始将要进行Java数据结构的相关讲解,Are you ready?Let's go~~ java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来的 ...

  8. 【Java数据结构】线性表

    线性表 线性表是最基本.最简单.也是最常用的一种数据结构. 线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的(注意,这句话只适用大部分线性表,而 ...

  9. C/C++语言 数据结构 创建邻接表存储的无向图及其邻接表的输出

    目录 1.邻接表相关知识补充 2. 图的邻接存储表示 3.测试输入与输出样例 4.代码实现 4.1 创建无向图邻接表 4.2 输入无向图的邻接表 1.邻接表相关知识补充 定义: 对于图中每个顶点 vi ...

最新文章

  1. php异常跑出,php 抛出异常但继续往下执行为什么
  2. A review of 3D/2D registration methods for image-guided interventions(1)
  3. 浏览器快捷键_干货 | 掌握这些快捷键,工作效率翻倍
  4. 爬虫系列---Scrapy框架学习
  5. pline加点lisp_用Autolisp 在AutoCAD中实现多种曲线的绘制
  6. python问题化教学设计_基于IPO的Python教学设计
  7. ice 服务java连接,java - ICE中的连接计数 - 堆栈内存溢出
  8. mysql 8 配置参数优化_MySQL性能优化之参数配置
  9. jmeter连接并使用mysql数据库_jmeter连接MySQL数据库,并执行sql
  10. pngquanttinypng 使用教程
  11. 环境试验之单臂跌落试验机操作规程
  12. NRF24L01模块使用(老干妈笔记)
  13. vba操作word删除某些页面
  14. 第二章、Magick命令组合多个图像处理操作
  15. 恒玉佳壬二酸使用方法,15壬二酸能帮助祛痘吗
  16. Java-编辑图片,添加文字
  17. Excel如何提取单元格中最后一次出现的数值
  18. vue(h5+app分享微信、朋友圈、保存图片)
  19. 二代测序的原理和简介
  20. MAC 升级monterey 系统后无法启动Parallels Desktop

热门文章

  1. Web3中文|逆流前行:日本开始拥抱Web3
  2. 2021.11.13
  3. Python实现最小生成树(Prim算法)
  4. AI:陆奇博士(原微软全球执行副总裁/百度COO/现奇绩创坛创始人兼CEO)演讲之《正视挑战,把握创业创新机会》
  5. ROS机器人操作系统实践(一)—— 环境搭建
  6. Linux 下安装Ubuntu20.04 启动花屏的解决方法(安装和启动时设置 quite splash nomodeset即可解决)
  7. java双下划线改单下划线_单下划线与双下划线的区别
  8. 百度点石-人工智能农作物识别比赛总结
  9. VINS-初始化:【翻译】Robust Initialization of Monocular Visual-Inertial Estimation on Aerial Robots
  10. windows 10 局域网设置固定 IP 地址