邻接矩阵保存图
用邻接矩阵来保存图
package Graph;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Graph {
private int[][] edges;
private int numOfEdges;
private List<String> vertexList;
public static void main(String[] args) {
int n = 8;
String vertexs[] = {"A", "B", "C", "D", "E"};
Graph graph = new Graph(vertexs.length);
for(String vertex: vertexs) {
graph.addVertex(vertex);
}
graph.insertEdge(0, 1, 1);
graph.insertEdge(0, 2, 1);
graph.insertEdge(1, 2, 1);
graph.insertEdge(1, 3, 1);
graph.insertEdge(1, 4, 1);
graph.showGraph();
}
public void addVertex(String vertex) {
vertexList.add(vertex);
}
public Graph(int n) {
edges = new int[n][n];
vertexList = new ArrayList<String>(n);
numOfEdges = 0;
}
public void showGraph() {
for (int[] edge : edges) {
System.out.println(Arrays.toString(edge));
}
}
public String getValueByIndex(int i) {
return vertexList.get(i);
}
public void insertEdge(int v1, int v2, int weight) {
edges[v1][v2] = weight;
edges[v2][v1] = weight;
}
}
使用链表储存图
package Graph;
public class LinkedGraphDemo {
public static void main(String[] args) {
String vertexs[] = {"A", "B", "C", "D", "E"};
Integer edge[][] = {{1,3},{2,4},{1,4},{1,2},{2,4},{2,3}};
LinkedGraph graph = new LinkedGraph(vertexs.length);
for (int i = 0; i < vertexs.length; i++) {
graph.linkedLists[i].root = new RootNode(vertexs[i]);
}
for (int i = 0; i < edge.length; i++) {
for (int j = 0; j < edge[i].length; j++) {
System.out.print(edge[i][j]+" ");
}
System.out.println();
}
graph.show();
}
}
class LinkedGraph {
GraphLinkedList[] linkedLists;
int vexNum;
public LinkedGraph(int vexNum) {
this.vexNum = vexNum;
linkedLists = new GraphLinkedList[vexNum];
for (int i = 0; i < linkedLists.length; i++) {
linkedLists[i] = new GraphLinkedList();
}
}
public void show() {
for (int i = 0; i < linkedLists.length; i++) {
linkedLists[i].show();
System.out.println();
}
}
}
class GraphLinkedList {
RootNode root;
public void addNode(int value) {
Node newNode = new Node(value);
if (root.next == null) {
root.next = newNode;
return;
}
Node cur = root.next;
while (cur.next != null) {
cur = cur.next;
}
cur.next = newNode;
}
public void show() {
System.out.print(root.data+"->");
Node cur = root.next;
while (cur != null) {
System.out.print(cur.data + "->");
cur = cur.next;
}
}
}
class Node {
int data;
Node next;
RootNode rootNode;
public Node(int value) {
data = value;
}
}
class RootNode {
String data;
Node next;
public RootNode(String value) {
data = value;
}
}
图的深度优先遍历
所谓图的遍历,即是对结点的访问。一个图有那么多个结点,如何遍历这些结点,需要特定策略,一般有两种访问策略: (1)深度优先遍历 (2)广度优先遍历
深度优先遍历基本思想
图的深度优先搜索(Depth First Search) 。
-
深度优先遍历,从初始访问结点出发,初始访问结点可能有多个邻接结点,深度优先遍历的策略就是首先访问第一个邻接结点,然后再以这个被访问的邻接结点作为初始结点,访问它的第一个邻接结点, 可以这样理解: 每次都在访问完当前结点后首先访问当前结点的第一个邻接结点。
-
我们可以看到,这样的访问策略是优先往纵向挖掘深入,而不是对一个结点的所有邻接结点进行横向访问。
-
显然,深度优先搜索是一个递归的过程
深度优先遍历算法步骤
-
输出v节点,并设置已访问 -
依次检查邻接矩阵 第v 行 有没有没被访问的节点, 值!=0 且 visited = false -
当检测到未被访问的节点时,以w为初始节点进行递归。
package Graph;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Graph {
private int[][] edges;
private int numOfEdges;
private List<String> vertexList;
private boolean[] isVisit;
public static void main(String[] args) {
int n = 8;
String vertexs[] = {"A", "B", "C", "D", "E"};
Graph graph = new Graph(vertexs.length);
for(String vertex: vertexs) {
graph.addVertex(vertex);
}
graph.insertEdge(0, 1, 1);
graph.insertEdge(0, 2, 1);
graph.insertEdge(1, 2, 1);
graph.insertEdge(1, 3, 1);
graph.insertEdge(1, 4, 1);
graph.showGraph();
graph.DFS(0);
}
public void addVertex(String vertex) {
vertexList.add(vertex);
}
public Graph(int n) {
edges = new int[n][n];
vertexList = new ArrayList<String>(n);
numOfEdges = 0;
isVisit = new boolean[n];
}
public void showGraph() {
for (int[] edge : edges) {
System.out.println(Arrays.toString(edge));
}
}
public String getValueByIndex(int i) {
return vertexList.get(i);
}
public void insertEdge(int v1, int v2, int weight) {
edges[v1][v2] = weight;
edges[v2][v1] = weight;
}
public void DFS(int index) {
System.out.print(getValueByIndex(index)+"->");
isVisit[index] = true;
for (int w = index+1; w < edges[index].length; w++) {
if (edges[index][w]!=0 && !isVisit[w]) {
DFS(w);
}
}
}
}
DFS 算法效率分析
用邻接矩阵来表示图,遍历图每一个顶点都要从头扫描该顶点所在行,时间复杂度O(n2)
用邻接表来表示图,虽然有2e个表节点,但只需扫描e个节点即可完成遍历,加上访问n个头节点的时间,时间复杂度为O(n+e)
- 稠密图适用于在邻接矩阵上进行深度遍历
- 稀疏图使用与在邻接表上进行深度遍历。
非连通图的遍历
从一个节点进行深度优先遍历后,再判断哪些顶点仍未被遍历到,从这些顶点开始再继续遍历
public void unConnectDFS(int index) {
DFS(index);
for (int i = 0; i < vertexList.size(); i++) {
if (!isVisit[i]) {
DFS(i);
}
}
}
|