一、概述

邻接表处理方法:

  1. 用一位数组存储顶点(为何不用单链表存储?数组可以较容易获得读取顶点信息),此外,每个数据元素还存储指向第一个邻接点的指针;
  2. 每个顶点Vi的所有邻接点构成一个线性表。

java邻接表存图 java实现邻接表_图

  • data:数据域,存储顶点Vi的名或其他信息 firstedge:指针域,指向此顶点的第一个邻接点
    adjvex:邻接点域,指示与Vi连接的节点在图中的位置 info:存储边或弧的相关信息,如权值,边编号等
    next:下一条边或弧的相关信息

二、图的邻接表存储表示

  1. 头节点类
public class VertextNode {

    private String data;//顶点域   
    private EdgeNode firstEdge;
    private int id;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getData() {
        return data;
    }
    public void setData(String data) {
        this.data = data;
    }
    public EdgeNode getFirstEdge() {
        return firstEdge;
    }
    public void setFirstEdge(EdgeNode firstEdge) {
        this.firstEdge = firstEdge;
    }           
}
  1. 边表节点
public class EdgeNode {

    private String Adjvex;//邻接点域,存储该顶点对应下标
    private int weight;//权重
    private EdgeNode next;
    private int edgeInfo;//边值

    public int getEdgeInfo() {
        return edgeInfo;
    }
    public void setEdgeInfo(int edgeInfo) {
        this.edgeInfo = edgeInfo;
    }
    public String getAdjvex() {
        return Adjvex;
    }
    public void setAdjvex(String adjvex) {
        Adjvex = adjvex;
    }
    public int getWeight() {
        return weight;
    }
    public void setWeight(int weight) {
        this.weight = weight;
    }
    public EdgeNode getNext() {
        return next;
    }
    public void setNext(EdgeNode next) {
        this.next = next;
    }       
}
  1. 图的实现
public class GraphLink {
    private int numInputV,numInputE;//输入的总数
    VertextNode vtNode[];   
    Boolean kind =false;//是否为有向图
}
    public GraphLink(int sizeVertexes,Boolean kind){
        if(sizeVertexes>0&&sizeVertexes<65535){
            vtNode = new VertextNode[sizeVertexes];//初始化顶点域     
            numInputV=numInputE=0;          
            for(int i=0;i<sizeVertexes;i++){
                //顶点域置空
                vtNode[i]=null;
            }
        }else{new RuntimeException("创建失败");}
        this.kind=kind;
    }
        //输入头节点
    public void InsertVertextes(String ev){
        VertextNode vt = new VertextNode();
        vt.setData(ev);
        vt.setFirstEdge(null);
        vt.setId(numInputV);

        vtNode[numInputV]=vt;
        numInputV++;
    }
        //建立边表_头插法,把边的next指向顶点的firstedge,顶点的firstedge指向eNode的getNext()
    public void InsertEdges(String start,String end,int weight,int ID){

        int pos = getVertexPos(start);
        if(pos!=-1){
            EdgeNode en = new EdgeNode();
            en.setAdjvex(end);
            en.setEdgeInfo(ID);
            en.setWeight(weight);
            en.setNext(vtNode[pos].getFirstEdge());     
            vtNode[pos].setFirstEdge(en);
            numInputE++;
        }
        if(!kind){//无向图
            int posEnd = getVertexPos(end);
            if(posEnd!=-1){
                EdgeNode enStart = new EdgeNode();
                enStart.setAdjvex(start);
                enStart.setEdgeInfo(ID);
                enStart.setWeight(weight);
                enStart.setNext(vtNode[posEnd].getFirstEdge());
                vtNode[posEnd].setFirstEdge(enStart);
                numInputE++;
            }
        }
    }   
    public int getVertexPos(String vertx) {
        //给出顶点vertex在图中的位置
        for (int i = 0; i < numInputV; i++)
            if (vtNode[i].getData() == vertx)
                return i;
        return -1;
    }

    public String GetFirstNeighbor(String vertx){

        int pos=getVertexPos(vertx);
        if(pos!=-1){
            EdgeNode en = vtNode[pos].getFirstEdge();
            return en.getAdjvex();
        }
        return null;
    }

    //给出顶点v的邻接点w,求下一个邻接点
    public String GetSecNeighbor(String start,String next){

        int pos1=getVertexPos(start);
        int pos2=getVertexPos(next);

        if(pos1!=-1&&pos2!=-1){
            EdgeNode en = vtNode[pos1].getFirstEdge();

            while(en!=null&&en.getAdjvex()!=next){
                en=en.getNext();
            }
            if(en.getNext()!=null){
                return en.getNext().getAdjvex();
            }
        }   
        return null;
    }

    public int getNumInputV() {
        return numInputV;
    }

    public void setNumInputV(int numInputV) {
        this.numInputV = numInputV;
    }

    public int getNumInputE() {
        return numInputE;
    }

    public void setNumInputE(int numInputE) {
        this.numInputE = numInputE;
    }

    public VertextNode[] getVtNode() {
        return vtNode;
    }

    public void setVtNode(VertextNode[] vtNode) {
        this.vtNode = vtNode;
    }

