`
luoweifu
  • 浏览: 60964 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

图(2)—— 邻接矩阵表示法

 
阅读更多

图的存储结构

图的存储结构比较复杂,其复杂性主要表现在:

◆任意顶点之间可能存在联系,无法以数据元素在存储区中的物理位置来表示元素之间的关系。

◆图中顶点的度不一样,有的可能相差很大,若按度数最大的顶点设计结构,则会浪费很多存储单元,反之按每个顶点自己的度设计不同的结构,又会影响操作。

图的常用的存储结构有:邻接矩阵邻接链表十字链表邻接多重表边表,其中邻接矩阵和邻接链表是比较常用的表示方法。

邻接矩阵(数组)表示法

基本思想:对于有n个顶点的图,用一维数组vexs[n]存储顶点信息,用二维数组A[n][n]存储顶点之间关系的信息。该二维数组称为邻接矩阵。在邻接矩阵中,以顶点在vexs数组中的下标代表顶点,邻接矩阵中的元素A[i][j]存放的是顶点i到顶点j之间关系的信息。

1无向图的数组表示

(1)无权图的邻接矩阵

无向无权图G=(VE)n(n1)个顶点,其邻接矩阵是n阶对称方阵,如下图所示。其元素的定义如下:

(2)带权图的邻接矩阵

无向带权图G=(VE)的邻接矩阵如下图所示。其元素的定义如下:

(3)无向图邻接矩阵的特性

◆邻接矩阵是对称方阵;

◆对于顶点vi,其度数是第i行的非0元素的个数;

◆无向图的边数是上(或下)三角形矩阵中非0元素个数。

2有向图的数组表示

(1)无权图的邻接矩阵

若有向无权图G=(VE)n(n1)个顶点,则其邻接矩阵是n阶对称方阵,如图7-7所示。元素定义如下:


(2)带权图的邻接矩阵

有向带权图G=(VE)的邻接矩阵如图所示。其元素的定义如下:


⑶有向图邻接矩阵的特性

◆对于顶点vi,第i行的非0元素的个数是其出度OD(vi);第i列的非0元素的个数是其入度ID(vi)

◆邻接矩阵中非0元素的个数就是图的弧的数目。


邻接矩阵表示法


上一节讲了图的定义和基本概念,以及接口的定义,现在对上一节中的接口进行类的实现,如下。

MatrixEdge.java
package datastructure.graph;
/**
 * 邻接矩阵表示法表示的图
 * @author luoweifu
 *
 */
public class MatrixEdge extends Edge {
	private Object v1, v2;
	/**
	 * 构造函数
	 * @param weight 权值
	 */
	public MatrixEdge(double weight) {
		v1 = null;
		v2 = null;
		this.info = null;
		this.weight = weight;
	}
	/**
	 * 构造函数
	 * @param v1 第一个顶点
	 * @param v2 第二个顶点
	 * @param info 边的信息
	 * @param weight 权值
	 */
	public MatrixEdge( Object v1, Object v2, Object info, double weight ) {
		super(info, weight);
		this.v1 = v1;
		this.v2 = v2;
	}
	@Override
	public Object getFirstVertex() {
		return v1;
	}

	@Override
	public Object getSecondVertex() {
		return v2;
	}

	@Override
	public int compareTo(Object o) {
		Edge e = (Edge)o;
		if(this.weight > e.getWeight())
			return 1;
		else if(this.weight < e.getWeight())
			return -1;
		else
			return 0;
	}
	@Override
	public boolean equals(Object obj) {
		return ((Edge)obj).info.equals(info) &&  ((Edge)obj).getWeight() == this.weight;
	}
	@Override
	public String toString() {
		//return "边信息:" + info + "\t权值:" + weight + "\t顶点1:" + getFirstVertex() + "\t顶点2:" + getSecondVertex();
		return "" + weight;
	}
}


MatrixGraph.java

package datastructure.graph;

import datastructure.list.ArrayList;
import datastructure.list.List;
import datastructure.queue.ArrayQueue;
import datastructure.queue.Queue;
/**
 * 邻接矩阵法表示图
 * @author luoweifu 
 *
 */
public class MatrixGraph implements Graph {
	private static final int defaultSize = 10;
	private int maxLen;  //矩阵的最大长度
	private int edgeNum; //边的条数 
	private List vertexs;
	private Edge edges[][];
	
	private enum Visit{unvisited, visited};
	
	/**
	 * 构造函数
	 */
	public MatrixGraph() {
		maxLen = defaultSize;
		vertexs  = new ArrayList();
		edges = new MatrixEdge[maxLen][maxLen];
	}
	/**
	 * 构造函数
	 * @param vexs 顶点的数组
	 */
	public MatrixGraph(Object vexs[]) {
		maxLen = vexs.length;
		vertexs  = new ArrayList();
		edges = new MatrixEdge[maxLen][maxLen];
		for(int i=0; i<maxLen; i++) {
			vertexs.add(vexs[i]);
		}
	}
	@Override
	public void addEdge(Object v1, Object v2, double weight) {
		int i1 = vertexs.indexOf(v1);
		int i2 = vertexs.indexOf(v2);
		//System.out.println("i1: " + i1 + "  i2:" + i2);
		if(i1>=0 && i1<vertexs.size() && i2 >=0 && i2<vertexs.size()) {
			edges[i1][i2] = new MatrixEdge(v1, v2, null, weight);
			edgeNum ++;
		} else {
			throw new ArrayIndexOutOfBoundsException("顶点越界或对应的边不合法!");
		}
	}
	@Override
	public void addEdge(Object v1, Object v2, Object info, double weight) {
		int i1 = vertexs.indexOf(v1);
		int i2 = vertexs.indexOf(v2);
		if(i1>=0 && i1<vertexs.size() && i2 >=0 && i2<vertexs.size()) {
			edges[i1][i2] = new MatrixEdge( v1, v2, info, weight);
			edgeNum ++;
		} else {
			throw new ArrayIndexOutOfBoundsException("顶点越界或对应的边不合法!");
		}
	}
	@Override
	public void addVex(Object v) {
		vertexs.add(v);
		if(vertexs.size() > maxLen) {
			expand();
		}
	}
	private void expand() {
		MatrixEdge newEdges[][] = new MatrixEdge[2*maxLen][2*maxLen];
		for(int i=0; i<maxLen; i++) {
			for(int j=0; j<maxLen; j++) {
				newEdges[i][j] = (MatrixEdge) edges[i][j];
			}
		}
		edges = newEdges;
	}
	
	@Override
	public int getEdgeSize() {
		return edgeNum;
	}
	@Override
	public int getVertexSize() {
		return vertexs.size();
	}
	@Override
	public void removeEdge(Object v1, Object v2) {
		int i1 = vertexs.indexOf(v1);
		int i2 = vertexs.indexOf(v2);
		if(i1>=0 && i1<vertexs.size() && i2 >=0 && i2<vertexs.size()) {
			if(edges[i1][i2] == null) {
				try {
					throw new Exception("该边不存在!");
				} catch (Exception e) {
					e.printStackTrace();
				}
			} else {
				edges[i1][i2] = null;
				edgeNum --;
			}
		} else {
			throw new ArrayIndexOutOfBoundsException("顶点越界或对应的边不合法!");
		}
	}
	@Override
	public void removeVex(Object v) {
		int index = vertexs.indexOf(v);
		int n = vertexs.size();
		vertexs.remove(index);
		for(int i=0; i<n; i++){
			edges[i][n-1] = null;
			edges[n-1][i] = null;
		}
	}
	@Override
	public String printGraph() {
		StringBuilder sb = new StringBuilder();
		int n = getVertexSize();
		for (int i = 0; i < n; i++) {
			for(int j=0; j<n; j++) {
				sb.append("  " + edges[i][j]);
			}
			sb.append("\n");
		}
		return sb.toString();
	}
	@Override
	public void clear() {
		maxLen = defaultSize;
		vertexs.clear();
		edges = null;
	}
	@Override
	public String bfs(Object o) {
		Visit visit[] = new Visit[vertexs.size()];
		for(int i=0; i<vertexs.size(); i++)
			visit[i] = Visit.unvisited;
		StringBuilder sb = new StringBuilder();
		bfs(o, visit, sb);
		return sb.toString();
	}
	private void bfs(Object o, Visit[] visit, StringBuilder sb) {
		Queue queue = new ArrayQueue();
		
		int n = vertexs.indexOf(o);
		sb.append(o + "\t");
		visit[n] = Visit.visited;
		
		queue.push(o);
		while(!queue.isEmpty()) {
			Object u = queue.deQueue();
			Object v = getFirstVertex(u);
			while(null != v) {
				if(Visit.unvisited == visit[vertexs.indexOf(v)]) {
					sb.append(v + "\t");
					visit[vertexs.indexOf(v)] = Visit.visited;
					queue.push(v);
				}
				v = getNextVertex(u, v);
			}
		}
	}
	@Override
	public String dfs(Object o) {
		Visit visit[] = new Visit[vertexs.size()];
		for(int i=0; i<vertexs.size(); i++)
			visit[i] = Visit.unvisited;
		StringBuilder sb = new StringBuilder();
		dfs(o, visit, sb);
		return sb.toString();
	}
	private void dfs(Object o, Visit[] visit, StringBuilder sb) {
		int n = vertexs.indexOf(o);
		sb.append(o + "\t");
		visit[n] = Visit.visited;
		
		Object v = getFirstVertex(o);
		while(null != v) {
			if(Visit.unvisited == visit[vertexs.indexOf(v)])
				dfs(v, visit, sb);
			v = getNextVertex(o, v);
		}
	}
	@Override
	public Object getFirstVertex(Object v) {
		int i = vertexs.indexOf(v);
		if(i<0)
			throw new ArrayIndexOutOfBoundsException("顶点v不存在!");
		for(int col=0; col<vertexs.size(); col++)
			if(edges[i][col] != null)
				return vertexs.get(col);
		return null;
	}
	@Override
	public Object getNextVertex(Object v1, Object v2) {
		int i1 = vertexs.indexOf(v1);
		int i2 = vertexs.indexOf(v2);
		if(i1<0 || i2<0)
			throw new ArrayIndexOutOfBoundsException("顶点v不存在!");
		for(int col=i2+1; col<vertexs.size(); col++)
			if(edges[i1][col] != null)
				return vertexs.get(col);
		return null;
	}
}

测试程序Test.java

package datastructure.graph;

public class Test {

	public static void main(String args[]) {
		
		Object obj[] = { 'A', 'B', 'C', 'D', 'E', 'F' };
		
		//Graph graph = new MatrixGraph(obj);
		Graph graph = new MatrixGraph(obj);

		//graph.addVex('F');
		graph.addEdge('A','C',5);
		graph.addEdge('B','A',2);
		graph.addEdge('C','B',15);
		graph.addEdge('E','D',4);
		graph.addEdge('F','E',18);
		graph.addEdge('A', 'F', 60);
		graph.addEdge('C', 'F', 70);
		System.out.println(graph.printGraph());
		/*graph.removeEdge('A', 'C');
		System.out.println(graph.printGraph());
		graph.removeVex('E');
		System.out.println(graph.printGraph());*/
		System.out.println(graph.dfs('A'));
		System.out.println(graph.bfs('A'));
	}
}


分享到:
评论

相关推荐

    node-v8.15.0-linux-s390x.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    Java基础知识总结(超详细整理).txt

    Java基础知识总结(超详细整理)

    ISO IEC 27021-2017 信息技术.安全技术.信息安全管理系统专业人员的能力要求.pdf

    ISO IEC 27021-2017 信息技术.安全技术.信息安全管理系统专业人员的能力要求.pdf

    2024年中国DFB激光器芯片行业研究报告.docx

    2024年中国DFB激光器芯片行业研究报告

    公开整理-ESG视角下的多期DID构建数据集(2009-2022年).xlsx

    详细介绍及样例数据:https://blog.csdn.net/li514006030/article/details/138510939

    红帆OA(医疗版)漏洞细节未授权SQL注入请求注入数据包

    红帆OA(医疗版)是**一款专为医疗机构设计的办公自动化软件,旨在提高医院和相关卫生机构的工作效率和管理效能**。其功能特点包括: 1. **日常办公管理**:提供医院日常行政办公所需的基本功能,如文档处理、通知公告、会议管理等。 2. **科室管理**:支持医院内部各科室的管理需求,包括人员管理、资源分配、绩效考核等。 3. **信息集成**:能够整合医院内部的各类信息系统,实现数据共享和业务协同。 4. **多样化的医院类型支持**:适用于不同类型和规模的医院,如大学附属教学医院、综合性医院、专科医院、民营医院和集团医院等。 5. **业务范围广泛**:涵盖行政办公、医务室管理、科研管理、护士排班管理、党政管理和医患关系管理等多个方面。 6. **综合业务管理平台**:结合了卫生主管部门的管理规范和众多行业特色应用,是符合医院行业特点的综合业务管理平台。 7. **丰富的成功案例**:拥有众多成功案例,是医院综合业务管理软件中应用最广泛的之一。 需要注意的是,尽管红帆OA(医疗版)提供了强大的功能和广泛的应用场景,但任何软件系统都可能存在一定的安全风险,例如SQL注入漏洞等。因

    网页制作基础学习--HTML+CSS常用代码.txt

    网页制作基础学习--HTML+CSS常用代码

    ECHO HCS-2810ES_3810ES 操作手册

    HCS-2810ES_3810ES 说明书

    2024-2030中国3-吗啉丙磺酸市场现状研究分析与发展前景预测报告.docx

    2024-2030中国3-吗啉丙磺酸市场现状研究分析与发展前景预测报告

    node-v4.6.2-x64.msi

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    node-v8.8.1-linux-arm64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    QYResearch:2023年前10大高流量治疗系统企业占据全球98%的市场份额.docx

    QYResearch:2023年前10大高流量治疗系统企业占据全球98%的市场份额.docx

    0.Python实现3D建模工具(上)内含设计文档和源码.md

    0.Python实现3D建模工具(上)内含设计文档和源码.md

    node-v8.8.1-linux-x86.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    c语言文件读写操作代码

    c语言文件读写操作代码

    node-v9.8.0-linux-arm64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    公开整理-ESG视角下的多期DID构建数据集(2009-2022年).dta

    详细介绍及样例数据:https://blog.csdn.net/li514006030/article/details/138510939

    MATLAB编程高效实战:涵盖核心数学、科学计算、数据可视化及算法应用,助力工程师与研究人员的必备函数代码集

    这款“matlab常用的函数代码”资源是您的最佳助手!它详细介绍了matlab中常用的函数代码,包括基本数学运算、数组创建和操作、控制流、数据导入和导出、绘图、数学函数以及字符串操作等。无论您是工程师、研究人员、学生还是matlab爱好者,这个资源都适合您。 资源以通俗易懂的语言,配合实例演示,帮助您更好地理解和掌握matlab编程的核心技巧。您可以在学习matlab的过程中,将其作为参考资料,随时查阅和巩固知识点。也可以在准备matlab项目或考试时,通过这个资源进行复习和提升。此外,这个资源还可以作为教学资料,辅助教学和学习。 这个资源的优势在于它的全面性和实用性。它不仅涵盖了matlab中的常用函数代码,还提供了一些实用的编程技巧和经验分享。通过学习这个资源,您将能够更加熟练地使用matlab,解决实际问题和项目挑战。 这款“matlab常用的函数代码”资源旨在帮助您快速掌握matlab编程的基本知识和技能,为您的学术和职业生涯提供坚实的支持。还等什么呢?快来学习这个资源,开启您的matlab编程之旅吧!

    node-v8.9.3-linux-s390x.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    validate_before_handin.py

    validate_before_handin

Global site tag (gtag.js) - Google Analytics