简述图的存储结构
图的存储结构分为:邻接矩阵与邻接表
邻接矩阵分为顶点、边表(1代表存在边、0代表不存在)。
邻接链表分为顶点(顶点信息、第一个边结点)、边表(顶点序号、下一个边结点)。
领结链表数据结构:
public class VertexNode {
private String vertex;
private EdgeNode firstEdge;
}
//边表结点
public class EdgeNode {
private int edge;
private EdgeNode next;
}
图的遍历原理
遍历:深度遍历、广度遍历。
深度遍历类似于树的前序遍历,遇见结点就访问。
广度遍历类似于树的层序遍历,先把结点入队,当结点出队的时候,访问该节点,把该节点的邻接结点入队。
以邻接矩阵为例分析:
深度遍历的访问过程:
- 访问V0,判断V0的是否被 访问标记为true,如果为true则不继续访问。如果为false,扫描edge[0][0]—edge[0][n]。
- 发现edge[0][3]==1,则访问V1。按照步骤一访问,剩余的都按照这种方式继续访问。
- 访问顺序为V0-V1-V2-V3。
广度遍历的访问过程:
- 访问结点V0,V0入队。
- 判断队列为空,如果不为空,队头出队即V0出队并且打印结点信息。
- 判断V0的边是否被访问过,若没有被访问过则全部入队,即V1、V3入队。
- 依次按照循环1-3步骤直到队列为空
- 访问顺序: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<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<vertexNum;row++<span style="color: #000000;">){
</span><span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> colunmNum=0;colunmNum<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<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<vertexNum;j++<span style="color: #000000;">){
</span><span style="color: #0000ff;">if</span>(edge[v][j]==1&&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><Integer> queue=<span style="color: #0000ff;">new</span> LinkedList<Integer><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<vertexNum;j++<span style="color: #000000;">){
</span><span style="color: #0000ff;">if</span>(edge[v][j]==1&&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<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<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><Integer> queue=<span style="color: #0000ff;">new</span> LinkedList<Integer><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;">);
}
}