您的位置:首页 > 其它

以邻接表的形式创建带权值的有向图即有向网

2018-01-19 00:00 483 查看
摘要: 邻接表(Adjacency List)是图的一种链式存储结构。在邻接表中,对图中的每个顶点都建立一个单链表,第i个单链表中的结点表示依附于该顶点的边(对于有向图来说是以该顶点为弧尾的弧)。

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

自行输入的运行结果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  有向网 邻接表