package com.yc.graph;
/**
*
* @author wb
* {@docRoot}
* 邻接表(Adjacency List)是图的一种链式存储结构。在邻接表中,对图中的每个顶点建立一个单链表,第i个单链表中的节点表示依附于顶点vi
* 的边(对有向图是以顶点vi为尾的弧)。每个节点由3个域组成,其中邻接点域(adjvex)指示与顶点vi邻接的点在图中的位置。链域(nextarc)
* 指示下一条边或弧的节点;数据域(info)存储和边或弧相关的信息,如权值等。每个链表上附设一个表头节点。在表头节点中,除了设有链域(firs
* tarc)指向链表中的第一个节点之外,还设有存储顶点vi的名或其他有关信息的数据域(data)。
* 如下所示:
* 表节点 头节点
*
* │adjvex │ nextarc │ info│ │data │ firstarc│
*
* 这些表头节点(可以链相接)通常以顺序结构的形式存储,以便随机访问任一顶点的链表,如一个图的邻接表存储结构可以是下面的样子:
* //----------图的邻接表存储表示------
* class ArcNode{
* int adjvex; //该弧所指向的顶点的位置
* ArcNode next; //指向下一个弧的指针
* InfoType info;//该弧相关信息的指针
* }
*
* class VNode{
* VertexType data; //顶点信息
* ArcNode firstarc; //指向第一条依附该顶点的弧的指针
* }
*
* class LinkGraph{
* int vexnum,arcnum; //图的当前顶点树和弧树
* int kind; //图的种类标志
* VNode[] vnodes; //图的每条单链表的开始存在vnodes数组里
* }
*
* 若无向图中有n个顶点、e条边,则它的邻接表需要n个头节点和2e个表节点。显然。在边稀疏(e<=n(n-1)/2)的情况下,用邻接表表示
* 图比邻接矩阵节省存储空间,当和边相关的信息较多时更是如此。
* 在无向图的邻接表中,顶点vi的度恰为第i个链表中的节点数;而在有向图中,第i个链表中的节点个数只是顶点vi的出度。在所有链表中其
* 邻接点域的值为i的节点的个数是顶点vi的入度。有时,为了便于确定顶点的入度或以顶点vi为头的弧,可以建立一个有向图的逆邻接表,即对每个顶
* 点vi建立一个邻接以vi为头的弧的表。
* 在建立邻接表或逆邻接表是,若输入的顶点信息即为顶点的编号,则建立邻接表的时间复杂度为O(n+e),否则,需要通过查找才能得到顶点
* 在图中的位置,则时间复杂度为O(n*e)。
* 在邻接表上容易找到任一顶点的第一个邻接点和下一个邻接点,但要判定任意两个顶点(vi和vj)之间是否有边或弧相连,则需要搜索第i个
* 或第j个链表,因此,不及邻接矩阵方便。
*
*
* 这种表示法以表结构来表示图形,他有点类似于相邻矩阵,不过忽略掉矩阵中为0的部分,直接把1的部分放入节点里,如此一来可以有效避免浪费存储空间。
*
* 相关特性如下:
* 1.每一个顶点使用一个表。
* 2.在无向图中,n个顶点e个边共需n个表头节点及2*e个节点;有向图则需n个表头节点及e个节点。在相邻表中,计算所有顶点的度所需的时间
* 复杂度为O(n+e)。
*
* 下面是我随便写的一个,意思是没按上面的方法出牌。
*/
public class LinkGraph {
class Node{
//顶点
int data;
//权值(有必要写?还是不是在顶点Node这里写?)
Object cost;
//下一个顶点
Node next;
public Node(int data, Object cost, Node next){
this.data = data;
this.cost = cost;
this.next = next;
}
public String toString(){
return "[顶点"+data+"]";
}
}
/*//起始顶点 //讲道理这个到现在我都觉得没有必要要
private Node start;*/
//用于存储每个节点链的开头,最后的最后一定会存满所有的顶点
private Node[] heads;
/*public LinkGraph(){
this.start = this.end = null;
}*/
public LinkGraph(int length){
//this.start = null;
this.heads = new Node[length];
}
public LinkGraph(int data, Object obj, int length){
//this.start = new Node(data, obj, null);
this.heads = new Node[length];
this.heads[0] = new Node(data, obj, null);
}
//判断该图是否为空
public boolean isEmpty(int index){
if(heads == null){
return true;
}
if(index > heads.length - 1 || index < 0){
try {
throw new Exception("为空判断异常");
} catch (Exception e) {
e.printStackTrace();
}
}else{
return heads[index] == null;
}
return false;
}
//插入数据1
public void insert(int data_1, int data_2){
Node toNode = new Node(data_2, null, null);
Node fromNode = new Node(data_1, null, toNode);
if(this.isEmpty(data_1 - 1)){
heads[data_1 - 1] = fromNode;
}
else{
int tmp = data_1 > data_2 ? data_1 : data_2;
if(0 < tmp && tmp <= heads.length){ //如果满足条件
Node current = heads[data_1 - 1];
while(current != null && current.next != null){
current = current.next;
}
current.next = toNode;
}
}
}
//插入数据2
public void insert(int data, Object obj){
}
/**
* 将指定数组转换为图
* @param arr:指定数组
*/
public void build(int[][] arr){
//int[][] data_1 = {{1,2},{2,1},{1,5},{5,1},{2,3},{3,2},{2,4},{4,2},{3,4},{4,3},{3,5},{5,3},{4,5},{5,4}};
if(arr != null){
for(int i = 0; i < arr.length; i ++){
int[] tmp = arr[i];
insert(tmp[0], tmp[1]);
}
}
else{
try {
throw new Exception("数组异常");
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void print(){
System.out.println("图形的邻接表表示为:");
if(heads == null){
System.out.println("[]");
}else{
StringBuilder sb = new StringBuilder();
for(int i = 0; i < heads.length; i ++){
sb.append("顶点" + (i + 1) + "==>");
for(Node node = heads[i]; node != null && node.next != null; node = node.next){
sb.append(node.next.toString());
}
sb.append("->NULL\n");
}
System.out.println(sb.toString());
}
}
public static void main(String[] args) {
int[][] data_1 = {{1,2},{2,1},{1,5},{5,1},{2,3},{3,2},{2,4},{4,2},{3,4},{4,3},{3,5},{5,3},{4,5},{5,4}};
LinkGraph graph_1 = new LinkGraph(5);
graph_1.build(data_1);
graph_1.print();
System.out.println();
int[][] data_2 = {{1,2},{2,3},{2,4},{4,3}};
LinkGraph graph_2 = new LinkGraph(4);
graph_2.build(data_2);
graph_2.print();
}
}
结果为:
图形的邻接表表示为:
顶点1==>[顶点2][顶点5]->NULL
顶点2==>[顶点1][顶点3][顶点4]->NULL
顶点3==>[顶点2][顶点4][顶点5]->NULL
顶点4==>[顶点2][顶点3][顶点5]->NULL
顶点5==>[顶点1][顶点3][顶点4]->NULL
图形的邻接表表示为:
顶点1==>[顶点2]->NULL
顶点2==>[顶点3][顶点4]->NULL
顶点3==>->NULL
顶点4==>[顶点3]->NULL