图
1、图的一些基本概念
- 图:每个节点都可以有零个或多个前驱,也可以有零个或多个后继,也就是说,元素之间的关系是任意的。也可以称为多对多。
- 节点:组成图的重要部分
- 边:两个节点的连接
- 无向图:节点之间的连接没有方向
- 有向图:节点之间的连接有方向
- 带权图(网):权就是节点中的值
- 路径:一个节点到另一个节点所经过的路程
- 图的表示方法
- 邻接矩阵(用二维数组表示):表示图形之中节点间相邻关系的矩阵
- 邻接表(用数组+链表表示):数组之中存放了这个图中所有的节点,每一个数组又是一个链表的头节点,该链表表示这个节点与多少个节点有连接
- 图的深度优先遍历:先遍历每一个节点的第一个邻接节点,也就是纵向的遍历
- 步骤:
- 1、访问初始节点 i,并将该节点标记为已访问
- 2、查找节点 i的第一个邻接节点 j
- 3、若 j存在:
- 若 j未被访问,则对 j进行深度优先遍历,也就是把 j当作新的 i,递归
- 若 j被访问,则对 i的的其他邻接节点继续重复上述步骤
- 4、若 j不存在:则对 i的其他邻接节点继续重复上述步骤,若没有其他邻接节点,就结束该递归,回到上一层
- 5、直至所有的节点都已判断完毕,结束
- 图的广度优先遍历:先遍历一个节点的所有邻接节点,再去遍历其他节点,也就是横向的遍历,类似于一个分层搜索,需要先使用一个队列保持访问过的节点的顺序,以便于按照这个顺序访问这些节点的邻接节点。
- 步骤:
- 1、访问初始节点 i,并将该节点标记为已访问,该节点入队列
- 2、当队列为非空的时候,继续执行,否则算法结束(注意:这里的算法结束是指对当前 i的算法)
- 3、出队列,取得该队列的头部节点 j
- 4、查找节点 j的第一个邻接节点 k
- 1、若节点 k不存在,则回到 3
- 2、若节点 k存在,则:
- 1、若节点 k未被访问,则将 k标记为已访问,k入队列
- 2、查找节点 j的继节点 k的下一个邻接节点 k,回到步骤 5
2、一些常用的方法
public int getNumOfVertex() {
return vertexList.size();
}
public int getNumOfEdges() {
return numOfEdges;
}
public String getValueByIndex(int i) {
return vertexList.get(i);
}
public int getWeight(int v1, int v2) {
return edges[v1][v2];
}
public void showGraph() {
for (int[] link : edges) {
System.out.println(Arrays.toString(link));
}
}
public int getFirstNeighbor(int i) {
for (int j = 0; j < vertexList.size(); j++) {
if (edges[i][j] > 0) {
return j;
}
}
return -1;
}
public int getNextNeighbor(int v1, int v2) {
for (int j = v2 + 1; j < vertexList.size(); j++) {
if (edges[v1][j] > 0) {
return j;
}
}
return -1;
}
3、深度优先遍历
private void dfs(boolean[] isVisited, int i) {
System.out.print(getValueByIndex(i) + "->");
isVisited[i] = true;
int j = getFirstNeighbor(i);
while (j != -1) {
if (!isVisited[j]) {
dfs(isVisited, j);
}
j = getNextNeighbor(i, j);
}
}
public void dfs() {
for (int i = 0; i < getNumOfVertex(); i++) {
if (!isVisited[i]) {
dfs(isVisited, i);
}
}
}
4、广度优先遍历
private void bfs(boolean[] isVisited, int i) {
int j;
int k;
LinkedList queue = new LinkedList();
System.out.print(getValueByIndex(i) + "->");
isVisited[i] = true;
queue.add(i);
while (!queue.isEmpty()) {
j = (Integer) queue.removeFirst();
k = getFirstNeighbor(i);
while (k != -1) {
if (!isVisited[i]) {
System.out.print(getValueByIndex(i) + "->");
isVisited[i] = true;
queue.addLast(k);
}
k = getNextNeighbor(j, k);
}
}
}
public void bfs() {
for (int i = 0; i < getNumOfVertex(); i++) {
if (!isVisited[i]) {
bfs(isVisited, i);
}
}
}
5、完整的代码
public class GraphDemo {
private ArrayList<String> vertexList;
private int[][] edges;
private int numOfEdges;
private boolean[] isVisited;
public static void main(String[] args) {
int n = 5;
String vertexs[] = {"A", "B", "C", "D", "E"};
GraphDemo graph1 = new GraphDemo(n);
for (String vertex : vertexs) {
graph1.insertVertex(vertex);
}
graph1.insertEdge(0, 1, 1);
graph1.insertEdge(0, 2, 1);
graph1.insertEdge(1, 2, 1);
graph1.insertEdge(1, 3, 1);
graph1.insertEdge(1, 4, 1);
graph1.showGraph();
System.out.println("深度优先遍历:");
graph1.dfs();
System.out.println();
System.out.println("------------------------");
GraphDemo graph2 = new GraphDemo(n);
for (String vertex : vertexs) {
graph2.insertVertex(vertex);
}
graph2.insertEdge(0, 1, 1);
graph2.insertEdge(0, 2, 1);
graph2.insertEdge(1, 2, 1);
graph2.insertEdge(1, 3, 1);
graph2.insertEdge(1, 4, 1);
graph2.showGraph();
System.out.println("广度优先遍历:");
graph2.bfs();
}
public GraphDemo(int n) {
edges = new int[n][n];
vertexList = new ArrayList<String>(n);
numOfEdges = 0;
isVisited = new boolean[n];
}
public void insertVertex(String vertex) {
vertexList.add(vertex);
}
public void insertEdge(int v1, int v2, int weight) {
edges[v1][v2] = weight;
edges[v2][v1] = weight;
numOfEdges++;
}
public int getNumOfVertex() {
return vertexList.size();
}
public int getNumOfEdges() {
return numOfEdges;
}
public String getValueByIndex(int i) {
return vertexList.get(i);
}
public int getWeight(int v1, int v2) {
return edges[v1][v2];
}
public void showGraph() {
for (int[] link : edges) {
System.out.println(Arrays.toString(link));
}
}
public int getFirstNeighbor(int i) {
for (int j = 0; j < vertexList.size(); j++) {
if (edges[i][j] > 0) {
return j;
}
}
return -1;
}
public int getNextNeighbor(int v1, int v2) {
for (int j = v2 + 1; j < vertexList.size(); j++) {
if (edges[v1][j] > 0) {
return j;
}
}
return -1;
}
private void dfs(boolean[] isVisited, int i) {
System.out.print(getValueByIndex(i) + "->");
isVisited[i] = true;
int j = getFirstNeighbor(i);
while (j != -1) {
if (!isVisited[j]) {
dfs(isVisited, j);
}
j = getNextNeighbor(i, j);
}
}
public void dfs() {
for (int i = 0; i < getNumOfVertex(); i++) {
if (!isVisited[i]) {
dfs(isVisited, i);
}
}
}
private void bfs(boolean[] isVisited, int i) {
int j;
int k;
LinkedList queue = new LinkedList();
System.out.print(getValueByIndex(i) + "->");
isVisited[i] = true;
queue.add(i);
while (!queue.isEmpty()) {
j = (Integer) queue.removeFirst();
k = getFirstNeighbor(i);
while (k != -1) {
if (!isVisited[i]) {
System.out.print(getValueByIndex(i) + "->");
isVisited[i] = true;
queue.addLast(k);
}
k = getNextNeighbor(j, k);
}
}
}
public void bfs() {
for (int i = 0; i < getNumOfVertex(); i++) {
if (!isVisited[i]) {
bfs(isVisited, i);
}
}
}
}