狄克斯特拉算法的Java實現

package cn.like.study.algorithm;

import java.util.*;

/**
 * @program: MyCode
 * @description: 狄克斯特拉算法
 * 算法步驟:1.判斷是否有未處理的節點
 * 2.如有,得到其中離起點最近的節點
 * 3.遍歷該節點全部鄰居並更行其開銷
 * 4.若是有鄰居的開銷被更新,同時更新父節點
 * 5.該節點標記爲已處理
 * 6.重複第1步
 * @author: like
 * @create: 2018-04-22 10:49
 **/
public class Dijkstra {
    //設置沒有已知到達路徑的標記
    private static int NOWAY_SIGN = Integer.MAX_VALUE;
    private static final String START = "start";
    private static final String END = "end";

    public void getMinStep(String start, String end, Map<String, Map<String, Integer>> graph) {
        //各節點的最少花費
        Map<String, Integer> costs = graph.get(start);
        //各節點最少花費時的父節點
        Map<String, String> parents = new HashMap<String, String>();
        //已處理的節點
        HashSet<String> processed = new HashSet<String>();
        //在未處理的節點中找到開銷最小的節點
        String node = findLowestCostNode(costs, processed);
        while (node != null && graph.get(node) != null) {
            int cost = costs.get(node);
            //遍歷當前節點的全部鄰居
            Iterator iterator = graph.get(node).entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, Integer> entry = (Map.Entry) iterator.next();
                //經過node節點到該節點的最小消耗
                int newCost = cost + entry.getValue();
                //更新從start到該節點的最小消耗
                if (!costs.containsKey(entry.getKey()) || costs.get(entry.getKey()) > newCost) {
                    costs.put(entry.getKey(), newCost);
                    parents.put(entry.getKey(), node);
                }
            }
            //該節點加入已處理
            processed.add(node);
            //找出當前最小消耗的節點
            node = findLowestCostNode(costs, processed);
        }
        printPath(parents, costs.get(END));
    }

    public void initParents(String start, Map<String, Integer> startGraph, Map<String, String> parents) {
        Iterator iterator = startGraph.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Integer> entry = (Map.Entry) iterator.next();
            parents.put(entry.getKey(), start);
        }
    }

    /**
     * 找出未處理節點中消耗最小的節點
     *
     * @param costs
     * @param processed
     * @return
     */
    public String findLowestCostNode(Map<String, Integer> costs, HashSet<String> processed) {
        int lowestCost = NOWAY_SIGN;
        String lowestCostNode = null;
        Iterator iterator = costs.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Integer> entry = (Map.Entry) iterator.next();
            if (!processed.contains(entry.getKey()) && entry.getValue() < lowestCost) {
                lowestCost = entry.getValue();
                lowestCostNode = entry.getKey();
            }
        }
        return lowestCostNode;
    }

    public void printPath(Map<String, String> parents, int cost) {
        Stack<String> stack = new Stack<String>();
        String parent = parents.get(END);
        while (parent != null) {
            if (START.equalsIgnoreCase(parent)) {
                stack.push(START);
                break;
            }
            stack.push(parent);
            parent = parents.get(parent);
        }
        StringBuffer path = new StringBuffer();
        while (!stack.empty()) {
            String node = stack.pop();
            if (path.length() != 0) {
                path.append("->");
            }
            path.append(node);
        }
        System.out.println("最優路線:" + START + "->" + path.toString() + "->" + END);
        System.out.println("其開銷爲:" + cost);
    }

    public static void main(String[] args) {
        Map<String, Map<String, Integer>> graph = new HashMap<String, Map<String, Integer>>();
        Map<String, Integer> start = new HashMap<String, Integer>();
        start.put("A", 5);
        start.put("B", 2);
        graph.put(START, start);
        Map<String, Integer> a = new HashMap<String, Integer>();
        a.put("C", 4);
        a.put("D", 2);
        graph.put("A", a);
        Map<String, Integer> b = new HashMap<String, Integer>();
        b.put("A", 8);
        b.put("D", 7);
        graph.put("B", b);
        Map<String, Integer> c = new HashMap<String, Integer>();
        c.put("D", 6);
        c.put(END, 3);
        graph.put("C", c);
        Map<String, Integer> d = new HashMap<String, Integer>();
        d.put(END, 1);
        graph.put("D", d);
        Dijkstra dijkstra = new Dijkstra();
        dijkstra.getMinStep(START, END, graph);
    }
}

測試示例:java

輸出結果:node

最優路線:start->A->D->end
其開銷爲:8算法

相關文章
相關標籤/搜索