圖的存儲(chǔ)結(jié)構(gòu)(鄰接矩陣方式)
此圖為帶權(quán)無(wú)向圖
public class MyGraph {
private ArrayList<Object> vertexList; //存放頂點(diǎn)的數(shù)組
private int[][] edges; //鄰接矩陣,存放邊集
private int numofEdges; //邊數(shù)
private static final int INF = 65535; //權(quán)值為65535時(shí)表示不可達(dá)
private boolean[] visited; //用于深度、廣度遍歷時(shí)頂點(diǎn)是否已被訪問(wèn)的標(biāo)志
public MyGraph(int n) {
vertexList = new ArrayList<>(n); //根據(jù)傳入的頂點(diǎn)數(shù)構(gòu)造頂點(diǎn)數(shù)組
edges = new int[n][n]; //構(gòu)造對(duì)應(yīng)的鄰接矩陣
numofEdges = 0;
visited = new boolean[n];
//初始化鄰接矩陣
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
if (i == j) {
edges[i][j] = 0;
}else {
edges[i][j] = INF;
}
}
}
}
//獲取頂點(diǎn)個(gè)數(shù)
public int getNumOfVertex() {
return vertexList.size();
}
//獲取邊數(shù)
public int getNumofEdges() {
return numofEdges;
}
//打印鄰接矩陣
public void printEdges() {
for(int i = 0; i < vertexList.size(); i++) {
for(int j =0; j < vertexList.size(); j++) {
if (j == vertexList.size() - 1) {
System.out.println(edges[i][j]);
}else {
System.out.print(edges[i][j]+" ");
}
}
}
}
//獲取頂點(diǎn)n的值
public Object getValueByIndex(int n) {
return vertexList.get(n);
}
//獲取邊n1-n2的權(quán)值
public int getWeight(int n1, int n2) {
return edges[n1][n2];
}
//插入結(jié)點(diǎn)
public void insertVertex(Object vertex) {
vertexList.add(vertexList.size(),vertex);
}
//插入頂點(diǎn)以及設(shè)置權(quán)值
public void insertEdge(int n1, int n2, int weight) {
edges[n1][n2] = weight;
//該圖為無(wú)向圖,所以矩陣關(guān)于對(duì)角線對(duì)稱
edges[n2][n1] = weight;
numofEdges++;
}
//刪除邊
public void deleteEdge(int n1, int n2) {
edges[n1][n2] = INF;
//無(wú)向圖刪除邊時(shí)矩陣依舊對(duì)稱
edges[n2][n1] = INF;
numofEdges--;
}
}
測(cè)試類
測(cè)試圖如圖所示:
圖片.png
測(cè)試程序如下:
//頂點(diǎn)數(shù)為4
int n = 4;
String[] vertex = {"A","B","C","D"};
MyGraph graph = new MyGraph(n);
for (String string : vertex) {
graph.insertVertex(string);
}
graph.insertEdge(0, 1, 3);
graph.insertEdge(0, 2, 8);
graph.insertEdge(0, 3,10);
graph.insertEdge(1, 2, 6);
System.out.println("結(jié)點(diǎn)數(shù):"+graph.getNumOfVertex());
System.out.println("邊數(shù):"+graph.getNumofEdges());
System.out.println("刪除前的鄰接矩陣:");
graph.printEdges();
graph.deleteEdge(1, 2);
System.out.println("刪除邊<B,C>后:");
System.out.println("結(jié)點(diǎn)個(gè)數(shù)為:"+graph.getNumOfVertex());
System.out.println("邊數(shù)為:"+graph.getNumofEdges());
System.out.println("刪除后的鄰接矩陣:");
graph.printEdges();
測(cè)試結(jié)果:
圖片.png
遍歷算法
測(cè)試圖(由于權(quán)值不影響遍歷結(jié)果,所以不標(biāo)注):
圖片.png
深度優(yōu)先
//鄰接矩陣的深度遍歷操作
public void DFSTraverse(MyGraph graph) {
for (int i = 0; i < graph.getNumOfVertex(); i++) {
visited[i] = false;
}
for( int i = 0; i < graph.getNumOfVertex(); i++) {
//對(duì)未訪問(wèn)過(guò)的結(jié)點(diǎn)調(diào)用DFS,若是連通圖,只會(huì)執(zhí)行一次,非連通圖的話有多少個(gè)子圖則會(huì)調(diào)用多少次
if (!visited[i]) {
DFS(graph, i);
}
}
}
//鄰接矩陣的深度優(yōu)先遞歸算法
public void DFS(MyGraph graph, int i) {
//設(shè)置訪問(wèn)標(biāo)志位為true
visited[i] = true;
System.out.print(getValueByIndex(i)+" ");
for(int j = 0; j < graph.getNumOfVertex(); j++) {
if (edges[i][j] != 0 && edges[i][j] != INF && !visited[j] ) {
//對(duì)未訪問(wèn)的鄰接結(jié)點(diǎn)遞歸調(diào)用
DFS(graph, j);
}
}
}
廣度優(yōu)先
//鄰接矩陣的廣度遍歷算法
public void BFSTraverse(MyGraph graph) {
int i,j;
//初始化訪問(wèn)標(biāo)志矩陣
for(i = 0; i < graph.getNumOfVertex(); i++) {
visited[i] = false;
}
//使用linkedList模擬隊(duì)列的功能
LinkedList<Integer> queue = new LinkedList<>();
for(i = 0; i < graph.getNumOfVertex(); i++) {
//該圖為非連通圖時(shí),第一次廣度遍歷完后還有結(jié)點(diǎn)未被訪問(wèn)時(shí)會(huì)再次進(jìn)入這個(gè)分支
//該圖為連通圖時(shí),該分支只會(huì)執(zhí)行一次,因?yàn)閳?zhí)行一次后所有的結(jié)點(diǎn)都被訪問(wèn)到了
if (!visited[i]) {
visited[i] = true;
System.out.print(getValueByIndex(i)+" ");
//將結(jié)點(diǎn)添加到隊(duì)尾
queue.addLast(i);
while(!queue.isEmpty()) {
//移除隊(duì)頭元素并將其賦值給i
i = ((Integer)queue.removeFirst()).intValue();
for(j = 0; j < graph.getNumOfVertex(); j++) {
if (edges[i][j] != 0 && edges[i][j] != INF && !visited[j] ) {
visited[j] = true;
System.out.print(getValueByIndex(j)+" ");
queue.addLast(j);
}
}
}
}
}
}
廣度優(yōu)先各結(jié)點(diǎn)在隊(duì)列中的情況如下
圖片.png
測(cè)試程序:
public class GraphTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
//頂點(diǎn)數(shù)為4
int n = 9;
String[] vertex = {"A","B","C","D","E","F","G","H","I"};
MyGraph graph = new MyGraph(n);
for (String string : vertex) {
graph.insertVertex(string);
}
graph.insertEdge(0, 1, 3);
graph.insertEdge(0, 2, 8);
graph.insertEdge(1, 3,10);
graph.insertEdge(1, 4, 3);
graph.insertEdge(2, 5, 3);
graph.insertEdge(2, 6, 3);
graph.insertEdge(3, 7, 3);
graph.insertEdge(7, 8, 3);
System.out.println("深度優(yōu)先遍歷結(jié)果:");
graph.DFSTraverse(graph);
System.out.println("\n廣度優(yōu)先遍歷:");
graph.BFSTraverse(graph);
}
}
測(cè)試結(jié)果:
圖片.png