java interview --- minimum path of graph

no weight

In finding the minimum path, there are many topics in the graph, and in the case of no weight, finding the minimum path is the breadth-first traversal of the graph. Breadth-first traversal is achieved by relying on queues. Since it is relatively simple, the code is not posted here.

Why breadth first

There are two types of graph traversal: depth and breadth, so why use breadth to find the minimum path? In fact, the condition for his establishment is that there is no weight, that is, the consumption of each path is the same. Breadth-first traversal corresponds to the hierarchical traversal of the tree, which is better understood. Since the hierarchical traversal of the tree is viewed layer by layer, the case with the smallest number of layers is the shortest case.

No negative weights

Without negative weights, Dijkstra is a good choice. Dijkstra is basically what is taught in university algorithm classes. In fact, the algorithm idea is good, and it is a little more complicated to write.

Algorithm explanation

Dijkstra's focus is on filling an icon.

node spend whether to visit

Dijkstra

Next, let's combine an example to illustrate how this form is filled! [Image description][1] [1]: //img.mukewang.com/5af006730001aff410080630.png

As shown above, the starting point is a and the end point is f.

Initialize the form

We initialize the table first, because a is the starting point, so it is not included in the calculation. This calculation is actually to initialize the starting point related to the table. b is reachable, and the rest of the nodes are unreachable, so the default cost is none.

node spend whether to visit
b 2 -
c - -
d - -
e - -
f - -

Find the node with the least consumption

According to the above figure, the minimum consumption is b

continue to visit the node

b is considered to have been visited, b to c is 4, so the cost of c is 6, and so on for other f, d, e

node spend whether to visit
b 2 Yes
c 6 -
d 3 -
e - -
f 7 -

repeated steps

  1. Find the smallest unvisited node
  2. Visit the neighbor nodes of a node
  3. Update the graph to save the least expensive value

result

node spend whether to visit
b 2 Yes
c 6 Yes
d 3 Yes
e 6 Yes
f 7 Yes

The end point is f, the result is 7

draw the path

The above situation is only to find the minimum consumption. If you want to find the path, just modify the table and save the corresponding parent node.

node parent node spend whether to visit

Code


public class Dijkstra {

	public static void main(String[] args) {
		String[] startEnd = new String[2];
		Map<String, Node> initData = initData(startEnd);
		Set<String> process = new HashSet<>();
		Map<String, NodeCost> costList = new HashMap<>();

		init(initData, costList, startEnd[0]);
		find(initData, process, costList);

		NodeCost nodeCost = costList.get(startEnd[1]);
		LinkedList<String> list = new LinkedList<>();
		System.out.println(nodeCost.cost);
		list.addFirst(nodeCost.current);
		while (nodeCost != null) {

			list.addFirst(nodeCost.parent);
			nodeCost = costList.get(nodeCost.parent);
		}
		System.out.println(list);

	}

	
	public static void find(Map<String, Node> initData, Set<String> process, Map<String, NodeCost> costList) {
		NodeCost minNode = getMinNode(process, costList);
		while (minNode != null) {
			Node node = initData.get(minNode.current);
			Map<String, Integer> nextNode = node.nextNode;
			Iterator<Entry<String, Integer>> iterator = nextNode.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<String, Integer> next = iterator.next();
				int cost = minNode.cost + next.getValue();
				NodeCost nodeCost = costList.get(next.getKey());
				int oldCost = nodeCost.cost;
				if (oldCost > cost) {
					nodeCost.parent = node.name;
					nodeCost.cost = cost;
				}
			}
			process.add(node.name);
			minNode = getMinNode(process, costList);

		}

	}

	
	//找出最小消耗没有访问过的节点
	public static NodeCost getMinNode(Set<String> process, Map<String, NodeCost> costList) {

		Collection<NodeCost> values = costList.values();
		NodeCost preCost = null;

		for (NodeCost cost : values) {
			if (!process.contains(cost.current)) {
				if (preCost == null) {
					preCost = cost;
				} else if (preCost.cost >= cost.cost) {
					preCost = cost;
				}
			}

		}

		return preCost;
	}

	
	//初始化图表耗费
	public static void init(Map<String, Node> initData, Map<String, NodeCost> costList, String start) {
		Collection<Node> values = initData.values();
		Iterator<Node> iteratorValues = values.iterator();
		while (iteratorValues.hasNext()) {

			Node node = iteratorValues.next();
			Map<String, Integer> nextNode = node.nextNode;
			Iterator<Entry<String, Integer>> iterator = nextNode.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<String, Integer> next = iterator.next();
				NodeCost cost = new NodeCost();
				cost.parent = node.name;
				cost.current = next.getKey();
				if (node.name.equals(start)) {
					cost.cost = next.getValue();
				} else {
					cost.cost = Integer.MAX_VALUE;
				}
				NodeCost oldCost = costList.get(next.getKey());
				if (oldCost == null || oldCost.cost == Integer.MAX_VALUE) {
					costList.put(next.getKey(), cost);
				}

			}
		}

	}

	
	//初始化图结构
	public static Map<String, Node> initData(String[] startEnd) {
		Map<String, Node> node = new HashMap<>();

		Node a = new Node();
		a.name = "a";
		a.nextNode = new HashMap<String, Integer>() {
			{
				put("b", 5);
				put("f", 2);
			}

		};

		node.put("a", a);

		Node b = new Node();
		b.name = "b";
		b.nextNode = new HashMap<String, Integer>() {
			{
				put("c", 4);
				put("e", 2);
			}

		};
		node.put("b", b);

		Node c = new Node();
		c.name = "c";
		c.nextNode = new HashMap<String, Integer>() {
			{
				put("d", 3);
				put("e", 6);
			}

		};
		node.put("c", c);

		Node d = new Node();
		d.name = "d";

		node.put("d", d);

		Node e = new Node();
		e.name = "e";
		e.nextNode = new HashMap<String, Integer>() {
			{

				put("d", 1);
			}

		};
		node.put("e", e);

		Node f = new Node();
		f.name = "f";
		f.nextNode = new HashMap<String, Integer>() {
			{

				put("b", 8);
				put("e", 7);
			}

		};
		node.put("f", f);

		startEnd[0] = "a";
		startEnd[1] = "d";

		return node;
	}

}


//图表的结构
class NodeCost {
	String current;
	String parent;
	Integer cost;

	public String getCurrent() {
		return current;
	}

	public void setCurrent(String current) {
		this.current = current;
	}

	public String getParent() {
		return parent;
	}

	public void setParent(String parent) {
		this.parent = parent;
	}

	public int getCost() {
		return cost;
	}

	public void setCost(int cost) {
		this.cost = cost;
	}

	@Override
	public String toString() {
		return "NodeCost [current=" + current + ", parent=" + parent + ", cost=" + cost + "]";
	}

}

//原始数据结构
class Node {
	String name;
	Map<String, Integer> nextNode = new HashMap<>();

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Map<String, Integer> getNextNode() {
		return nextNode;
	}

	public void setNextNode(Map<String, Integer> nextNode) {
		this.nextNode = nextNode;
	}

}

There is a lot of code here, but most of them are to initialize the structure of the graph, and the real number of operation gut codes can still be viewed.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325609665&siteId=291194637