图的邻接表实现(Java)
当图的结点多边少(又称为稀疏图)的时候,相比使用邻接矩阵存储,使用邻接表存储图的空间效率更高。
使用邻接表存储图的时候,图的每个结点对应一个边链表,也就是说,每个结点所包含的边构成一个链表。例如结点A和B相连,A也和C相连,若边e1表示A和B之间的边,e2表示A和C之间的边,那么结点A包含的边链表就是e1->e2,其中e1保存着A的临接点B,e2保存着A的临接点C。
Graph.java
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
//实现图的邻接表结构
class Edge {//边:作为邻接表中每个结点的边链表的元素,例如结点A和B构成边e1,那么A拥有e1,在A的边链表中,e1的verAdj = B
int verAdj;
int weight;
Edge nextEdge;//如果结点A拥有多条边,边构成链表,例如e1->e2->...->en
}
class Vertex{
int verName;
Edge edgeHead;//边链表的头指针
}
public class Graph {
private Vertex[] vertexs;
private boolean isDirected;//若为有向图,则isDirected为true
Graph(int[] vexs,int[][] edges,boolean isDirected){//图的初始化
//vexs包含各顶点的编号,若有n个顶点,顶点的编号范围是0~n-1
//edges是一个n×3的数组,,边的权值等于edges[i][2],若为有向图,那么edges[i][0]指向edges[i][1]
vertexs = new Vertex[vexs.length];
this.isDirected = isDirected;
if(isDirected == false){//无向图的初始化
for (int j = 0; j < vexs.length; j++) {
vertexs[j] = new Vertex();
vertexs[j].verName = vexs[j];
Edge cur = null;
for (int i = 0; i < edges.length; i++) {
if(edges[i][0] == vexs[j]){
if(vertexs[j].edgeHead == null){
vertexs[j].edgeHead = new Edge();
vertexs[j].edgeHead.verAdj = edges[i][1];
vertexs[j].edgeHead.weight = edges[i][2];
cur = vertexs[j].edgeHead;
}else{
while(cur.nextEdge != null) cur = cur.nextEdge;
cur.nextEdge = new Edge();
cur = cur.nextEdge;
cur.verAdj = edges[i][1];
cur.weight = edges[i][2];
}
}else if(edges[i][1] == vexs[j]){
if(vertexs[j].edgeHead == null){
vertexs[j].edgeHead = new Edge();
vertexs[j].edgeHead.verAdj = edges[i][0];
vertexs[j].edgeHead.weight = edges[i][2];
cur = vertexs[j].edgeHead;
}else{
while(cur.nextEdge != null) cur = cur.nextEdge;
cur.nextEdge = new Edge();
cur = cur.nextEdge;
cur.verAdj = edges[i][0];
cur.weight = edges[i][2];
}
}
}
}
}else{//有向图的初始化
for (int j = 0; j < vexs.length; j++) {
vertexs[j] = new Vertex();
vertexs[j].verName = vexs[j];
Edge cur = null;
for (int i = 0; i < edges.length; i++) {
if(edges[i][0] == vexs[j]){
if(vertexs[j].edgeHead == null){
vertexs[j].edgeHead = new Edge();
vertexs[j].edgeHead.verAdj = edges[i][1];
vertexs[j].edgeHead.weight = edges[i][2];
cur = vertexs[j].edgeHead;
}else{
while(cur.nextEdge != null) cur = cur.nextEdge;
cur.nextEdge = new Edge();
cur = cur.nextEdge;
cur.verAdj = edges[i][1];
cur.weight = edges[i][2];
}
}
}
}
}
}
void bfs(){//广度优先遍历
if(vertexs == null || vertexs.length == 0) return;
Queue<Vertex> queue = new LinkedList<Vertex>();
boolean[] visited = new boolean[vertexs.length];
for (int i = 0; i < visited.length; i++) {
visited[i] = false;
}
queue.offer(vertexs[0]);
visited[0] = true;
System.out.print(vertexs[0].verName);
while(!queue.isEmpty()){
Vertex v = queue.remove();
Edge e = v.edgeHead;
while(e != null && visited[e.verAdj] == false){
queue.offer(vertexs[e.verAdj]);
visited[e.verAdj] = true;
System.out.print(e.verAdj + " ");
e = e.nextEdge;
}
}
}
void dfsNonRec(){//邻接表非递归深度优先遍历
if(vertexs == null || vertexs.length == 0) return;
boolean[] visited = new boolean[vertexs.length];
for (int i = 0; i < visited.length; i++) {
visited[i] = false;
}
Stack<Vertex> stack = new Stack<Vertex>();
stack.push(vertexs[0]);
visited[0] = true;
while(!stack.isEmpty()){
Vertex v = stack.pop();
visited[v.verName] = true;
System.out.print(v.verName + " ");
Edge e = v.edgeHead;
while(e != null && visited[e.verAdj] != true){
stack.push(vertexs[e.verAdj]);
e = e.nextEdge;
}
}
}
void dfs(){//dfs和dfsRec共同实现邻接表存储的图的递归深度优先遍历
if(vertexs == null || vertexs.length == 0) return;
boolean[] visited = new boolean[vertexs.length];
dfsRec(visited, vertexs[0]);
}
void dfsRec(boolean[] visited,Vertex vertex){
if(vertex == null) return;
visited[vertex.verName] = true;
System.out.print(vertex.verName + " ");
Edge e = vertex.edgeHead;
while(e != null){
if(visited[e.verAdj] != true){
dfsRec(visited, vertexs[e.verAdj]);
}
e = e.nextEdge;
}
}
void printGraph(){
if(isDirected == false){
for (Vertex vertex : vertexs) {
Edge e = vertex.edgeHead;
while(e != null){
System.out.println(vertex.verName + "--" + e.verAdj + " weight = " + e.weight);
e = e.nextEdge;
}
}
}else{
for (Vertex vertex : vertexs) {
Edge e = vertex.edgeHead;
while(e != null){
System.out.println(vertex.verName + "->" + e.verAdj + " weight = " + e.weight);
e = e.nextEdge;
}
}
}
}
}
Main.java
public class Main{
public static void main(String[] args){
int[] vexs = {0,1,2,3,4,5};
int[][] edges = {{0,1,100},{0,2,100},{0,3,100},{1,4,100},{2,5,100},{4,5,100},{5,3,100}};
Graph g = new Graph(vexs, edges,true);
g.bfs();
//g.dfs();
//g.dfsNonRec();
}
}