以邻接表的形式创建带权值的有向图即有向网
2018-01-19 00:00
483 查看
摘要: 邻接表(Adjacency List)是图的一种链式存储结构。在邻接表中,对图中的每个顶点都建立一个单链表,第i个单链表中的结点表示依附于该顶点的边(对于有向图来说是以该顶点为弧尾的弧)。
1.有向网的数据结构
单链表中的每个结点有3个域组成,分别为邻接点域(adjvex)表示与某顶点邻接的点在图中的位置;链域(nextarc)表示下一条边或弧的结点;数据域info存储和边或弧相关的信息,如权值等。
每个链表上附设一个表头结点。在表头结点中,除了设有链域(firstarc)指向链表中的第一个结点之外,还设有存储顶点的名或其他相关信息的数据域data.
2.附上代码:
3.测试
4.测试结果如下:
自行输入的运行结果如下:
1.有向网的数据结构
单链表中的每个结点有3个域组成,分别为邻接点域(adjvex)表示与某顶点邻接的点在图中的位置;链域(nextarc)表示下一条边或弧的结点;数据域info存储和边或弧相关的信息,如权值等。
每个链表上附设一个表头结点。在表头结点中,除了设有链域(firstarc)指向链表中的第一个结点之外,还设有存储顶点的名或其他相关信息的数据域data.
// 邻接表中表对应的链表的顶点 private class ENode { int ivex; // 该边所指向的顶点的位置,如果该结点为B,而图的顶点数组中B的索引为1,则此时的ivex值就位1 ENode nextEdge; // 指向下一条弧的指针, int weight; //权值,顶点到该结点的权值,距离 } // 邻接表中表的顶点(头结点) private class VNode { String data; // 顶点信息,名字或者其他,如A,B,C,V0,V1等 ENode firstEdge; // 指向第一条依附该顶点的弧,如果该顶点下没有链表,则为null } private VNode[] mVexs; // 顶点数组,存取图的各个顶点
2.附上代码:
package com.test.frame.fighting.graph; import java.io.IOException; import java.util.ArrayList; import java.util.Scanner; /** * ListDG class * * @author guanhuifang * @date 2018/1/19 下午8:20 **/ public class ListDG { // 邻接表中表对应的链表的顶点 private class ENode { int ivex; // 该边所指向的顶点的位置 ENode nextEdge; // 指向下一条弧的指针 int weight; //权值,顶点到该节点的权值,距离 } // 邻接表中表的顶点(头结点) private class VNode { String data; // 顶点信息 ENode firstEdge; // 指向第一条依附该顶点的弧 } private VNode[] mVexs; // 顶点数组 /** * 创建图,输入数据 */ public ListDN() { // 输入"顶点数"和"边数" System.out.printf("input vertex number: "); int vlen = readInt(); System.out.printf("input edge number: "); int elen = readInt(); if (vlen < 1 || elen < 1 || (elen > (vlen * (vlen - 1)))) { System.out.printf("input error: invalid parameters!\n"); return; } // 初始化"顶点" mVexs = new VNode[vlen]; for (int i = 0; i < mVexs.length; i++) { System.out.printf("vertex(%d): ", i); mVexs[i] = new VNode(); mVexs[i].data = String.valueOf(readChar()); mVexs[i].firstEdge = null; } // 初始化"边" for (int i = 0; i < elen; i++) { // 读取边的起始顶点和结束顶点 System.out.printf("edge(%d):", i); String c1 = String.valueOf(readChar()); String c2 = String.valueOf(readChar()); int weight = readInt(); System.out.println(c2 + "——>" + c2 + " weight:" + weight); int p1 = getPosition(c1); int p2 = getPosition(c2); // 初始化node1 ENode node1 = new ENode(); node1.ivex = p2; node1.weight = weight; // 将node1链接到"p1所在链表的末尾" if (mVexs[p1].firstEdge == null) { mVexs[p1].firstEdge = node1; } else { linkLast(mVexs[p1].firstEdge, node1); } } } /** * 创建图,已知顶点和弧 * @param vexs 顶点数组 * @param edges 边数组 */ public ListDG(String[] vexs, ArrayList<String> edges) { // 初始化"顶点数"和"边数" int vlen = vexs.length; int elen = edges.size(); // 初始化"顶点" mVexs = new VNode[vlen]; for (int i = 0; i < mVexs.length; i++) { mVexs[i] = new VNode(); mVexs[i].data = vexs[i]; mVexs[i].firstEdge = null; } // 初始化"边" for (int i = 0; i < elen; i++) { // 读取边的起始顶点和结束顶点 String c1 = edges.get(i).substring(0, 1); String c2 = edges.get(i).substring(1, 2); int weight = Integer.parseInt(edges.get(i).substring(2)); System.out.println(c1+c2+weight); // 读取边的起始顶点和结束顶点 int p1 = getPosition(c1); int p2 = getPosition(c2); // 初始化node1 ENode node1 = new ENode(); node1.ivex = p2; //ivex是指该边指向顶点的位置 node1.weight = weight; node1.nextEdge = null; // 将node1链接到"p1所在链表的末尾" if (mVexs[p1].firstEdge == null) { //判断起点是否为顶点,如果是头顶点,则把该顶点直接挂到该头顶点的位置 mVexs[p1].firstEdge = node1; } else { /** * 如果找到顶点向量数组中的顶点不是头结点,即他下面挂有结点,则把他下面 * 挂的第一个顶点,和该顶点 */ linkLast(mVexs[p1].firstEdge, node1); } } } /* * 将node节点链接到list的最后 */ private void linkLast(ENode list, ENode node) { ENode p = list; while (p.nextEdge != null) { p = p.nextEdge; } p.nextEdge = node; } /* * 返回ch位置 */ private int getPosition(String ch) { for (int i = 0; i < mVexs.length; i++) { if (mVexs[i].data.equals(ch)) { return i; } } return -1; } /* * 读取一个输入字符 */ private char readChar() { char ch = '0'; do { try { ch = (char) System.in.read(); } catch (IOException e) { e.printStackTrace(); } } while (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))); return ch; } /* * 读取一个输入字符 */ private int readInt() { Scanner scanner = new Scanner(System.in); return scanner.nextInt(); } /* * 打印矩阵队列图 */ public void print() { System.out.printf("List Graph:\n"); for (int i = 0; i < mVexs.length; i++) { System.out.printf("%d(%s)-> ", i, mVexs[i].data); ENode node = mVexs[i].firstEdge; while (node != null) { System.out.printf("%d(%s)-%d ", node.ivex, mVexs[node.ivex].data,node.weight); node = node.nextEdge; } System.out.printf("\n"); } } }
3.测试
import com.test.frame.fighting.graph.ListDN; import org.junit.Test; import java.util.ArrayList; /** * ListDNTest class * * @author guanhuifang * @date 2018/1/19 下午10:19 **/ public class ListDNTest { @Test public void createListDN(){ String[] vexs = {"A", "B", "C", "D", "E"}; ArrayList<String> edgeList = new ArrayList<>(); edgeList.add("AB5"); edgeList.add("BC4"); edgeList.add("CD8"); edgeList.add("DC8"); edgeList.add("DE6"); edgeList.add("AD5"); edgeList.add("CE2"); edgeList.add("EB3"); edgeList.add("AE7"); // 采用已有的"图" ListDN pN = new ListDN(vexs, edgeList); pN.print(); // 打印图 } }
4.测试结果如下:
List Graph: 0(A)-> 1(B)-5 3(D)-5 4(E)-7 1(B)-> 2(C)-4 2(C)-> 3(D)-8 4(E)-2 3(D)-> 2(C)-8 4(E)-6 4(E)-> 1(B)-3 Process finished with exit code 0
自行输入的运行结果如下:
![](https://static.oschina.net/uploads/space/2018/0119/230933_ld6z_2263272.png)
相关文章推荐
- Windows系统无法安装(分区形式为GPT形式 或者 无法创建新的系统分区,也无法定位系统分区)
- 数组形式实现邻接表
- 用小说的形式讲解Spring(4) —— 使用Spring Boot创建NoXml的Web应用
- Oracle11g中,设置主键为自增1形式-创建Trigger
- Oracle11g中,设置主键为自增1形式-创建Trigger
- xml 形式的参数 删除存储过程的创建
- RxAndroid从零开始学之二(Observable的其它创建与订阅形式)
- 动态创建对话框WND形式
- 创建一个Date.text文件,获取当前的日期,将日期格式为“2013/02/14 05:20:00”的形式。然后一秒钟记录一次,将新的时间存入到文件中。
- Delphi代码创建形式规范
- 图-深度优先广度优先,以及邻接表的创建
- 线程创建的两种形式
- 01.使用eclipse+maven形式创建Jfinal项目(特效版)
- c++实现图的邻接表(带有权值和入度…
- 以上下文(Context)的形式创建一个共享数据的容器
- C++ 无向图 邻接表创建 广度遍历 深度遍历
- idea 创建dubbo服务 jar包形式
- 【数据结构】邻接表创建_CreateALGraph
- VS创建Web项目的两种形式WebSite和WebApplicationd的区别!
- 最大流模板(SAP算法)(邻接表形式)