浅谈图的存储结构与遍历
简述图的存储结构
图的存储结构分为:邻接矩阵与邻接表
邻接矩阵分为顶点、边表(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;
private int edge[][];
private String vertex[];
private boolean isDFSVisited[];
private boolean isBFSVisited[];
/**
* @param vertex 图的顶点
* @param n 图的顶点数
* @param e 图的边数
*/
public AdjMatrixGraph(String vertex[],int n,int e) {
this.vertexNum=n;
this.edgeNum=e;
isDFSVisited=new boolean[vertexNum];
isBFSVisited=new boolean[vertexNum];
this.edge=new int[vertexNum][vertexNum];
this.vertex=new String[vertexNum];
//初始化顶点
for(int i=0;i<vertexNum;i++){
this.vertex[i]=vertex[i];
}
//初始化边表
for(int row=0;row<vertexNum;row++){
for(int colunmNum=0;colunmNum<vertexNum;colunmNum++){
edge[row][colunmNum]=0;
}
}
Scanner sc=new Scanner(System.in);
//输入边表信息
for(int k=0;k<edgeNum;k++){
//领阶矩阵的行号
int rowNum=sc.nextInt();
//领阶矩阵的列号
int colunmNum=sc.nextInt();
edge[rowNum][colunmNum]=1;
edge[colunmNum][rowNum]=1;
}
}
/**
* 深度优先遍历
*/
@Override
public void DFSTraverse(int v) {
System.out.print(vertex[v]+"\t");
isDFSVisited[v]=true;
for(int j=0;j<vertexNum;j++){
if(edge[v][j]==1&&isDFSVisited[j]==false){
DFSTraverse(j);
}
}
}
/**
* 广(宽)度优先遍历
*/
@Override
public void BFSTraverse(int v) {
Queue<Integer> queue=new LinkedList<Integer>();
System.out.print(vertex[v]+"\t");
isBFSVisited[v]=true;
queue.add(v);
while(!queue.isEmpty()){
v=queue.poll();
for(int j=0;j<vertexNum;j++){
if(edge[v][j]==1&&isBFSVisited[j]==false){
System.out.print(vertex[j]+"\t");
isBFSVisited[j]=true;
queue.add(j);
}
}
}
}
public static void main(String[] args) {
String [] vertex=new String[]{"vo","v1","v2","v3"};
AdjMatrixGraph graph=new AdjMatrixGraph(vertex, 4, 4);
//图的深度遍历
System.out.println("图的深度遍历");
graph.DFSTraverse(0);
//图的广度遍历
System.out.println("");
System.out.println("图的广度遍历");
graph.BFSTraverse(0);
}
}
邻接表代码实现
public class AdjListGraph implements BaseGraph{
private int vertexNum;
private int edgeNum;
private VertexNode [] adjList;
private boolean isDFSVisited[];
private boolean isBFSVisited[];
public AdjListGraph(String vertexs[],int vertexNum,int edgeNum) {
this.vertexNum=vertexNum;
this.edgeNum=edgeNum;
adjList=new VertexNode[vertexNum];
isDFSVisited=new boolean[vertexNum];
isBFSVisited=new boolean[vertexNum];
//初始化
for(int i=0;i<vertexNum;i++){
adjList[i]=new VertexNode();
adjList[i].setVertex(vertexs[i]);
adjList[i].setFirstEdge(null);
}
Scanner sc=new Scanner(System.in);
for(int k=0;k<edgeNum;k++){
int i=sc.nextInt();//第几号节点
int j=sc.nextInt();//链接边节点
EdgeNode eNode=new EdgeNode(j,adjList[i].getFirstEdge());
adjList[i].setFirstEdge(eNode);
}
}
@Override
public void DFSTraverse(int v) {
System.out.println(adjList[v].getVertex());
isDFSVisited[v]=true;
EdgeNode p=adjList[v].getFirstEdge();
while(p!=null){
int j=p.getEdge();
if(isDFSVisited[j]==false)
DFSTraverse(j);
p=p.getNext();
}
}
@Override
public void BFSTraverse(int v) {
Queue<Integer> queue=new LinkedList<Integer>();
System.out.println(adjList[v].getVertex());
isBFSVisited[v]=true;
queue.add(v);
while(!queue.isEmpty()){
v=queue.poll();
EdgeNode p=adjList[v].getFirstEdge();
while(p!=null){
int j=p.getEdge();
if(isBFSVisited[j]==false){
System.out.println(adjList[j].getVertex());
isBFSVisited[j]=true;
queue.add(j);
}
p=p.getNext();
}
}
}
public static void main(String[] args) {
String [] vertexs=new String[]{"vo","v1","v2","v3"};
AdjListGraph graph=new AdjListGraph(vertexs, 4,4);
graph.DFSTraverse(0);
graph.BFSTraverse(0);
}
}