图的基本操作

本文详细介绍了使用邻接矩阵表示的无向图,并提供了插入顶点和边的方法,以及输出邻接矩阵、查找邻接点等功能。接着,实现了深度优先搜索(DFS)和广度优先搜索(BFS)算法,分别给出了两种搜索策略的遍历顺序。示例代码展示了如何在给定的无向图中应用这两种搜索方法。
摘要由CSDN通过智能技术生成

图的表示方式:

  • 用二维数组表示的邻接矩阵
  • 用数组加链表表示的邻接表

图的基本方法:

  • 建图:(插入图顶点和插入图的边)

图的顶点用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 

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值