Java数据结构与算法:无向图,有向图,带权图,图的遍历,最小生成树
文章目录
- 无向图
- 有向图
- 带权图
- 图的遍历
- 广度优先遍历
- 深度优先遍历
- 最小生成树
无向图
前面了解到树是有单一根结点的非线性结构,图(graph)也是一种非线性结构,其中的结点可以与许多其他的结点相连接,并且没有特定的父/子关系。图和图论的研究是数学和计算机科学中的完整学科。
与树一样,图由结点及结点间的连接组成。在图中,结点称为顶点(vertice,vertex),结点间的连接称为边(edge)。顶点通常由名字或标号来表示,例如可以标记顶点A、B、C和D。边可以由它所连接的顶点对来表示,例如顶点A和顶点B之间的一条边可以表示为(A,B)。
无向图中,表示边的顶点对是无序的。
图中表示边的顶点对是无序的图就是无向图(undirected graph),所以边(A,B)意味着A和B之间的连接是双向的,它也可以表示成(B,A)。如果图中两个顶点之间有边连接,则称这两个顶点是邻接的(adjacent)。邻接点有时也称为邻居(neighbor)。图中自己连接到自己的边称为自循环(self-loop)或悬挂(sling)。
含有最多边的无向图称为完全图(complete)。所有的顶点都相互连接,所以含n个顶点的完全图的边数为n(n-1)/2。
路径(path)是连接图中两个顶点的边的序列。在例图中,A、B、D是从A到D的一条路径。每个顺序对(A,B)及(B,D)都是一条边。无向图中的路径是双向的。路径长度是路径中所含边的数目(或包含顶点个数减1)。路径长度的定义和讨论树的时候给出的定义是一样的,实际上,树就是图。
如果无向图中任意两个顶点之间都有路径,则称它是连通的(connected)。第一个顶点和最后一个顶点是同一个顶点且没有重复边的路径称为一个环(circle)。没有环的图称为无环图(acyclic)。加入这些定义,我们可以明确地表明树和图的关系:一棵无向树是连通的、无环的无向图,其中的一个元素表示根。
有向图
图中的边是顶点的有序对的图称为有向图(directed graph,或称digraph)。这个定义表明有向图中的边(A,B)和边(B,A)是不同的、有方向的边。
有向连通图的定义看上去与无向图中的定义一样,即有向图中任意两个顶点之间都有路径相连。但是对于有向图来说,路径的定义是不同的,下图中第一个图是连通的,第二个图是不连通的,因为从任何顶点到顶点1都没有路径。
如果有向图中没有环,则有可能将顶点按某个次序进行排列。例如,如果从顶点A到顶点B有边,则将A排在B之前。这样得到的顶点次序就称为**拓扑序 **(topological order)。这个排序是非常有用的。
带权图
图中每条边都对应一个权值的图称为带权图(weighted graph),有时也称为网络(network)。下面的左图就是一个无向带权图,表示城市之间的航线和飞机票价。这个图可以用来确定从一个城市到另一个城市最便宜的出行路线。带权图中路径的权定义为路径中所含边上的权值之和。根据需要,带权图也可以是有向的,当从A地飞往B地的机票价格与从B地飞回A地的价格不同,如下面的右图,就是使用有向带权图的例子。
图的遍历
广度优先遍历
我们可以使用队列和迭代器建立图的广度优先遍历(breadth-first traversal),它类似于树的层序遍历。利用队列(traversalQueue)管理遍历过程,并用迭代器(iter)得到结果。第一步将开始顶点入队,并将开始顶点标记为已访问。然后开始循环,直到队列为空时结束。在循环中,从队列中取出第一个顶点,并将该顶点添加到迭代器中。接下来,将当前顶点中未被标记为已访问的所有邻接点入队,同时将这些顶点标记为已访问,然后重复循环。对每个已访问的顶点重复这个过程,直到队列为空时结束,此时意味着不能再到达任何新的顶点。这样迭代器中就包含了从给定顶点开始的广度优先遍历的结点序列。
下面的方法使用数组实现图的广度优先遍历的迭代算法。
public Iterator<T> iteratorBFS(int startIndex)
{int currentVertex; // 当前顶点LinkedQueue<Integer> traversalQueue = new LinkedQueue<Integer>(); //新建队列ArrayIterator<T> iter = new ArrayIterator<T>(); //新建迭代器if (!indexIsValid(startIndex))return iter; //初始顶点是否有效boolean[] visited = new boolean[numVertices]; //新建状态,是否已访问for (int vertexIndex = 0; vertexIndex < numVertices; vertexIndex++)visited[vertexIndex] = false; //将所有顶点设置为未访问traversalQueue.enqueue(startIndex);visited[startIndex] = true; //对第一个顶点的操作while (!traversalQueue.isEmpty()) //迭代终止条件,队列为空{currentVertex = traversalQueue.dequeue();iter.add(vertices[currentVertex]);for (int vertexIndex = 0; vertexIndex < numVertices; vertexIndex++)if (adjMatrix[currentVertex][vertexIndex] && !visited[vertexIndex]) //邻接矩阵为true并且未访问{traversalQueue.enqueue(vertexIndex);visited[vertexIndex] = true;}}return iter;
}
当且仅当从任意顶点开始的广度优先遍历中得到的顶点数等于图中所含的顶点数时,图是连通的。
深度优先遍历
利用栈替换队列,使用同样的逻辑可以构造图的深度优先遍历。不过算法中的一个不同点是,直到将顶点添加到迭代器时才将顶点标记为已访问。下面的方法是用数组实现的图的深度优先遍历算法。
public Iterator<T> iteratorDFS(int startIndex)
{int currentVertex;LinkedStack<Integer> traversalStack = new LinkedStack<Integer>();ArrayIterator<T> iter = new ArrayIterator<T>;boolean[] visited = new boolean[numVertices];boolean found;if (!indexIsValid(startIndex))return iter;for (int vertexIdx = 0; vertexIdx < numVertices; vertexIdx++)visited[vertexIdx] = false;traversalStack.push(startIndex);iter.add(vertices[startIndex]);visited[startIndex] = true;while (!traversalStack.isEmpty()){currentVertex = traversalStack.peek;found = false;for (int vertexIdx = 0; vertexIdx < numVertices && !found; vertexIdx++)if (adjMatrix[currentVertex][vertexIdx] && !visited[vertexIdx]){traversalStack.push(vertexIdx);iter.add(vertices[vertexIdx]);visited[vertexIdx] = true;found = true;}if (!found && !traversalStack.isEmpty())traversalStack.pop();}return iter;
}
最小生成树
生成树 (spanning tree)是包含图中所有顶点及图中部分(可能不是全部)边的一棵树。因为树总是图,对于有些图来说,图本身就是一棵生成树,所以这样的图的生成树就包含所有的边。生成树的一个重要应用就是找到带权图的最小生成树(minimum spanning tree)。最小生成树是其所含边的权值之和小于等于图的任意其他生成树的边的权值之和的生成树。
生成最小生成树的算法非常简洁。带权图的每条边由包括起始点、结束点及权值的三元组来表示。选择任意一点为起始点,将它加入最小生成树(MST)中。下一步,将包含起始点的所有边按权值大小加入一个最小堆中。下一步,从最小堆中删除权值最小的边,并将这条边和新的顶点加入MST中。接下来,将这个新顶点与其他尚不在MST中的顶点之间的所有边加入到最小堆中。继续这个过程,直到MST中已经包含原图中的所有顶点或是最小堆为空时停止。
Java数据结构与算法:无向图,有向图,带权图,图的遍历,最小生成树相关推荐
- 【Java数据结构与算法】第十六章 图
第十六章 图 文章目录 第十六章 图 一.图 1.介绍 2.基本术语 3.邻接矩阵 4.邻接表和逆邻接表 5.十字链表 二.深度优先遍历 三.广度优先遍历 四.代码实现 一.图 1.介绍 图相较于前面 ...
- 数据结构几种常见图的邻接矩阵的画法(有向图带权值,有向图不带权值,无向图带权值,无向图不带权值)
这不马上要期末考试了,复习的时候突然发现了有好几种图的邻接矩阵需要画,在网上找了半天结果发现也没有特别详细的总结,所以经过总结写一下吧,希望对有需要的人,有点帮助吧!!!!(如有不对还请见谅!!!!! ...
- Java 数据结构和算法(十五):无权无向图
Java数据结构和算法(十五)--无权无向图 前面我们介绍了树这种数据结构,树是由n(n>0)个有限节点通过连接它们的边组成一个具有层次关系的集合,把它叫做"树"是因为它看起 ...
- Java数据结构与算法 二
树结构基础部分 树 数组存储方式 优点:通过下标方式访问元素,速度快.对于有序数组,可使用二分查找提高检索速度. 缺点:如果要检索具体某个值,或者插入值(按一定顺序)会整体移动,效率较低 链式存储方式 ...
- Java数据结构和算法(第二版)
Java数据结构和算法(第二版) 下载地址 https://pan.baidu.com/s/112D5houIgu0eMs_i5o0Ujw 扫码下面二维码关注公众号回复 100066获取分享码 本书目 ...
- java数据结构与算法之(Queue)队列设计与实现
[版权申明]转载请注明出处(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/53375004 出自[zejian的博客] ...
- 数据结构 - Java -韩顺平 图解Java数据结构和算法
数据结构 Lesson 1 数据结构的知识总结 1. 几个经典的算法面试题 2. 线性结构与非线性结构 2.1 稀疏数组 sparsearray 2.2 队列 2.2.1 顺序队列: 2.2.2 环形 ...
- Java 数据结构与算法系列之冒泡排序
一.前言 相信大部分同学都已经学过数据结构与算法这门课了,并且我们可能都会发现一个现象就是我们所学过的数据结构与算法类的书籍基本都是使用 C 语言来写的,好像没见过使用 Java 写的数据结构与算法. ...
- Java数据结构与算法——树(基本概念,很重要)
声明:码字不易,转载请注明出处,欢迎文章下方讨论交流. 有网友私信我,期待我的下一篇数据结构.非常荣幸文章被认可,也非常感谢你们的监督. 前言:Java数据结构与算法专题会不定时更新,欢迎各位读者监督 ...
最新文章
- html语言 section type,HTML5中div、article、section的区别及使用介绍
- proximinty
- Kinect v2.0 for windows开发环境说明
- rcu宽限期_如何处理宽限期错误:静默失败不是一种选择
- 文本分类模型_多标签文本分类、情感倾向分析、文本实体抽取模型如何定制?...
- php会话控制区别和流程,PHP会话控制:cookie和session区别与用法深入理解_后端开发...
- mysql - 5.5.21_MySQL5.5.21安装配置教程(win7)
- 矩池云上cifar10使用说明
- ASP.NET是如何在IIS下工作的
- python 逆序_python编程题-句子的逆序
- jquery 省市区联动插件
- Windows 95 输入法编辑器
- vue复选框组件自定义对勾_关于vue的列表图片选中打钩操作
- snort实验(一)
- 服务器安装系统路径,裸金属服务器安装多路径软件
- 苹果x屏幕出现一条绿线_苹果iPad换屏幕出现售后问题解答
- 【Fungus笔记】No.12:Load Scene(加载场景 / 转场)
- 电脑主板资料库 10 【转至www.ongood.com.tw】【FreeXploiT收集整理】
- 题注自动带章节编号 and怎样删除Word题注标签和编号间的空格?
- 用火狐浏览器快速扒网页图片素材