数据结构系列是我学习做的笔记,会持续更新,源码分享在github:数据结构,当然你也可以从下面的代码片中获取
注:github代码更新会有延迟,关注不迷路😄
本篇博文简单介绍邻接表与其存储图的特点,并用java实现
1. 邻接表
邻接表(Adjacency list)是图的一种链式存储方法,其是由一个顺序存储的顶点表和n个链式存储的边表组成。其中,顶点表由定点节点组成,边表是由边(弧)节点组成的一个单链表,表示所有依附于顶点v_i的边。
2. 具体实现代码
2.1 图的类型枚举:GraphKind.java
package code.Graph;
/*
* 罗列图的四种类型
* */
public enum GraphKind {
UDG, //无向图----(UnDirected Graph)
DG, //有向图----(Directed Graph)
UDN, //无向网----(UnDirected Network)
DN; //有向网----(Directed Network)
}
2.2 图的接口:IGraph .java
package code.Graph;
/*
* 图的存储结构除了存储图中各个顶点的信息外,还要存储与顶点相关联的边的信息,
* 图的常见存储结构有邻接矩阵,邻接表,邻接多重表,十字链表
*
* 图的接口
*
* */
public interface IGraph {
/**创建一个图*/
public void createGraph();
/**返回图中的顶点数*/
public int getVexNum();
/**返回图中的边数*/
public int getArcNum();
/**
* 给定点的位置v,返回其对应的顶点值,其中, 0 <= v < vexNum
* @param v
* */
public Object getVex(int v) throws Exception;
/**
* 给定顶点的值vex,返回其在图中的位置,如果图中不包含此定点,返回-1
* @param vex
*/
public int locateVex(Object vex);
/**
* 返回v的第一个邻接点,若V没有邻接点,则返回-1,其中, 0 <= v < vexNum
* @param v
*/
public int firstAdjVex(int v) throws Exception;
/**
* 返回v相对于w的下一个邻接点,若w是v的最后一个邻接点,则返回-1,其中, 0 <= v, w < vexNum
* @param v
* @param w
*/
public int nextAdjVex(int v,int w) throws Exception;
}
2.3 顶点节点类:VNode.java
package code.Graph;
/**
* 图的邻接表存储表示中的顶点节点类
* */
public class VNode {
public Object data;//顶点信息
public ArcNode firstArc;//指向第一条依附于该顶点的弧
public VNode(Object data) {
this(data,null);
}
public VNode(Object data, ArcNode firstArc) {
this.data = data;
this.firstArc = firstArc;
}
public VNode() {
this(null,null);
}
public Object getData() {
return data;
}
public ArcNode getFirstArc() {
return firstArc;
}
}
2.4 边(或弧)节点类:ArcNode.java
package code.Graph;
/**
* 图的邻接表存储表示中的边(或弧)节点类
*
* */
public class ArcNode {
public int adjVex;//该弧所指向的顶点位置
public int value;//边或弧的权值
private ArcNode nextArc;//指向下一条弧
public ArcNode(int adjVex, int value, ArcNode nextArc) {
this.adjVex = adjVex;
this.value = value;
this.nextArc = nextArc;
}
public ArcNode(int adjVex, int value) {
this(adjVex,value,null);
}
public ArcNode(int adjVex) {
this(adjVex,0,null);
}
public ArcNode() {
this(-1,0,null);
}
public int getAdjVex() {
return adjVex;
}
public int getValue() {
return value;
}
public ArcNode getNextArc() {
return nextArc;
}
public void setAdjVex(int adjVex) {
this.adjVex = adjVex;
}
public void setValue(int value) {
this.value = value;
}
public void setNextArc(ArcNode nextArc) {
this.nextArc = nextArc;
}
}
2.5 图的邻接表类:ALGraph.java
package code.Graph;
import java.util.Scanner;
public class ALGraph implements IGraph{
private GraphKind kind;//图的种类标志
private int vexNum,arcNum;//图的当前顶点数和边数
private VNode[] vexs;//顶点
public ALGraph() {
this(null,0,0,null);
}
public ALGraph(GraphKind kind, int vexNum, int arcNum, VNode[] vexs) {
this.kind = kind;
this.vexNum = vexNum;
this.arcNum = arcNum;
this.vexs = vexs;
}
/**
* 创建一个图
*/
@Override
public void createGraph() {
Scanner sc = new Scanner(System.in);
System.out.println("请输入图的类型:");
GraphKind kind = GraphKind.valueOf(sc.next());
switch (kind){
case UDG:
createUDG();
return;
case DG:
createDG();
return;
case UDN:
createUDN();
return;
case DN:
createDN();
return;
}
}
//创建 图,网 的工具方法
private void createNetworkOrGraphUnit(){
Scanner sc = new Scanner(System.in);
System.out.println("请分别输入图的顶点数,图的边数");
vexNum = sc.nextInt();//图的顶点数
arcNum = sc.nextInt();//图的边数
vexs = new VNode[vexNum];//存储顶点的数组
System.out.println("请分别输入图的各个顶点:");
for (int v = 0;v < vexNum;v++){//构造顶点向量
vexs[v] = new VNode(sc.next());
}
}
//有向图
private void createDG() {
Scanner sc = new Scanner(System.in);
createNetworkOrGraphUnit();
System.out.println("请输入各边的顶点及其权值:");
for (int k = 0;k < arcNum;k++){
int v = locateVex(sc.next());//弧头
int u = locateVex(sc.next());//弧尾
addArc(v,u,1);
}
}
//无向图
private void createUDG() {
Scanner sc = new Scanner(System.in);
createNetworkOrGraphUnit();
System.out.println("请输入各边的顶点:");
for (int k = 0;k < arcNum;k++){
int v = locateVex(sc.next());//弧头
int u = locateVex(sc.next());//弧尾
int value = 1;
addArc(v,u,value);
addArc(u,v,value);
}
}
//无向网
private void createUDN(){
Scanner sc = new Scanner(System.in);
createNetworkOrGraphUnit();
System.out.println("请输入各边的顶点及其权值:");
for (int k = 0;k < arcNum;k++){
int v = locateVex(sc.next());//弧头
int u = locateVex(sc.next());//弧尾
int value = sc.nextInt();
addArc(v,u,value);
addArc(u,v,value);
}
}
//有向网
private void createDN(){
Scanner sc = new Scanner(System.in);
createNetworkOrGraphUnit();
System.out.println("请输入各边的顶点及其权值:");
for (int k = 0;k < arcNum;k++){
int v = locateVex(sc.next());//弧头
int u = locateVex(sc.next());//弧尾
int value = sc.nextInt();
addArc(v,u,value);
}
}
/**
* 在位置为v,u的顶点之间添加一条弧,其权值为value
* */
public void addArc(int v,int u,int value){
ArcNode arc = new ArcNode(u,value);
arc.setNextArc(vexs[v].firstArc);
vexs[v].firstArc = arc;
}
/**
* 返回图中的顶点数
*/
@Override
public int getVexNum() {
return vexNum;
}
/**
* 返回图中的边数
*/
@Override
public int getArcNum() {
return arcNum;
}
/**
* 给定点的位置v,返回其对应的顶点值,其中, 0 <= v < vexNum
*
* @param v
*/
@Override
public Object getVex(int v) throws Exception {
if (v < 0 && v >= vexNum){
throw new Exception("第" + v + "个顶点不存在!");
}
return vexs[v].getData();
}
/**
* 给定顶点的值vex,返回其在图中的位置,如果图中不包含此定点,返回-1
*
* @param vex
*/
@Override
public int locateVex(Object vex) {
for (int v = 0;v<vexNum;v++){
if (vexs[v].data.equals(vex)){
return v;
}
}
return -1;
}
/**
* 返回v的第一个邻接点,若V没有邻接点,则返回-1,其中, 0 <= v < vexNum
*
* @param v
*/
@Override
public int firstAdjVex(int v) throws Exception {
if (v < 0 && v >= vexNum){
throw new Exception("第" + v + "个顶点不存在!");
}
VNode vex = vexs[v];
if (vex.firstArc != null){
return vex.firstArc.adjVex;
}else {
return -1;
}
}
/**
* 返回v相对于w的下一个邻接点,若w是v的最后一个邻接点,则返回-1,其中, 0 <= v, w < vexNum
*
* @param v
* @param w
*/
@Override
public int nextAdjVex(int v, int w) throws Exception {
if (v < 0 && v >= vexNum){
throw new Exception("第" + v + "个顶点不存在!");
}
VNode vex = vexs[v];
ArcNode arcvw = null;
for (ArcNode arc = vex.firstArc;arc != null;arc = arc.getNextArc()){
if (arc.adjVex == w){
arcvw = arc;
break;
}
}
if (arcvw != null && arcvw.getNextArc() != null){
return arcvw.getNextArc().adjVex;
}else {
return -1;
}
}
public GraphKind getKind() {
return kind;
}
public VNode[] getVexs() {
return vexs;
}
}
有关图的邻接矩阵实现见此链接