生成图和图的宽度优先遍历和深度优先遍历

一个图有边和结点,边包含权重、入结点和出结点,结点包含值、入度、出度、next结点集、和边的集合。可以用以下代码表示:

public class Edge {
	public int weight;
	public Node from;
	public Node to;
	
	public Edge(int weight, Node from, Node to) {
		this.weight = weight;
		this.from = from;
		this.to = to;
	}
}

public class Node {
	public int value;
	public int in;
	public int out;
	public 	ArrayList<Node> nexts;
	public ArrayList<Edge> edges;
	
	public Node(int value) {
		this.value = value;
		in = 0;
		out = 0;
		nexts = new ArrayList<>();
		edges = new ArrayList<>();
	}
}

public class Graph {
	public HashMap<Integer, Node> nodes;
	public HashSet<Edge> edges;
	public Graph() {
		nodes = new HashMap<>();
		edges = new HashSet<>();
	}
}

而生成图时,可以提供一个二维数组,每个子数组为边的权重、边的入结点和出结点,可以用以下代码表示:

public class GraphGenerator {
	public  static Graph createGraph(Integer[][] matrix) {
		Graph graph = new Graph();
		for(int i = 0; i < matrix.length; i++) {
			Integer weight = matrix[i][0];
			Integer from = matrix[i][1];
			Integer to = matrix[i][2];
			if(!graph.nodes.containsKey(from)) {
				graph.nodes.put(from, new Node(from));
			}
			if(!graph.nodes.containsKey(to)) {
				graph.nodes.put(to, new Node(to));
			}
			Node fromNode = graph.nodes.get(from);
			Node toNode = graph.nodes.get(to);
			Edge newEdge = new Edge(weight, fromNode, toNode);
			fromNode.nexts.add(toNode);
			fromNode.out++;
			toNode.in++;
			fromNode.edges.add(newEdge);
			graph.edges.add(newEdge);
		}
		return graph;
	}
}

图生成后就可以来看宽度优先遍历和深度优先遍历了。

宽度优先遍历:用队列和set来实现。思想是按层遍历,把根结点输出,把根节点的所有next结点放进队列,一次输出next结点同时把他的所有next结点放进队列就完成了。set用来表示是否打印过。代码如下所示:

public class BFS {
	public static void bfs(Node node) {
		if(node == null) {
			return;
		}
		Queue<Node> queue = new LinkedList<>();
		HashSet<Node> set = new HashSet<>();
		queue.add(node);
		set.add(node);
		while(!queue.isEmpty()) {
			Node cur = queue.poll();
			System.out.println(cur.value);
			for(Node next : cur.nexts) {
				if(!set.contains(next)) {
					set.add(next);
					queue.add(next);
				}
			}
		}
	}
}

深度优先遍历:用栈和set来实现。思想是先遍历根节点的一个next结点的所有next结点,遍历完之后再遍历根节点的其他next结点。代码如下所示:

public class DFS {
	public static void dfs(Node node) {
		if(node == null) {
			return;
		}
		Stack<Node> stack = new Stack<>();
		HashSet<Node> set = new HashSet<>();
		stack.add(node);
		set.add(node);
		System.out.println(node.value);
		while(!stack.isEmpty()) {
			Node cur = stack.pop();
			for(Node next : cur.nexts) {
				if(!set.contains(next)) {
					stack.push(cur);
					stack.push(next);
					set.add(next);
					System.out.println(next.value);
					break;//注意这是就放进根节点和最左边的结点就break
				}
			}
		}
	}
}

 

    原文作者:数据结构之图
    原文地址: https://blog.csdn.net/m0_37930105/article/details/84308750
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