1. import java.util.ArrayList;
  2. import java.util.List;
  3. // 模块E
  4. public class AdjMatrixGraph<E> {
  5. protected SeqList<E> vertexlist; // 顺序表存储图的顶点集合
  6. protected int[][] adjmatrix; // 图的邻接矩阵 二维图 存储的是每个顶点的名称(A,B,C,D....)
  7. ;
  8. // private final int MAX_WEIGHT = 10000;
  9. // -------一,构造图:增删改查-------------------------//
  10. public AdjMatrixGraph(int n) {// n为顶点的数目
  11. this.vertexlist = new SeqList<E>(n);
  12. this.adjmatrix = new int[n][n];
  13. ; i < n; i++)
  14. ; j < n; j++)
  15. : MAX_WEIGHT;
  16. // 对角线上为0,其他的都为无穷大。
  17. }
  18. // 构造函数内一个是字符串数组,一个是edge的set集合
  19. public AdjMatrixGraph(E[] vertices, Edge[] edges) {
  20. this(vertices.length);
  21. ; i < vertices.length; i++)
  22. insertVertex(vertices[i]);// 添加顶点
  23. ; j < edges.length; j++)
  24. insertEdge(edges[j]);// 添加边
  25. }
  26. // 构造函数内一个是数组集合,一个是edge的set集合
  27. public AdjMatrixGraph(SeqList<E> list, Edge[] edges) {
  28. this(list.length());
  29. this.vertexlist = list;
  30. ; j < edges.length; j++)
  31. insertEdge(edges[j]);
  32. }
  33. // 显示出一共顶点的数目
  34. public int vertexCount() {
  35. return this.vertexlist.length();
  36. }
  37. // 根据编号得到该顶点
  38. public E get(int i) {
  39. return this.vertexlist.get(i);
  40. }
  41. public boolean insertVertex(E vertex) { // 插入一个顶点,若插入成功,返回true
  42. return this.vertexlist.add(vertex);
  43. }
  44. public boolean insertEdge(int i, int j, int weight)
  45. // 插入一条权值为weight的边<vi,vj>,若该边已有,则不插入
  46. {
  47. && i < vertexCount() && j >= 0 && j < vertexCount()
  48. && i != j && adjmatrix[i][j] == MAX_WEIGHT) {
  49. // 先判断该边两个顶点的编号是否在范围,该边的值是否为最大值,来确定所添加边的值是否存在;
  50. this.adjmatrix[i][j] = weight;// 添加权值
  51. return true;
  52. }
  53. return false;
  54. }
  55. public boolean insertEdge(Edge edge) {
  56. if (edge != null)
  57. ;
  58. return insertEdge(edge.start, edge.dest, edge.weight);
  59. }
  60. public String toString() {
  61. String str = "顶点集合: " + vertexlist.toString() + "\n";
  62. str += "邻近矩阵:    \n";
  63. int n = vertexCount();
  64. ; i < n; i++) {
  65. ; j < n; j++) {
  66. if (adjmatrix[i][j] == MAX_WEIGHT)
  67. str += " ∞";// 最大值(不存在)的时候的显示方式;
  68. else
  69. str += " " + adjmatrix[i][j];// 每一个顶点到其他顶点的权值
  70. }
  71. str += "\n";
  72. }
  73. return str;
  74. }
  75. public boolean removeEdge(int i, int j) // 删除边〈vi,vj〉,若成功,返回T
  76. {
  77. && i < vertexCount() && j >= 0 && j < vertexCount()
  78. && i != j && this.adjmatrix[i][j] != MAX_WEIGHT) {
  79. // 判断该边的两个顶点是否存在,以及改边的值是否为最大值来判断改边是否存在;
  80. this.adjmatrix[i][j] = MAX_WEIGHT; // 设置该边的权值为无穷大,说明已不存在;
  81. return true;
  82. }
  83. return false;
  84. }
  85. public boolean removeVertex(int v) // 删除序号为v的顶点及其关联的边
  86. {
  87. int n = vertexCount(); // 删除之前的顶点数
  88. && v < n) {// V的要求范围
  89. this.vertexlist.remove(v); // 删除顺序表的第i个元素,顶点数已减一
  90. ; i++)
  91. ; j < n; j++)
  92. ][j]; // 邻接矩阵:删除点以下往上移动一位
  93. ; j++)
  94. ; i < n - 1; i++)
  95. ]; // 邻接矩阵:删除点以右往左移动一位
  96. return true;
  97. }
  98. return false;
  99. }
  100. public int getFirstNeighbor(int v) // 返回顶点v的第一个邻接顶点的序号
  101. {
  102. );
  103. } // 若不存在第一个邻接顶点,则返回-1
  104. public int getNextNeighbor(int v, int w) { // 返回v在w后的下一个邻接顶点
  105. && v < vertexCount() && w >= -1 && w < vertexCount()// 对v
  106. // w的范围限定
  107. && v != w)
  108. ; j < vertexCount(); j++)
  109. // w=-1时,j从0开始寻找下一个邻接顶点
  110. && adjmatrix[v][j] < MAX_WEIGHT)
  111. // 遍历和v相关的点,得到下一个点
  112. return j;
  113. ;
  114. }
  115. // -------二,最小生成树-------------------------//
  116. /*
  117. * 普里姆算法的基本思想: 取图中任意一个顶点 v 作为生成树的根,之后往生成树上添加新的顶点 w。 在添加的顶点 w
  118. * 和已经在生成树上的顶点v之间必定存在一条边, 并且该边的权值在所有连通顶点 v 和 w 之间的边中取值最小。
  119. * 之后继续往生成树上添加顶点,直至生成树上含有 n-1 个顶点为止。
  120. */
  121. public AdjMatrixGraph minSpanTree_prim() {
  122. ]; // n个顶点最小生成树有n-1条边
  123. int un;
  124. List<Integer> u = new ArrayList<Integer>();// 存放所有已访问过的顶点集合
  125. );// 起始点默认为标识为0的顶点
  126. ; i < this.vertexCount() - 1; i++) {
  127. int minweight = MAX_WEIGHT;// 最小边的时候,权值
  128. int minstart = MAX_WEIGHT;// 最小边的时候,起点
  129. int mindest = MAX_WEIGHT;// 最小边的时候,终点
  130. ; j < u.size(); j++) {
  131. un = u.get(j);
  132. ; k < this.vertexCount(); k++) {
  133. // 获取最小值的条件:1.该边比当前情况下的最小值小;2.该边还未访问过;
  134. if ((minweight > adjmatrix[un][k]) && (!u.contains(k))) {
  135. minweight = adjmatrix[un][k];
  136. minstart = un;
  137. mindest = k;
  138. }
  139. }
  140. }
  141. System.out.println("一次遍历所添加的最小边:他的权值,起点,终点分别为:weight:" + minweight
  142. + "start:" + minstart + "dest:" + mindest);
  143. u.add(mindest);
  144. Edge e = new Edge(minstart, mindest, adjmatrix[minstart][mindest]);
  145. mst[i] = e;
  146. }
  147. return new AdjMatrixGraph(this.vertexlist, mst); // 构造最小生成树相应的图对象
  148. }
  149. /*
  150. * public AdjMatrixGraph minSpanTree_kruskal() { }
  151. */
  152. // -------三,图的遍历(广度遍历,深度遍历)-------------------------//
  153. public void DFStraverse() {
  154. int n = this.vertexCount();
  155. boolean[] visited = new boolean[n];
  156. ; i < n; i++) {
  157. visited[i] = false;
  158. }
  159. // 编号0为起始点,进行一次深度优先遍历(一次得到一个连通分量)
  160. ; j < n; j++) {
  161. if (!visited[j]) {
  162. System.out.println("以该顶点为" + j + "起始点的遍历:");
  163. this.DFS(j, visited);
  164. }
  165. }
  166. }
  167. // 参数1:遍历起始点的编号,参数2:记录各个顶点是否被访问过
  168. public void DFS(int v, boolean[] visited2) {
  169. boolean[] visited = visited2;
  170. visited[v] = true;
  171. System.out.println("遍历顶点" + v);
  172. ; w = this
  173. .getNextNeighbor(v, w)) {
  174. if (!visited[w]) {
  175. visited[w] = true;
  176. DFS(w, visited);
  177. }
  178. }
  179. }
  180. public void BFStraverse() {
  181. int n = this.vertexCount();
  182. boolean[] visited = new boolean[n];
  183. MyQueue myqueue = new MyQueue();
  184. ; i < n; i++) {
  185. visited[i] = false;
  186. }
  187. ; j < n; j++) {
  188. if (!visited[j]) {
  189. visited[j] = true;
  190. System.out.println("遍历起点:" + j);
  191. myqueue.EnQueue(j);
  192. while (!myqueue.empty()) {
  193. int v = (Integer) myqueue.DeQueue();
  194. System.out.println("遍历点:" + v);
  195. ; w = this
  196. .getNextNeighbor(v, w)) {
  197. if (!visited[w]) {
  198. visited[w] = true;
  199. myqueue.EnQueue(w);
  200. }
  201. }
  202. }
  203. }
  204. }
  205. }
  206. // -------四,图的最短路径Dijkstra算法-------------------------//
  207. public void Dijkstra() {
  208. int n = this.vertexCount();
  209. int minweight = MAX_WEIGHT;
  210. ;
  211. int[] minmatrix = new int[n];// 存放当前起始点到其余各个顶点的距离;
  212. boolean[] isS = new boolean[n];// 判断各个是否被访问过
  213. String[] route = new String[n];// 每个字符串是显示对应顶点最短距离的路径;
  214. ; i < n; i++) {// 初始化
  215. ][i];
  216. isS[i] = false;
  217. route[i] = "起点->" + i;
  218. }
  219. ; i < n; i++) {
  220. // 选择 当前 和起点 连通的,且值最小的顶点;
  221. ; k < n; k++) {
  222. if (!isS[k]) {
  223. if (minmatrix[k] < minweight) {
  224. minweight = minmatrix[k];
  225. minUn = k;
  226. }
  227. }
  228. }
  229. isS[minUn] = true;// 将该点设置为已访问;
  230. ; j < n; j++) {
  231. if (!isS[j]) {// 判断:该顶点还没加入到S中/属于U-S;
  232. if (minweight + adjmatrix[minUn][j] < minmatrix[j]) {
  233. // 通过当下最小值 访问到得其他顶点的距离小于原先的最小值 则进行交换值
  234. minmatrix[j] = minweight + adjmatrix[minUn][j];
  235. route[j] = route[minUn] + "->" + j;
  236. }
  237. }
  238. }
  239. minweight = MAX_WEIGHT;// 因为要放到下一个循环中,所以一定要重设置一下,回到最大值
  240. }
  241. ; m < n; m++) {
  242. System.out.println("从V0出发到达" + m + "点");
  243. if (minmatrix[m] == MAX_WEIGHT) {
  244. System.out.println("没有到达该点的路径");
  245. } else {
  246. System.out.println("当前从V0出发到达该点的最短距离:" + minmatrix[m]);
  247. System.out.println("当前从V0出发到达该点的最短距离:" + route[m]);
  248. }
  249. }
  250. }
  251. // -------五,图的连通性-------------------------//
  252. public boolean isConnect() {
  253. int n = this.vertexCount();
  254. boolean[] visited = new boolean[n];
  255. // 记录不能一次深度优先遍历通过的数目
  256. // 全部顶点作为出发点开始遍历,如果全部都不能一次遍历通过(notConnectNum == n),说明该图不连通。
  257. ;
  258. ; j < n; j++) {
  259. ; i < n; i++) {
  260. visited[i] = false;
  261. }
  262. this.DFS(j, visited);
  263. ; k < n; k++) {
  264. System.out.println(visited[k]);
  265. if (visited[k] == false) {
  266. notConnectNum++;
  267. break;// 一旦有没有被遍历到的顶点(说明该顶点不属于该连通分量),跳出循环
  268. }
  269. }
  270. }
  271. if (notConnectNum == n) {
  272. System.out.println("此图是不连通的");
  273. return false;
  274. } else {
  275. System.out.println("此图是连通的");
  276. return true;
  277. }
  278. }
  279. // -------六,图的拓扑排序-------------------------//
  280. public void topologicalSort() {
  281. int n = this.vertexCount();
  282. int[] indegree = new int[n];
  283. MyStack mystack = new MyStack();
  284. String route = "拓扑排序出发:";
  285. ;
  286. ; i < n; i++) {
  287. ;
  288. ; j < n; j++) {//获取每一个顶点的入度
  289. && adjmatrix[j][i] != MAX_WEIGHT) {
  290. ;
  291. }
  292. }//先将入度为0的顶点加入到栈中
  293. ) {
  294. mystack.push(i);
  295. }
  296. }
  297. while (!mystack.empty()) {
  298. int v = (Integer) mystack.pop();//从栈中删除该顶点
  299. route += "->" + v;
  300. ++count;
  301. ; w = this
  302. .getNextNeighbor(v, w)) {
  303. ;//因为该顶点被“删除”,所有以该顶点为弧尾的边的弧头的入度减一
  304. ) {
  305. mystack.push(w);//先将入度为0的顶点加入到栈中
  306. }
  307. }
  308. }
  309. if (count < n) {//当经历拓扑排序遍历后,所有顶点都被“删除”时(count=n),此时实现拓扑排序
  310. System.out.println("存在回路,不满足拓扑排序的条件");
  311. } else {
  312. System.out.println("实现拓扑排序" + route);
  313. }
  314. }
  315. }

