特点:

图形结构中,每个结点的前驱结点数和后续结点数可以任意多个,能表示多对多的关系。

存储方式

邻接矩阵:一个int[n][n]的二维数组,其中n为图的节点数,图节点关系稀疏时浪费空间很严重

邻接表:每个节点通过链表存储与之相连的节点信息

 

使用邻接矩阵实现一个图,并实现深度优先搜索和广度优先搜索

深度优先遍历思路:

从某一个顶点出发,访问与它邻接的一个顶点,然后再从该顶点出发,访问一个与它邻接并且未访问过的节点,如果存在这样的顶点则访问,不存在则返回上一个顶点寻找另一个与它邻接并且未访问的顶点。如果回到第一个顶点,则从存储的下一个未访问的节点出发。

广度优先遍历思路:

从某一个顶点出发,访问与它邻接的所有顶点,并且存储在队列中,然后从队头开始,访问队列中的每一个顶点的邻接顶点(未访问的)并存在队列中,直到队列为空,再从存储的下一个未访问顶点出发。

先定义类和常用方法:

public class Graph { //无向图
	private ArrayList<String> vertexList; //存储顶点集合
	private int[][] edges; //存储图对应的邻接矩阵
	private int edgeCount; //边的条数
	public Graph(int n) { //构造器,传入顶点个数
		vertexList = new ArrayList<String>(n);
		edges = new int[n][n];
	}
	//插入节点
	public void insertVertex(String vertex) {
		vertexList.add(vertex);
	}
	//添加边
	public void addEdge(int v1,int v2,int weight) {
		edges[v1][v2] = weight;
		edges[v2][v1] = weight;
		edgeCount++ ;
	}
	//获取顶点个数
	public int getNumOfVertex() { 
		return vertexList.size();
	}
	//获取边的条数
	public int vertexList() { 
		return edgeCount;
	}
	//通过顶点索引获取顶点值
	public String getValueByIndex(int i) { 
		return vertexList.get(i);
	}
	//返回边的权值
	public int getEdgebyIndex(int v1,int v2) {
		return edges[v1][v2];
	}
	//显示邻接矩阵
	public void showEdges() {
		for(int[] arr:edges) {
			System.out.println(Arrays.toString(arr));
		}
	}
}

 深度优先搜索

//从下标start开始查找index节点的邻接点
private int getBorder(int index,int start) {
	for(int j=start;j<vertexList.size();j++) {
		if( edges[index][j] > 0) {
			return j;
		}
	}
	return -1;
}
//访问某个顶点,并递归访问它的未访问邻接顶点
private void dfs(boolean[] isVisited,int i) {
	System.out.print(getValueByIndex(i)+ "->");//访问该节点
	isVisited[i] = true;//把该节点设置为已访问
	int border = getBorder(i,0);//查找节点i的第一个邻接点
	while(border != -1) {
		if(!isVisited[border]) {
			dfs(isVisited,border);
		}
		border = getBorder(i, border + 1);//访问i的邻接点中border的下一个邻接点
	}
}
public void dfs(){
	boolean[] isVisited = new boolean[vertexList.size()];//记录顶点是否被访问过
	for(int i=0;i<vertexList.size();i++) {
		if(!isVisited[i]) {
			dfs(isVisited,i);
		}
	}
}

广度优先搜索

public void bfs(){
	boolean[] isVisited = new boolean[vertexList.size()];//记录顶点是否被访问过
      //存储未访问邻接点的队列
	ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(vertexList.size());
	for(int i=0;i<vertexList.size();i++) {
		if(!isVisited[i]) {
			System.out.print(getValueByIndex(i)+ "->");//访问该节点
			isVisited[i] = true;//把该节点设置为已访问
			bfs(isVisited,queue,i);
		}
	}
}
private void bfs(boolean[] isVisited,ArrayBlockingQueue<Integer> queue,int i) {
    for(int j=i;j<vertexList.size();j++) {
		if( edges[i][j] > 0 && isVisited[j] == false) {
			queue.add(j); //把未访问的邻接点加入队列
			System.out.print(getValueByIndex(j)+ "->");//把该节点设置为已访问
			isVisited[j] = true;	
		}
	}
	while(!queue.isEmpty()) {
		int index = queue.poll();
		bfs(isVisited,queue,index);
	}
}

使用该类创建一个图,如下图的关系

public static void main(String[] args) {
	String[] vertexs = {"A","B","C","D","E","F"};
	int n = vertexs.length;
	Graph graph = new Graph(n);
	for(String vertex:vertexs) {
		graph.insertVertex(vertex);
	}
	graph.addEdge(0, 1, 1);
	graph.addEdge(0, 2, 2);
	graph.addEdge(0, 4, 4);
	graph.addEdge(1, 3, 3);
	graph.addEdge(2, 3, 2);
	graph.addEdge(2, 4, 3);
	graph.addEdge(2, 5, 5);
	graph.addEdge(3, 5, 4);
	System.out.println("邻接矩阵:");
	graph.showEdges();
	System.out.println("深度遍历:");
	graph.dfs();
	System.out.println("\n广度遍历:");
	graph.bfs();
}

运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值