浅谈图的存储结构与遍历

简述图的存储结构

  图的存储结构分为:邻接矩阵与邻接表

  

  邻接矩阵分为顶点、边表(1代表存在边、0代表不存在)。

  邻接链表分为顶点(顶点信息、第一个边结点)、边表(顶点序号、下一个边结点)。

  领结链表数据结构:

public class VertexNode {
    private String vertex;
    private EdgeNode firstEdge;
}
//边表结点
public class EdgeNode {
    private int edge;
    private EdgeNode next;
}

图的遍历原理

  遍历:深度遍历、广度遍历。

  深度遍历类似于树的前序遍历,遇见结点就访问。

  广度遍历类似于树的层序遍历,先把结点入队,当结点出队的时候,访问该节点,把该节点的邻接结点入队。

  以邻接矩阵为例分析:

  深度遍历的访问过程:

  1. 访问V0,判断V0的是否被 访问标记为true,如果为true则不继续访问。如果为false,扫描edge[0][0]—edge[0][n]。
  2. 发现edge[0][3]==1,则访问V1。按照步骤一访问,剩余的都按照这种方式继续访问。
  3. 访问顺序为V0-V1-V2-V3。

  广度遍历的访问过程:

  1. 访问结点V0,V0入队。
  2. 判断队列为空,如果不为空,队头出队即V0出队并且打印结点信息。
  3. 判断V0的边是否被访问过,若没有被访问过则全部入队,即V1、V3入队。
  4. 依次按照循环1-3步骤直到队列为空
  5. 访问顺序:V0-V1-V3-V2

图遍历代码实现

public interface BaseGraph {
    //深度优先遍历-类似于前序遍历
    void DFSTraverse(int v);
    //广度优先遍历-类似于层序遍历
    void BFSTraverse(int v);
}

邻接矩阵代码实现

public class AdjMatrixGraph implements BaseGraph {
    public static final int MAX_SIZE=20;
    //图的顶点数
    private int vertexNum;
    //图的边数
    private int edgeNum;
</span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> edge[][];

</span><span style="color: #0000ff;">private</span><span style="color: #000000;"> String vertex[];

</span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> isDFSVisited[];

</span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> isBFSVisited[];

</span><span style="color: #008000;">/**</span><span style="color: #008000;">
 * </span><span style="color: #808080;">@param</span><span style="color: #008000;"> vertex 图的顶点
 * </span><span style="color: #808080;">@param</span><span style="color: #008000;"> n 图的顶点数
 * </span><span style="color: #808080;">@param</span><span style="color: #008000;"> e    图的边数
 </span><span style="color: #008000;">*/</span>
<span style="color: #0000ff;">public</span> AdjMatrixGraph(String vertex[],<span style="color: #0000ff;">int</span> n,<span style="color: #0000ff;">int</span><span style="color: #000000;"> e) {
    </span><span style="color: #0000ff;">this</span>.vertexNum=<span style="color: #000000;">n;
    </span><span style="color: #0000ff;">this</span>.edgeNum=<span style="color: #000000;">e;
    isDFSVisited</span>=<span style="color: #0000ff;">new</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;">[vertexNum];
    isBFSVisited</span>=<span style="color: #0000ff;">new</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;">[vertexNum];
    </span><span style="color: #0000ff;">this</span>.edge=<span style="color: #0000ff;">new</span> <span style="color: #0000ff;">int</span><span style="color: #000000;">[vertexNum][vertexNum];
    </span><span style="color: #0000ff;">this</span>.vertex=<span style="color: #0000ff;">new</span><span style="color: #000000;"> String[vertexNum];
    </span><span style="color: #008000;">//</span><span style="color: #008000;">初始化顶点</span>
    <span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> i=0;i&lt;vertexNum;i++<span style="color: #000000;">){
        </span><span style="color: #0000ff;">this</span>.vertex[i]=<span style="color: #000000;">vertex[i];
    }
    
