玩轉圖論算法(1)圖的基本表示

 

 

2-1 圖的分類 

圖是一個用線  或  邊連接在一起的頂點的集合,可以說,圖是有限 頂點V 和 邊E 的有序對。頂點(Vertex),邊(Edge)

圖a中的邊沒有方向,稱爲無向圖。圖b中邊存在方向稱爲有向圖

1.1(a)所示的圖可以表示爲 G1(V, E)。其中頂點集合 V(G1) = { 1, 2, 3, 4, 5, 6 },集合
 
中的元素爲頂點(用序號代表,在其他圖中,頂點集合中的元素也可以是其他標識頂點的符號,
 
如字母 ABC 等);
邊的集合爲:E(G1) = { (1, 2), (1, 3), (2, 3), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (4, 5) }
 

1.1(b)所示的圖可以表示爲 G2(V, E),其中頂點集合 V(G2) = { 1, 2, 3, 4, 5, 6, 7 },集合中的元素也爲頂點的序號;
 
邊的集合爲:
 
E(G2) = { <1, 2>, <2, 3>, <2, 5>, <2, 6>, <3, 5>, <4, 3>, <5, 2>, <5, 4>, <6, 7> }
 
在上述邊的集合中,每個元素<u, v>爲一對頂點構成的有序對(用尖括號括起來),
表示從點 u 到頂點 v 有向邊directed Edge
 
權值weight):某些圖的邊具有與它相關的數,稱爲權值。
下列圖示分別表示:無向有權圖,有向有權圖
 

 上圖a中:所示的無向網可表示爲 G1(V, E),其中頂點集合 V(G1) = { 1, 2, 3, 4, 5, 6, 7 }

邊的集合爲:
 
E(G1) = { (1, 2, 28), (1, 6, 10), (2, 3, 16), (2, 7, 14), (3, 4, 12), (4, 5, 22), (4, 7, 18), (5, 6, 25), (5, 7, 24) }。
 
在邊的集合中,每個元素的第 3 個分量表示該邊的權值。
 

所以依據圖的有無方向和權值可以分爲4類:

1.無向無權圖

2.有向無權圖

3.無向有權圖

4.有向有權圖


2-2 圖的基本概念

頂點的度(degree):對於無向圖來說,一個頂點的度就是這個頂點的相鄰的邊的數量。如第一張圖a中點1的度就是 2 。

簡單圖:沒有自環邊,沒有平行邊

子圖:例如,圖 1.8(a)(b)所示的無向圖都是圖 1.1(a)所示的無向圖 G1的子圖

聯通圖和非聯通圖:

在無向圖中,若從頂點 u v 有路徑,則稱頂點 u v連通的connected)。
 
如果無向圖中任意一對頂點都是連通的,則稱此圖是連通圖connected  graph);
 
相反,如果一個無向圖不是連通圖,則稱爲非連通圖disconnected graph)。
 
如果一個無向圖不是連通的,則其極大連通子圖稱爲連通分量connected component
 

樹是一種無環圖,任意結點都可以看做是根節點。聯通的無環圖是樹

生成樹Spanning Tree):一個無向連通圖的生成樹是它的包含所有頂點的極小連通子圖,這裏所謂的極小就是邊的數目極小。
 
如果圖中有 n 個頂點,則生成樹有 n-1 條邊。一個無向連通圖可能有多個生成樹。
 
圖1.1(a) 所示的無向圖 G1的一個生成樹如圖 1.9(a)所示。爲了更形象地表示這個生成樹,
 
在圖 1.9 中,圖(b)把它畫成了以頂點 1 爲根結點的樹,圖(c)把它畫成了以頂點 3 爲根結點的樹。

 


2-3 圖的基本表示:鄰接矩陣

在鄰接矩陣存儲方法中,除了一個記錄各個頂點信息的頂點數組外,還有一個表示各個頂點
 
之間關係的矩陣,稱爲鄰接矩陣adjacency matrix)。兩頂點相鄰則爲1, 不相鄰則爲 0
 

 

其中 V = 7 表示頂點的數量, E = 9 表示邊的數量
 

練習的是簡單圖,不包含自環邊和平行邊

 
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;

//只是處理簡單的圖
public class AdjMatrix {
	
	private int V;  // 圖的頂點的數量
	private int E;  // 圖的邊的數量
	private int[][] adj;  // 鄰接矩陣
	
	public AdjMatrix(String filename) {
		File file = new File(filename);
		
		try {
			// 讀取文件
			Scanner scanner = new Scanner(file);
			V = scanner.nextInt();
			// 判斷頂點數量是否有誤
			if (V < 0) throw new IllegalArgumentException("V 必須是個不爲負數的數值");
			adj = new int[V][V];  // 創建二維矩陣
			
			E = scanner.nextInt();
			if (V < 0) throw new IllegalArgumentException("E 必須是個不爲負數的數值");
			for (int i = 0; i< E; i++) {
				int a = scanner.nextInt();
				validateVertex(a);
				int b = scanner.nextInt();
				validateVertex(b);
				// 判斷是否是自環邊
				if (a == b) throw new IllegalArgumentException("不允許存在自環邊");
				if (adj[a][b] == 1) throw new IllegalArgumentException("不允許存在平行邊");
				adj[a][b] = 1;
				adj[b][a] = 1;
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private void validateVertex(int v) {
		if (v < 0 || v > V) {
			throw new IllegalArgumentException("輸入的數值" + v +"不合法");
		}
	}
	
	// 獲取指定結點相鄰的結點
	public ArrayList<Integer> adj(int v){
		validateVertex(v);
		ArrayList<Integer> res = new ArrayList<>();
		
		for (int i = 0; i < V; i++) {  // 頂點的數量
			if (adj[v][i] == 1) {
				res.add(i);
			}
		}
		return res;
	}
	
	// 獲取指定結點的度,即相鄰的結點的數量
	public int degree(int v) {
		return adj(v).size();
	}
	
	public int V() {
		return V;
	}
	
	public int E() {
		return E;
	}
	
	public boolean hasEdge(int x, int y) {  // 依據兩個頂點判斷邊是否存在
		validateVertex(x);
		validateVertex(y);
		return adj[x][y] == 1;
	}
	
	public String toString() {
		
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.append(String.format("V = %d, E = %d \n", V, E)); 
		// 打印出矩陣
		for (int i =0; i< V; i++) {
			for (int j = 0; j < V; j++) {
				stringBuilder.append(String.format("%d ", adj[i][j]));
			}
			stringBuilder.append("\n");
		}
		
		return stringBuilder.toString();
		
	}

	public static void main(String[] args) {
		AdjMatrix adjMatrix = new AdjMatrix("g.txt");
		System.out.println(adjMatrix);
//		V = 7, E = 9 
//		0 1 0 1 0 0 0 
//		1 0 1 0 0 0 1 
//		0 1 0 1 0 1 0 
//		1 0 1 0 1 0 0 
//		0 0 0 1 0 1 0 
//		0 0 1 0 1 0 1 
//		0 1 0 0 0 1 0 
		System.out.println(adjMatrix.adj(2).toString());
		System.out.println(adjMatrix.degree(2));

	}

}

 


2-4 圖的基本表示:鄰接表

 

 


2-6 鄰接表的實現


2-7 鄰接表的問題和改進


2-8 實現鄰接表的改進


2-9 圖的基本表示的比較

 

 

 

 

 

待更新。。。。。。。。。。。。。


 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章