图的基本操作
作者:互联网
图的表示方式:
- 用二维数组表示的邻接矩阵
- 用数组加链表表示的邻接表
图的基本方法:
-
建图:(插入图顶点和插入图的边)
图的顶点用ArrayList<String>存储,边用二维数组edges[][] 存储。
ArrayList<String> vertex;
int [][]edges;
public void insertVertex(String s) {//插入顶点
vertex.add(s);
}
public void insertEdge(int a,int b,int weight) {//插入边(无向图)
edges[a][b] = weight;
edges[b][a] = weight;
numOfEdge++;
}
-
输出邻接矩阵:
public void printGragh() {//输出二维edges
for(int[] data : edges) {
System.out.println(Arrays.toString(data));
}
}
-
找图的某一顶点的第一个邻接点:
无论dfs还是bfs都需要找顶点的邻接点和该邻接点的下一邻接点
public int getFirstNeighbor(int i) {//i为图中的某一顶点
for(int j = 0; j < edges[i].length;j++) {
if(edges[i][j] > 0) {
return j;
}
}
return -1;
}
-
找图的某一顶点的邻接点的下一个邻接点:
public int getNextNeighbor(int i,int j) {//i为图的某一顶点,j为已知的邻接点,返回j的下一邻接点
for(int k = j + 1;k < edges[i].length;k++) {
if(edges[i][k] > 0) {
return k;
}
}
return -1;
}
-
深度优先搜索:
深度优先遍历是从出初始点出发,初始点可能会有多个邻接点,深搜的策略是首先访问第一个邻接点,然后再以这个被访问的邻接点作为初始结点,访问它的第一个邻接结点,以此递归。即深度优先搜索每次都是优先往纵向访问。
private void dfs(boolean isVisited[],int i) {
System.out.print(vertex.get(i) + " ");
isVisited[i] = true;
int index = getFirstNeighbor(i);
while(index != -1) {
if(!isVisited[index]) {
dfs(isVisited, index);
}
index = getNextNeighbor(i, index);
}
}
public void dfs() {//对上个方法重载,使得每个结点都有机会被访问
isVisited = new boolean[vertex.size()];
for(int i = 0; i < vertex.size();i++) {
if(!isVisited[i]) {
dfs(isVisited, i);
}
}
}
-
广度优先搜索:
广度优先搜索类似于树的层序遍历,在从初始结点出发时,要将该结点的邻接点一次性都访问完,同时将它的所有邻接点用队列结构保存,再访问这些邻接点为顶点的邻接点。即广度优先搜索每次都是优先往横向访问。
public void bfs(boolean isVisited[],int i) {
LinkedList<Integer> queue = new LinkedList<>();
System.out.print(vertex.get(i) + " ");
queue.addLast(i);
isVisited[i] = true;
while(!queue.isEmpty()) {
Integer index = queue.removeFirst();
int j = getFirstNeighbor(index);
while(j != -1) {
if(!isVisited[j]) {
System.out.print(vertex.get(j) + " ");
isVisited[j] = true;
queue.addLast(j);
}
j = getNextNeighbor(index, j);
}
}
}
public void bfs() {//对上个方法重载,使图的每个结点都能被访问到
boolean []isVisited = new boolean[vertex.size()];
for(int i = 0; i < vertex.size();i++) {
if(!isVisited[i]) {
bfs(isVisited, i);
}
}
}
对下面无向图实现深搜和广搜:
java代码(邻接矩阵):
import java.util.*;
public class GraphTest {
public static void main(String[] args) {
Graph graph = new Graph(8);
String[]vertex = {"1","2","3","4","5","6","7","8"};
for(int i = 0; i < vertex.length;i++) {
graph.insertVertex(vertex[i]);
}
graph.insertEdge(0, 1, 1);
graph.insertEdge(0, 2, 1);
graph.insertEdge(1, 3, 1);
graph.insertEdge(1, 4, 1);
graph.insertEdge(3, 7, 1);
graph.insertEdge(4, 7, 1);
graph.insertEdge(2, 5, 1);
graph.insertEdge(2, 6, 1);
graph.insertEdge(5, 6, 1);
graph.printGragh();
System.out.println("图的深度优先遍历顺序:");
graph.dfs();
System.out.println();
System.out.println("图的广度优先遍历顺序:");
graph.bfs();
}
}
class Graph{
ArrayList<String> vertex;
int [][]edges;
int numOfEdge;
boolean []isVisited;
public Graph(int n) {
vertex = new ArrayList<String>(n);
edges = new int [n][n];
numOfEdge = 0;
}
public void insertVertex(String s) {
vertex.add(s);
}
public void insertEdge(int a,int b,int weight) {
edges[a][b] = weight;
edges[b][a] = weight;
numOfEdge++;
}
public void printGragh() {
for(int[] data : edges) {
System.out.println(Arrays.toString(data));
}
}
public int getFirstNeighbor(int i) {
for(int j = 0; j < edges[i].length;j++) {
if(edges[i][j] > 0) {
return j;
}
}
return -1;
}
public int getNextNeighbor(int i,int j) {
for(int k = j + 1;k < edges[i].length;k++) {
if(edges[i][k] > 0) {
return k;
}
}
return -1;
}
private void dfs(boolean isVisited[],int i) {
System.out.print(vertex.get(i) + " ");
isVisited[i] = true;
int index = getFirstNeighbor(i);
while(index != -1) {
if(!isVisited[index]) {
dfs(isVisited, index);
}
index = getNextNeighbor(i, index);
}
}
public void dfs() {
isVisited = new boolean[vertex.size()];
for(int i = 0; i < vertex.size();i++) {
if(!isVisited[i]) {
dfs(isVisited, i);
}
}
}
public void bfs(boolean isVisited[],int i) {
LinkedList<Integer> queue = new LinkedList<>();
System.out.print(vertex.get(i) + " ");
queue.addLast(i);
isVisited[i] = true;
while(!queue.isEmpty()) {
Integer index = queue.removeFirst();
int j = getFirstNeighbor(index);
while(j != -1) {
if(!isVisited[j]) {
System.out.print(vertex.get(j) + " ");
isVisited[j] = true;
queue.addLast(j);
}
j = getNextNeighbor(index, j);
}
}
}
public void bfs() {
boolean []isVisited = new boolean[vertex.size()];
for(int i = 0; i < vertex.size();i++) {
if(!isVisited[i]) {
bfs(isVisited, i);
}
}
}
}
输出:
[0, 1, 1, 0, 0, 0, 0, 0]
[1, 0, 0, 1, 1, 0, 0, 0]
[1, 0, 0, 0, 0, 1, 1, 0]
[0, 1, 0, 0, 0, 0, 0, 1]
[0, 1, 0, 0, 0, 0, 0, 1]
[0, 0, 1, 0, 0, 0, 1, 0]
[0, 0, 1, 0, 0, 1, 0, 0]
[0, 0, 0, 1, 1, 0, 0, 0]
图的深度优先遍历顺序:
1 2 4 8 5 3 6 7
图的广度优先遍历顺序:
1 2 3 4 5 6 7 8
标签:index,int,vertex,edges,基本操作,public,isVisited 来源: https://blog.csdn.net/weixin_48898946/article/details/120907494