数据结构-图-Java实现:有向图 图存储(邻接矩阵),最小生成树,广度深度遍历,图的连通性,最短路径1
- import java.util.ArrayList;
- import java.util.List;
- // 模块E
- public class AdjMatrixGraph<E> {
- protected SeqList<E> vertexlist; // 顺序表存储图的顶点集合
- protected int[][] adjmatrix; // 图的邻接矩阵 二维图 存储的是每个顶点的名称(A,B,C,D....)
- ;
- // private final int MAX_WEIGHT = 10000;
- // -------一,构造图:增删改查-------------------------//
- public AdjMatrixGraph(int n) {// n为顶点的数目
- this.vertexlist = new SeqList<E>(n);
- this.adjmatrix = new int[n][n];
- ; i < n; i++)
- ; j < n; j++)
- : MAX_WEIGHT;
- // 对角线上为0,其他的都为无穷大。
- }
- // 构造函数内一个是字符串数组,一个是edge的set集合
- public AdjMatrixGraph(E[] vertices, Edge[] edges) {
- this(vertices.length);
- ; i < vertices.length; i++)
- insertVertex(vertices[i]);// 添加顶点
- ; j < edges.length; j++)
- insertEdge(edges[j]);// 添加边
- }
- // 构造函数内一个是数组集合,一个是edge的set集合
- public AdjMatrixGraph(SeqList<E> list, Edge[] edges) {
- this(list.length());
- this.vertexlist = list;
- ; j < edges.length; j++)
- insertEdge(edges[j]);
- }
- // 显示出一共顶点的数目
- public int vertexCount() {
- return this.vertexlist.length();
- }
- // 根据编号得到该顶点
- public E get(int i) {
- return this.vertexlist.get(i);
- }
- public boolean insertVertex(E vertex) { // 插入一个顶点,若插入成功,返回true
- return this.vertexlist.add(vertex);
- }
- public boolean insertEdge(int i, int j, int weight)
- // 插入一条权值为weight的边<vi,vj>,若该边已有,则不插入
- {
- && i < vertexCount() && j >= 0 && j < vertexCount()
- && i != j && adjmatrix[i][j] == MAX_WEIGHT) {
- // 先判断该边两个顶点的编号是否在范围,该边的值是否为最大值,来确定所添加边的值是否存在;
- this.adjmatrix[i][j] = weight;// 添加权值
- return true;
- }
- return false;
- }
- public boolean insertEdge(Edge edge) {
- if (edge != null)
- ;
- return insertEdge(edge.start, edge.dest, edge.weight);
- }
- public String toString() {
- String str = "顶点集合: " + vertexlist.toString() + "\n";
- str += "邻近矩阵: \n";
- int n = vertexCount();
- ; i < n; i++) {
- ; j < n; j++) {
- if (adjmatrix[i][j] == MAX_WEIGHT)
- str += " ∞";// 最大值(不存在)的时候的显示方式;
- else
- str += " " + adjmatrix[i][j];// 每一个顶点到其他顶点的权值
- }
- str += "\n";
- }
- return str;
- }
- public boolean removeEdge(int i, int j) // 删除边〈vi,vj〉,若成功,返回T
- {
- && i < vertexCount() && j >= 0 && j < vertexCount()
- && i != j && this.adjmatrix[i][j] != MAX_WEIGHT) {
- // 判断该边的两个顶点是否存在,以及改边的值是否为最大值来判断改边是否存在;
- this.adjmatrix[i][j] = MAX_WEIGHT; // 设置该边的权值为无穷大,说明已不存在;
- return true;
- }
- return false;
- }
- public boolean removeVertex(int v) // 删除序号为v的顶点及其关联的边
- {
- int n = vertexCount(); // 删除之前的顶点数
- && v < n) {// V的要求范围
- this.vertexlist.remove(v); // 删除顺序表的第i个元素,顶点数已减一
- ; i++)
- ; j < n; j++)
- ][j]; // 邻接矩阵:删除点以下往上移动一位
- ; j++)
- ; i < n - 1; i++)
- ]; // 邻接矩阵:删除点以右往左移动一位
- return true;
- }
- return false;
- }
- public int getFirstNeighbor(int v) // 返回顶点v的第一个邻接顶点的序号
- {
- );
- } // 若不存在第一个邻接顶点,则返回-1
- public int getNextNeighbor(int v, int w) { // 返回v在w后的下一个邻接顶点
- && v < vertexCount() && w >= -1 && w < vertexCount()// 对v
- // w的范围限定
- && v != w)
- ; j < vertexCount(); j++)
- // w=-1时,j从0开始寻找下一个邻接顶点
- && adjmatrix[v][j] < MAX_WEIGHT)
- // 遍历和v相关的点,得到下一个点
- return j;
- ;
- }
- // -------二,最小生成树-------------------------//
- /*
- * 普里姆算法的基本思想: 取图中任意一个顶点 v 作为生成树的根,之后往生成树上添加新的顶点 w。 在添加的顶点 w
- * 和已经在生成树上的顶点v之间必定存在一条边, 并且该边的权值在所有连通顶点 v 和 w 之间的边中取值最小。
- * 之后继续往生成树上添加顶点,直至生成树上含有 n-1 个顶点为止。
- */
- public AdjMatrixGraph minSpanTree_prim() {
- ]; // n个顶点最小生成树有n-1条边
- int un;
- List<Integer> u = new ArrayList<Integer>();// 存放所有已访问过的顶点集合
- );// 起始点默认为标识为0的顶点
- ; i < this.vertexCount() - 1; i++) {
- int minweight = MAX_WEIGHT;// 最小边的时候,权值
- int minstart = MAX_WEIGHT;// 最小边的时候,起点
- int mindest = MAX_WEIGHT;// 最小边的时候,终点
- ; j < u.size(); j++) {
- un = u.get(j);
- ; k < this.vertexCount(); k++) {
- // 获取最小值的条件:1.该边比当前情况下的最小值小;2.该边还未访问过;
- if ((minweight > adjmatrix[un][k]) && (!u.contains(k))) {
- minweight = adjmatrix[un][k];
- minstart = un;
- mindest = k;
- }
- }
- }
- System.out.println("一次遍历所添加的最小边:他的权值,起点,终点分别为:weight:" + minweight
- + "start:" + minstart + "dest:" + mindest);
- u.add(mindest);
- Edge e = new Edge(minstart, mindest, adjmatrix[minstart][mindest]);
- mst[i] = e;
- }
- return new AdjMatrixGraph(this.vertexlist, mst); // 构造最小生成树相应的图对象
- }
- /*
- * public AdjMatrixGraph minSpanTree_kruskal() { }
- */
- // -------三,图的遍历(广度遍历,深度遍历)-------------------------//
- public void DFStraverse() {
- int n = this.vertexCount();
- boolean[] visited = new boolean[n];
- ; i < n; i++) {
- visited[i] = false;
- }
- // 编号0为起始点,进行一次深度优先遍历(一次得到一个连通分量)
- ; j < n; j++) {
- if (!visited[j]) {
- System.out.println("以该顶点为" + j + "起始点的遍历:");
- this.DFS(j, visited);
- }
- }
- }
- // 参数1:遍历起始点的编号,参数2:记录各个顶点是否被访问过
- public void DFS(int v, boolean[] visited2) {
- boolean[] visited = visited2;
- visited[v] = true;
- System.out.println("遍历顶点" + v);
- ; w = this
- .getNextNeighbor(v, w)) {
- if (!visited[w]) {
- visited[w] = true;
- DFS(w, visited);
- }
- }
- }
- public void BFStraverse() {
- int n = this.vertexCount();
- boolean[] visited = new boolean[n];
- MyQueue myqueue = new MyQueue();
- ; i < n; i++) {
- visited[i] = false;
- }
- ; j < n; j++) {
- if (!visited[j]) {
- visited[j] = true;
- System.out.println("遍历起点:" + j);
- myqueue.EnQueue(j);
- while (!myqueue.empty()) {
- int v = (Integer) myqueue.DeQueue();
- System.out.println("遍历点:" + v);
- ; w = this
- .getNextNeighbor(v, w)) {
- if (!visited[w]) {
- visited[w] = true;
- myqueue.EnQueue(w);
- }
- }
- }
- }
- }
- }
- // -------四,图的最短路径Dijkstra算法-------------------------//
- public void Dijkstra() {
- int n = this.vertexCount();
- int minweight = MAX_WEIGHT;
- ;
- int[] minmatrix = new int[n];// 存放当前起始点到其余各个顶点的距离;
- boolean[] isS = new boolean[n];// 判断各个是否被访问过
- String[] route = new String[n];// 每个字符串是显示对应顶点最短距离的路径;
- ; i < n; i++) {// 初始化
- ][i];
- isS[i] = false;
- route[i] = "起点->" + i;
- }
- ; i < n; i++) {
- // 选择 当前 和起点 连通的,且值最小的顶点;
- ; k < n; k++) {
- if (!isS[k]) {
- if (minmatrix[k] < minweight) {
- minweight = minmatrix[k];
- minUn = k;
- }
- }
- }
- isS[minUn] = true;// 将该点设置为已访问;
- ; j < n; j++) {
- if (!isS[j]) {// 判断:该顶点还没加入到S中/属于U-S;
- if (minweight + adjmatrix[minUn][j] < minmatrix[j]) {
- // 通过当下最小值 访问到得其他顶点的距离小于原先的最小值 则进行交换值
- minmatrix[j] = minweight + adjmatrix[minUn][j];
- route[j] = route[minUn] + "->" + j;
- }
- }
- }
- minweight = MAX_WEIGHT;// 因为要放到下一个循环中,所以一定要重设置一下,回到最大值
- }
- ; m < n; m++) {
- System.out.println("从V0出发到达" + m + "点");
- if (minmatrix[m] == MAX_WEIGHT) {
- System.out.println("没有到达该点的路径");
- } else {
- System.out.println("当前从V0出发到达该点的最短距离:" + minmatrix[m]);
- System.out.println("当前从V0出发到达该点的最短距离:" + route[m]);
- }
- }
- }
- // -------五,图的连通性-------------------------//
- public boolean isConnect() {
- int n = this.vertexCount();
- boolean[] visited = new boolean[n];
- // 记录不能一次深度优先遍历通过的数目
- // 全部顶点作为出发点开始遍历,如果全部都不能一次遍历通过(notConnectNum == n),说明该图不连通。
- ;
- ; j < n; j++) {
- ; i < n; i++) {
- visited[i] = false;
- }
- this.DFS(j, visited);
- ; k < n; k++) {
- System.out.println(visited[k]);
- if (visited[k] == false) {
- notConnectNum++;
- break;// 一旦有没有被遍历到的顶点(说明该顶点不属于该连通分量),跳出循环
- }
- }
- }
- if (notConnectNum == n) {
- System.out.println("此图是不连通的");
- return false;
- } else {
- System.out.println("此图是连通的");
- return true;
- }
- }
- // -------六,图的拓扑排序-------------------------//
- public void topologicalSort() {
- int n = this.vertexCount();
- int[] indegree = new int[n];
- MyStack mystack = new MyStack();
- String route = "拓扑排序出发:";
- ;
- ; i < n; i++) {
- ;
- ; j < n; j++) {//获取每一个顶点的入度
- && adjmatrix[j][i] != MAX_WEIGHT) {
- ;
- }
- }//先将入度为0的顶点加入到栈中
- ) {
- mystack.push(i);
- }
- }
- while (!mystack.empty()) {
- int v = (Integer) mystack.pop();//从栈中删除该顶点
- route += "->" + v;
- ++count;
- ; w = this
- .getNextNeighbor(v, w)) {
- ;//因为该顶点被“删除”,所有以该顶点为弧尾的边的弧头的入度减一
- ) {
- mystack.push(w);//先将入度为0的顶点加入到栈中
- }
- }
- }
- if (count < n) {//当经历拓扑排序遍历后,所有顶点都被“删除”时(count=n),此时实现拓扑排序
- System.out.println("存在回路,不满足拓扑排序的条件");
- } else {
- System.out.println("实现拓扑排序" + route);
- }
- }
- }
数据结构-图-Java实现:有向图 图存储(邻接矩阵),最小生成树,广度深度遍历,图的连通性,最短路径1的更多相关文章
- 数据结构实验之图论一:基于邻接矩阵的广度优先搜索遍历 (SDUT 2141)
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> ...
- SDUT-2124_基于邻接矩阵的广度优先搜索遍历
数据结构实验之图论一:基于邻接矩阵的广度优先搜索遍历 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 给定一个无向连通图 ...
- 从上面的集合框架图可以看到,Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射
从上面的集合框架图可以看到,Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射.Collection 接口又有 3 ...
- 邻接矩阵实现图的存储,DFS,BFS遍历
图的遍历一般由两者方式:深度优先搜索(DFS),广度优先搜索(BFS),深度优先就是先访问完最深层次的数据元素,而BFS其实就是层次遍历,每一层每一层的遍历. 1.深度优先搜索(DFS) 我一贯习惯有 ...
- 数据结构C语言版 有向图的十字链表存储表示和实现
/*1wangxiaobo@163.com 数据结构C语言版 有向图的十字链表存储表示和实现 P165 编译环境:Dev-C++ 4.9.9.2 */ #include <stdio.h> ...
- c++邻接表存储图(无向),并用广度优先和深度优先遍历(实验)
一开始我是用c写的,后面才发现广搜要用到队列,所以我就直接使用c++的STL队列来写, 因为不想再写多一个队列了.这次实验写了两个多钟,因为要边写边思考,太菜了哈哈. 主要参考<大话数据结构&g ...
- 重新整理数据结构与算法(c#)—— 图的深度遍历和广度遍历[十一]
参考网址:https://www.cnblogs.com/aoximin/p/13162635.html 前言 简介图: 在数据的逻辑结构D=(KR)中,如果K中结点对于关系R的前趋和后继的个数不加限 ...
- Java生鲜电商平台-商城后台架构与原型图实战
Java生鲜电商平台-商城后台架构与原型图实战 说明:生鲜电商平台的运营平台,其中需要很多的功能进行管理.目前把架构与原型图实战分享给大家,希望对大家有用. 仪表盘/首页,简单统计,报表页,运营快捷口 ...
- Java设计模式(一):设计模式概述、UML图、设计原则
1 设计模式概述 1.1 软件设计模式的产生背景 "设计模式"最初并不是出现在软件设计中,而是被用于建筑领域的设计中. 1977年美国著名建筑大师.加利福尼亚大学伯克利分校环境结构 ...
随机推荐
- c++程序判断系统是Linux还是Windows
用C++来实现,本来想了很多,后来越写越烂,而且结果总是不尽人意,干脆这样子好了: int main() { int judge = system("cls"); ) cout & ...
- Contiki-一个进程的例子
进程调度器 进程调度器的作用是调用进程.进程调度器通过调用实现进程线程的函数来调用进程.Contiki中所有的进程被设计为响应传递到进程中的事件,或者相应进程请求的轮询.进程调度器在调度进程的时候会将 ...
- VB用windows API激活子窗体
http://files.cnblogs.com/files/liuzhaoyzz/%E6%BF%80%E6%B4%BB%E5%AD%90%E7%AA%97%E4%BD%93.rar setforeg ...
- js触发按钮点击事件
js触发按钮点击事件 博客分类: javascript 模拟JS触发按钮点击功能 <html> <head> <title>usually function&l ...
- Android编译环境折腾记
题记:感觉是时候写点什么了=_=! 第一次安装了ubuntu14.04.5,官网下载的iso,官网下的jar,编译android4.x需要安装jdk6,更高的版本会有问题,baidu到很多搭建环境的步 ...
- 【转】Python 日期和时间
本文转自:http://www.runoob.com/python/python-date-time.html Python 程序能用很多方式处理日期和时间,转换日期格式是一个常见的功能. Pytho ...
- 重温Javascript第一章
一.script标签 script标签有6个属性,其中一个废弃,五个可选. 按照传统的写法,<script>的标签都是放在<head>元素中,但是在<head>中包 ...
- web前端代码编写体验
最好是使用HTML5的有意义的标签,并尝试在不同的,老版本的浏览器中也保持一致,不然你会发现,满屏都是div,后期进行代码验证,修改和查找简直是一场大灾难. 而且,编写代码的时候,为了方便以后代码的复 ...
- jquery.fullPage.js全屏滚动插件教程演示
css部分(此处需要导入jquery.fullPage.css) <style> .section { text-align: center; font: 50px "Micro ...
- iOS---自动布局
自动布局的发展 1.frame:通过代码计算 frame iPhone3GS \ iPhone4 \ iPhone4S 屏幕的物理尺寸是一样的(无需屏幕适配), 而且一个当时的应用要么是横屏要么是竖屏 ...