    </span><span style="color: #008000;">//</span><span style="color: #008000;">初始化边表</span>
    <span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> row=0;row&lt;vertexNum;row++<span style="color: #000000;">){
        </span><span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> colunmNum=0;colunmNum&lt;vertexNum;colunmNum++<span style="color: #000000;">){
            edge[row][colunmNum]</span>=0<span style="color: #000000;">;
        }
    }
    
    Scanner sc</span>=<span style="color: #0000ff;">new</span><span style="color: #000000;"> Scanner(System.in);
    </span><span style="color: #008000;">//</span><span style="color: #008000;">输入边表信息</span>
    <span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> k=0;k&lt;edgeNum;k++<span style="color: #000000;">){
        </span><span style="color: #008000;">//</span><span style="color: #008000;">领阶矩阵的行号</span>
        <span style="color: #0000ff;">int</span> rowNum=<span style="color: #000000;">sc.nextInt();
        </span><span style="color: #008000;">//</span><span style="color: #008000;">领阶矩阵的列号</span>
        <span style="color: #0000ff;">int</span> colunmNum=<span style="color: #000000;">sc.nextInt();
        edge[rowNum][colunmNum]</span>=1<span style="color: #000000;">;
        edge[colunmNum][rowNum]</span>=1<span style="color: #000000;">;
    }
}

</span><span style="color: #008000;">/**</span><span style="color: #008000;">
 * 深度优先遍历
 </span><span style="color: #008000;">*/</span><span style="color: #000000;">
@Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> DFSTraverse(<span style="color: #0000ff;">int</span><span style="color: #000000;"> v) {
    System.out.print(vertex[v]</span>+"	"<span style="color: #000000;">);
    isDFSVisited[v]</span>=<span style="color: #0000ff;">true</span><span style="color: #000000;">;
    </span><span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> j=0;j&lt;vertexNum;j++<span style="color: #000000;">){
        </span><span style="color: #0000ff;">if</span>(edge[v][j]==1&amp;&amp;isDFSVisited[j]==<span style="color: #0000ff;">false</span><span style="color: #000000;">){
            DFSTraverse(j);
        }
    }
}

</span><span style="color: #008000;">/**</span><span style="color: #008000;">
 * 广(宽)度优先遍历
 </span><span style="color: #008000;">*/</span><span style="color: #000000;">
@Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> BFSTraverse(<span style="color: #0000ff;">int</span><span style="color: #000000;"> v) {
    Queue</span>&lt;Integer&gt; queue=<span style="color: #0000ff;">new</span> LinkedList&lt;Integer&gt;<span style="color: #000000;">();
    System.out.print(vertex[v]</span>+"	"<span style="color: #000000;">);
    isBFSVisited[v]</span>=<span style="color: #0000ff;">true</span><span style="color: #000000;">;
    queue.add(v);
    </span><span style="color: #0000ff;">while</span>(!<span style="color: #000000;">queue.isEmpty()){
        v</span>=<span style="color: #000000;">queue.poll();
        </span><span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> j=0;j&lt;vertexNum;j++<span style="color: #000000;">){
            </span><span style="color: #0000ff;">if</span>(edge[v][j]==1&amp;&amp;isBFSVisited[j]==<span style="color: #0000ff;">false</span><span style="color: #000000;">){
                System.out.print(vertex[j]</span>+"	"<span style="color: #000000;">);
                isBFSVisited[j]</span>=<span style="color: #0000ff;">true</span><span style="color: #000000;">;
                queue.add(j);
            }
        }
    }
}

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) {
    String [] vertex</span>=<span style="color: #0000ff;">new</span> String[]{"vo","v1","v2","v3"<span style="color: #000000;">};
    AdjMatrixGraph graph</span>=<span style="color: #0000ff;">new</span> AdjMatrixGraph(vertex, 4, 4<span style="color: #000000;">);
    </span><span style="color: #008000;">//</span><span style="color: #008000;">图的深度遍历</span>
    System.out.println("图的深度遍历"<span style="color: #000000;">);
    graph.DFSTraverse(</span>0<span style="color: #000000;">);
    </span><span style="color: #008000;">//</span><span style="color: #008000;">图的广度遍历</span>
    System.out.println(""<span style="color: #000000;">);
    System.out.println(</span>"图的广度遍历"<span style="color: #000000;">);
    graph.BFSTraverse(</span>0<span style="color: #000000;">);
}

}

 

邻接表代码实现