三、测试

public class TestClass {

    public static void main(String[] args){
        TestClass ts = new TestClass();
        ts.initGraph();
    }

    private void initGraph(){

        GraphLink gl = new GraphLink(9,false);

        gl.InsertVertextes("A");
        gl.InsertVertextes("B");
        gl.InsertVertextes("C");
        gl.InsertVertextes("D");
        gl.InsertVertextes("E");
        gl.InsertVertextes("F");
        gl.InsertVertextes("G");
        gl.InsertVertextes("H");
        gl.InsertVertextes("I");

        gl.InsertEdges("A", "B", 0, 1);
        gl.InsertEdges("A", "F", 0, 2);             
        gl.InsertEdges("B", "C", 0, 3);
        gl.InsertEdges("B", "I", 0, 4);     
        gl.InsertEdges("B", "G", 0, 5);
        gl.InsertEdges("C", "I", 1, 6);     
        gl.InsertEdges("C", "D", 1, 7);     
        gl.InsertEdges("D", "G", 1, 8);
        gl.InsertEdges("D", "I", 5, 1);         
        gl.InsertEdges("D", "H", 4, 2);             
        gl.InsertEdges("D", "E", 3, 3);
        gl.InsertEdges("E", "F", 2, 4);     
        gl.InsertEdges("E", "H", 1, 5);
        gl.InsertEdges("G", "F", 1, 6);     
        gl.InsertEdges("G", "H", 1, 7);     

        DFSTraverse(gl);
        System.out.println(gl.GetFirstNeighbor("A"));
        System.out.println(gl.GetSecNeighbor("A", "F"));
    }

    Boolean [] visited;

    private void DFS(GraphLink gl,int i){

        visited[i]=true;        
        System.out.println(gl.vtNode[i].getData());

        EdgeNode en = gl.vtNode[i].getFirstEdge();//获取当前结点的下一个相邻结点
        while(en!=null){

            int pos = gl.getVertexPos(en.getAdjvex());

            if( !visited[pos]){
                DFS(gl,gl.getVertexPos(en.getAdjvex()));                
            }
            en=en.getNext();
        }       
    }

    void DFSTraverse(GraphLink gl){

        visited = new Boolean[gl.getNumInputV()];
        for(int i=0;i<gl.getNumInputV();i++){
            visited[i]=false;
        }
        for(int i=0;i<gl.getNumInputV();i++){
            if(!visited[i]){
                DFS(gl,i);
            }
        }
    }
}

/**
     * 广度优先
     * @param gl
     */
    private void BFSTraverse(GraphLink gl){
        Queue<String> q = new LinkedList<String>();//初始化一个辅助队列

        Boolean [] visitedB = new Boolean [gl.getNumInputV()];
        for(int i=0;i<gl.getNumInputV();i++){
            visitedB[i]=false;
        }

        //访问i元素
        for(int i=0;i<gl.getNumInputV();i++){

            if(!visitedB[i]){
                System.out.println(gl.getVtNode()[i].getData());//getData中为顶点头的内容
                visitedB[i]=true;
                q.add(gl.getVtNode()[i].getData());//把当前顶点添加到队列中

                while(!q.isEmpty()){//队列不为空则一直循环
                    int j =gl.getVertexPos(q.poll());//获取当前出栈元素的位置
                    EdgeNode en = gl.getVtNode()[j].getFirstEdge();//当前出栈元素的连接边
                    while(en!=null){
                        j= gl.getVertexPos(en.getAdjvex());//Agjvex为String,需先获取在图中位置,当前边对应结点在图中的位置(id)
                        if(!visitedB[j] ){
                            visitedB[j]=true;
                            System.out.println(en.getAdjvex());
                            q.add(en.getAdjvex());//将顶点入栈
                        }
                        en = en.getNext();//指向下一个结点
                    }               
                }
            }
        }       
    }

~感觉写的有点麻烦~~图结构建的不是很好,后续在改进咯

邻接表的插入方法选用的为“前插法”,书中教程一般选用尾差法,所以深搜和宽搜结果会不一致,验证了下,结果是正确的~

测试用例中图的结构如下:

java邻接表存图 java实现邻接表_图_02

最后(DFS)输出结果为:

A 
 F 
 G 
 H 
 E 
 D 
 I 
 C 
 BF 
 B