圖形共有兩種:一種是無向圖形,一是有向圖形。五香圖形以(V1, V2)表示邊線,有線圖形以<V1,V2>表示邊線
圖形由頂點和邊所組成,以G=(V, E)來表示:其中V為所有頂點的集合,E為所有邊的集合
他們的數據結構可以表示為:
G1=(V1,E1), 其中 V1={a,b,c,d},E1={(a,b),(a,c),(a,d),(b,d),(c,d)},
G2=(V2,E2),其中 V2={1,2,3}, E2={<1,2>,<1,3>,<2,3>,<3,1>}
完全圖:在無向圖形中,N個定點正好有N(N-1)/2條邊,則稱為完全圖。但是在有向圖形中,若要成為完全圖,則必須有N(N-1)條邊
-
路徑:兩個不同頂點間所經過的邊稱為路徑
-
回路:起始頂點及終止頂點為同一個點的簡單路徑稱為回路
-
相連:在無向圖形中,若頂點Vi到頂點Vj間存在路徑,則Vi和Vj是相連的
-
相連圖形:如果圖形G中,任兩個頂點均相連,則次圖形稱為相連圖形,否則稱為非相連圖形
-
路徑長度:路徑上所包含邊的總數為路徑長度
-
相連單元:圖形中相連在一起的最大子圖總數
-
強相連:在有向圖形中,若兩頂點間有兩條方向相反的邊稱為強相連
-
度:在無向圖形中,一個頂點所擁有邊的總數為度
-
入/出度: 在有向圖形中,以頂點V為箭頭終點的邊之個數為入度,反之則由V出發的箭頭總數為出度
圖形表示法
相鄰矩陣法
相關特性:
-
對無向圖形而言,相鄰矩陣一定是對稱的,而且對角線一定為0,有向圖形則不一定如此
-
在無向圖形中,任一節點i的度為第i行所有元素的和。在有向圖中,節點i的出度為第i行所有元素的和,而入度為j列所有元素的和
-
用相鄰矩陣法表示圖形共需要n**2空間,由於無向圖形的相鄰矩陣一定具有堆成關系,所以出去對角線全部為零外,僅需要存儲上三角形或下三角形的數據即可,因此僅需n(n-1)/2空間
相鄰表法
相關特性:
-
每一個頂點使用一個表
-
在無向圖中,n個頂點e個邊工序n個表頭節點及2*e個節點:有向圖則需n個表頭節點及e個節點。在相鄰表中,計算所有頂點的度所需的時間復雜度為O(n+e)
相鄰多元列表法
結構:M----V1----V2----LINK1----LINK2
-
M:記錄改邊是否被找過的一個字段
-
V1及V2:所記錄的邊的起點與終點
-
LINK1:在尚有其他頂點與V1相連的情況下,此字段會指向下一個與V1相連的邊節點,如果已經沒有任何頂點與V1相連時,則指向null
-
LINK2:在尚有其他頂點與V2相連的情況下,此字段會指向下一個與V2相連的邊節點,如果已經沒有任何頂點與V2相連時,則指向null
圖形的遍歷
一個圖形G=(V,E),存在某一頂點v∈V,我們希望從v開始,通過此節點相鄰的節點而去訪問G中其他節點,這成為圖形的遍歷
先深后廣法
先深后廣遍歷的方式有點類似於前序遍歷。從圖形的某一頂點開始遍歷,被訪問過的頂點就做上訪問的記號,接着遍歷此頂點的所有相鄰且未訪問過的頂點中的任意一個頂點,並做上已訪問的記號。在以改點為新的起點繼續進行先深后廣的搜索。由於此方法會造成無限循環,所以必須加入一個變量,判斷改點是否已經遍歷完畢
Node類
package DFS算法;
/**
* @author YanAemons
* @date 2021/10/16 16:11
*/
public class Node {
int x;
Node next;
public Node(int x)
{
this.x = x;
this.next = null;
}
}
GrapLink類
package DFS算法;
/**
* @author YanAemons
* @date 2021/10/16 16:11
*/
public class GraphLink {
public Node first;
public Node last;
public boolean isEmpty()
{
return first == null;
}
public void print()
{
Node current = first;
while (current != null)
{
System.out.print("["+ current.x+"]");
current = current.next;
}
System.out.println();
}
public void insert(int x)
{
Node newNode = new Node(x);
if (this.isEmpty())
{
first = newNode;
last = newNode;
}
else
{
last.next = newNode;
last = newNode;
}
}
}
Main類
package DFS算法;
/**
* @author YanAemons
* @date 2021/10/16 16:15
*/
public class Main {
public static int run[] = new int[9];
public static GraphLink Head[] = new GraphLink[9];
public static void dfs(int current)
{
run[current] = 1;
System.out.print("["+current+"]");
while (Head[current].first != null)
{
if (run[Head[current].first.x] == 0)
dfs(Head[current].first.x);
Head[current].first = Head[current].first.next;
}
}
public static void main(String[] args) {
int[][] Data = {{1,2},{2,1},{1,3},{3,1},{2,4},{4,2},{2,5},{5,2},{3,6},{6,3},{3,7},{7,3},{4,5},{5,4},{6,7},{7,6},{5,8},{8,5},{6,8},{8,6}};
int DataNum;
int i, j;
System.out.println("圖形的鄰接表內容");
for (i = 1; i < 9; i++)
{
run[i] = 0;
Head[i] = new GraphLink();
System.out.print("頂點"+i+"=>");
for (j = 0; j < 20; j++)
{
if (Data[j][0] == i)
{
DataNum = Data[j][1];
Head[i].insert(DataNum);
}
}
Head[i].print();
}
System.out.println("深度優先遍歷頂點:");
dfs(1);
System.out.println("");
}
}
列表run:用來記錄頂點是否被遍歷過,創建時所有數據都為0,當頂點被遍歷時,對應的索引的值變為1以此來記錄頂點被遍歷過
鏈表Head:該鏈表的每一個Node代表一個頂點,在創建時每個節點內創建了一個新鏈表,新鏈表用來記錄該頂點所有的相鄰頂點
遍歷時設置一個初始頂點(例中為頂點1),然后在Head鏈表里找到對應的索引根據Node里面的鏈表獲取下一個頂點,獲取到后根據run列表的記錄判斷是否被遍歷過。
-
若未被遍歷過就執行遞歸打印,並且Head鏈表根據此頂點索引到對應的Node,重新根據該Node的鏈表重復操作
-
若被遍歷過,就根據Node內的鏈表獲取下一個值重復判斷
先廣后深
Node類和GrapLink類和上文一樣
Main
package BFS算法;
/**
* @author YanAemons
* @date 2021/10/16 17:48
*/
public class Main {
public static int run[] = new int[9];
public static GraphLink Head[] = new GraphLink[9];
public final static int MAXSIZE = 10;
static int[] queue = new int[MAXSIZE];
static int front = -1;
static int rear = -1;
public static int dequeue()
{
if (front == rear ) return -1;
front++;
return queue[front];
}
public static void enqueue(int value)
{
if (rear >= MAXSIZE) return;
rear++;
queue[rear] = value;
}
public static void bfs(int current)
{
Node tempnode;
enqueue(current);
run[current] = 1;
System.out.print("["+current+"]");
while (front != rear)
{
current = dequeue();
tempnode = Head[current].first;
while (tempnode != null)
{
if (run[tempnode.x] == 0)
{
enqueue(tempnode.x);
run[tempnode.x] = 1;
System.out.print("["+tempnode.x+"]");
}
tempnode = tempnode.next;
}
}
}
public static void main(String[] args) {
int[][] Data = {{1,2},{2,1},{1,3},{3,1},{2,4},{4,2},{2,5},{5,2},{3,6},{6,3},{3,7},{7,3},{4,5},{5,4},{6,7},{7,6},{