数据结构-图-Java实现:有向图 图存储(邻接矩阵),最小生成树,广度深度遍历,图的连通性,最短路径1的更多相关文章

  1. 数据结构实验之图论一:基于邻接矩阵的广度优先搜索遍历 (SDUT 2141)

    #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> ...

  2. SDUT-2124_基于邻接矩阵的广度优先搜索遍历

    数据结构实验之图论一:基于邻接矩阵的广度优先搜索遍历 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 给定一个无向连通图 ...

  3. 从上面的集合框架图可以看到,Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射

    从上面的集合框架图可以看到,Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射.Collection 接口又有 3 ...

  4. 邻接矩阵实现图的存储,DFS,BFS遍历

    图的遍历一般由两者方式:深度优先搜索(DFS),广度优先搜索(BFS),深度优先就是先访问完最深层次的数据元素,而BFS其实就是层次遍历,每一层每一层的遍历. 1.深度优先搜索(DFS) 我一贯习惯有 ...

  5. 数据结构C语言版 有向图的十字链表存储表示和实现

    /*1wangxiaobo@163.com 数据结构C语言版 有向图的十字链表存储表示和实现 P165 编译环境:Dev-C++ 4.9.9.2 */ #include <stdio.h> ...

  6. c++邻接表存储图(无向),并用广度优先和深度优先遍历(实验)

    一开始我是用c写的,后面才发现广搜要用到队列,所以我就直接使用c++的STL队列来写, 因为不想再写多一个队列了.这次实验写了两个多钟,因为要边写边思考,太菜了哈哈. 主要参考<大话数据结构&g ...

  7. 重新整理数据结构与算法(c#)—— 图的深度遍历和广度遍历[十一]

    参考网址:https://www.cnblogs.com/aoximin/p/13162635.html 前言 简介图: 在数据的逻辑结构D=(KR)中,如果K中结点对于关系R的前趋和后继的个数不加限 ...

  8. Java生鲜电商平台-商城后台架构与原型图实战

    Java生鲜电商平台-商城后台架构与原型图实战 说明:生鲜电商平台的运营平台,其中需要很多的功能进行管理.目前把架构与原型图实战分享给大家,希望对大家有用. 仪表盘/首页,简单统计,报表页,运营快捷口 ...

  9. Java设计模式(一):设计模式概述、UML图、设计原则

    1 设计模式概述 1.1 软件设计模式的产生背景 "设计模式"最初并不是出现在软件设计中,而是被用于建筑领域的设计中. 1977年美国著名建筑大师.加利福尼亚大学伯克利分校环境结构 ...

随机推荐

  1. linux 基础知识

    一.命令的基本用法 (1).Linux里面的命令分为内置命令和独立的命令. (2).命令行的基本使用方法            Cli Syntax                    #命令和选项 ...

  2. JQuery_DOM 节点操作之创建节点、插入节点

    一.创建节点 为了使页面更加智能化,有时我们想动态的在html 结构页面添加一个元素标签,那么在插入之前首先要做的动作就是:创建节点 <script type="text/javasc ...

  3. Webpack、Browserify和Gulp

    https://www.zhihu.com/question/37020798 https://www.zhihu.com/question/35479764

  4. contiki-rime-单跳单播

    rucb是单跳单播的最顶层,将数据以块为单位进行传输(Bulk transfer). ruc,Reliable communication,保证可靠通信,主要实现确认和序列功能. suc,Stubbo ...

  5. 哈希表(Hash Table)

    参考: Hash table - Wiki Hash table_百度百科 从头到尾彻底解析Hash表算法 谈谈 Hash Table 我们身边的哈希,最常见的就是perl和python里面的字典了, ...

  6. Spring IOC/DI- 3 different types

    理论: IOC(Inversion of Control控制反转) DI(依赖注入) (Dependency Injection)   它不是一种技术而是一种思想.当初IOC理论的提出就是为了解决对象 ...

  7. HashMap多线程并发问题分析

    转载: HashMap多线程并发问题分析 并发问题的症状 多线程put后可能导致get死循环 从前我们的Java代码因为一些原因使用了HashMap这个东西,但是当时的程序是单线程的,一切都没有问题. ...

  8. CSS样式应用

    CSS样式应用的方法: (1)行内样式,将css样式直接放到标签当中,一般都是放入标签的style属性中,它是最方便的一种样式,也是最不方便修改的样式.如下: (2)内嵌式,通过将css写在网页源文件 ...

  9. Sql Server如何新建计划任务

    打开Sql Server数据库,在管理中找到维护计划功能,右击维护计划选择维护计划向导.如图所示: 打开维护计划向导后,在第一个步骤下输入计划名称. 输入完计划名称后,点击右下角的更改按钮,这里是配置 ...

  10. 常用shell

    常用shell命令 选项 参数 ctrl+alt+f(1-6)字符界面7图形界面 ls 列出当前目录 -a 查看文件的详细信息 -L 查看所有的文件 包括隐藏文件 pwd 查看当前的工作路径 cd 切 ...