public class AdjListGraph implements BaseGraph{
</span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> vertexNum;
</span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> edgeNum;
</span><span style="color: #0000ff;">private</span><span style="color: #000000;"> VertexNode [] adjList;
</span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> isDFSVisited[];
</span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> isBFSVisited[];

</span><span style="color: #0000ff;">public</span> AdjListGraph(String vertexs[],<span style="color: #0000ff;">int</span> vertexNum,<span style="color: #0000ff;">int</span><span style="color: #000000;"> edgeNum) {
    </span><span style="color: #0000ff;">this</span>.vertexNum=<span style="color: #000000;">vertexNum;
    </span><span style="color: #0000ff;">this</span>.edgeNum=<span style="color: #000000;">edgeNum;
    adjList</span>=<span style="color: #0000ff;">new</span><span style="color: #000000;"> VertexNode[vertexNum];
    isDFSVisited</span>=<span style="color: #0000ff;">new</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;">[vertexNum];
    isBFSVisited</span>=<span style="color: #0000ff;">new</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;">[vertexNum];
    </span><span style="color: #008000;">//</span><span style="color: #008000;">初始化</span>
    <span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> i=0;i&lt;vertexNum;i++<span style="color: #000000;">){
        adjList[i]</span>=<span style="color: #0000ff;">new</span><span style="color: #000000;"> VertexNode();
        adjList[i].setVertex(vertexs[i]);
        adjList[i].setFirstEdge(</span><span style="color: #0000ff;">null</span><span style="color: #000000;">);
    }
    
    Scanner sc</span>=<span style="color: #0000ff;">new</span><span style="color: #000000;"> Scanner(System.in);
    </span><span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> k=0;k&lt;edgeNum;k++<span style="color: #000000;">){
        </span><span style="color: #0000ff;">int</span> i=sc.nextInt();<span style="color: #008000;">//</span><span style="color: #008000;">第几号节点</span>
        <span style="color: #0000ff;">int</span> j=sc.nextInt();<span style="color: #008000;">//</span><span style="color: #008000;">链接边节点</span>
        EdgeNode eNode=<span style="color: #0000ff;">new</span><span style="color: #000000;"> EdgeNode(j,adjList[i].getFirstEdge());
        adjList[i].setFirstEdge(eNode);
    }
}

@Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> DFSTraverse(<span style="color: #0000ff;">int</span><span style="color: #000000;"> v) {
    System.out.println(adjList[v].getVertex());
    isDFSVisited[v]</span>=<span style="color: #0000ff;">true</span><span style="color: #000000;">;
    EdgeNode p</span>=<span style="color: #000000;">adjList[v].getFirstEdge();
    </span><span style="color: #0000ff;">while</span>(p!=<span style="color: #0000ff;">null</span><span style="color: #000000;">){
        </span><span style="color: #0000ff;">int</span> j=<span style="color: #000000;">p.getEdge();
        </span><span style="color: #0000ff;">if</span>(isDFSVisited[j]==<span style="color: #0000ff;">false</span><span style="color: #000000;">)
            DFSTraverse(j);
        p</span>=<span style="color: #000000;">p.getNext();
    }
}

@Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> BFSTraverse(<span style="color: #0000ff;">int</span><span style="color: #000000;"> v) {
    Queue</span>&lt;Integer&gt; queue=<span style="color: #0000ff;">new</span> LinkedList&lt;Integer&gt;<span style="color: #000000;">();
    System.out.println(adjList[v].getVertex());
    isBFSVisited[v]</span>=<span style="color: #0000ff;">true</span><span style="color: #000000;">;
    queue.add(v);
    </span><span style="color: #0000ff;">while</span>(!<span style="color: #000000;">queue.isEmpty()){
        v</span>=<span style="color: #000000;">queue.poll();
        EdgeNode p</span>=<span style="color: #000000;">adjList[v].getFirstEdge();
        </span><span style="color: #0000ff;">while</span>(p!=<span style="color: #0000ff;">null</span><span style="color: #000000;">){
            </span><span style="color: #0000ff;">int</span> j=<span style="color: #000000;">p.getEdge();
            </span><span style="color: #0000ff;">if</span>(isBFSVisited[j]==<span style="color: #0000ff;">false</span><span style="color: #000000;">){
                System.out.println(adjList[j].getVertex());
                isBFSVisited[j]</span>=<span style="color: #0000ff;">true</span><span style="color: #000000;">;
                queue.add(j);
            }
            p</span>=<span style="color: #000000;">p.getNext();
        }
    }
}

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) {
    String [] vertexs</span>=<span style="color: #0000ff;">new</span> String[]{"vo","v1","v2","v3"<span style="color: #000000;">};
    AdjListGraph graph</span>=<span style="color: #0000ff;">new</span> AdjListGraph(vertexs, 4,4<span style="color: #000000;">);
    graph.DFSTraverse(</span>0<span style="color: #000000;">);
    graph.BFSTraverse(</span>0<span style="color: #000000;">);
}

}

原文地址:https://www.cnblogs.com/qiuyong/p/6842781.html