算法与数据结构——Dijkstra算法

单源最短路径

  给定一个带权有向图G=(V,E),其中每条边的权是一个实数。另外,还给定V中的一个顶点,称为源。现在要计算从源到其他所有各顶点的最短路径长度。这里的长度就是指路上各边权之和。这个问题通常称为单源最短路径问题。
  Dijkstra算法和图的广度优先搜索算法有很多相似,不同之处除了距离(在广度优先搜索中称为度数)和权重有关外,算法遍历过程是从队列中取距离最小的节点,即使用优先队列,而不是普通队列。

算法导论中算法执行过程

算法与数据结构——Dijkstra算法_第1张图片

代码

import java.util.*;

public class Dijkstra {

    private static void initializeSingleSource(List g, Node s) {
        for (Node n : g) {
            n.d = 1 << 30;
            n.pre = null;
        }

        s.d = 0;
    }

    private static void relax(Node u, Node v, int w) {
        if (v.d > (u.d + w)) {
            v.d = u.d + w;
            v.pre = u;
        }
    }

    private static void dukstra(List g, Node s) {
        initializeSingleSource(g, s);
        Set alreadyScan = new LinkedHashSet<>();
        Queue q = new PriorityQueue<>(new Comparator() {
            @Override
            public int compare(Node o1, Node o2) {
                return o1.d - o2.d;
            }
        });

        q.addAll(g);

        Node u;
        while (q.size() != 0) {
            u = q.poll();

            alreadyScan.add(u);

            if (u.next != null && u.next.size() != 0) {
                for (int i = 0; i < u.next.size(); i++) {
                    relax(u, u.next.get(i), u.w.get(i));
                }
            }
        }

    }

    private enum Color {

        WHITE(0, "white"),
        GRAY(1, "gray"),
        BLACK(2, "black");

        private int value;
        private String desc;

        Color(int value, String desc) {
            this.value = value;
            this.desc = desc;
        }
    }


    static class Node {
        public Node pre;
        public List next;
        public List w;
        public Color color;
        // BFS中作为与指定节点的度数,DFS中作为首次访问该节点的时间
        public int d;
        // 深度优先遍历中使用,节点深度遍历访问完成的时间,与其连接的结点都已经访问过
        public int f;
        public int value;
    }

    /**
     * 生成有向图,结点数量为count
     * 使用邻接链表表示图
     *
     * @param count
     * @return
     */
    private static List generateDirectedGraph(int count) {

        // 控制结点与其他结点连接的概率
        int p = 6;
        int bound = 10;

        List allNode = new ArrayList<>();

        for (int i = 0; i < count; i++) {
            Node node = new Node();
            node.value = i;
            allNode.add(node);
        }

        Random random = new Random();

        for (int i = 0; i < count; i++) {
            for (int j = 0; j < count; j++) {
                if (i == j) {
                    continue;
                }

                if (random.nextInt(bound) < p) {
                    List iNextList = allNode.get(i).next;
                    List wList = allNode.get(i).w;
                    if (iNextList == null) {
                        iNextList = new ArrayList<>();
                        allNode.get(i).next = iNextList;

                        wList = new ArrayList<>();
                        allNode.get(i).w = wList;

                    }
                    iNextList.add(allNode.get(j));
                    wList.add(random.nextInt(100));
                }
            }
        }

        return allNode;
    }

    public static void printGraph(List allNode) {
        for (Node node : allNode) {
            if (node.next != null && node.next.size() != 0) {
                StringBuilder next = new StringBuilder();
                for (int i = 0; i < node.next.size(); i++) {
                    next.append(node.next.get(i).value);
                    next.append("(" + node.w.get(i) + ")");
                    next.append(",");
                }

                StringBuilder printString =
                        new StringBuilder("node : " + node.value + ", next : " + next.toString() +
                                " d : " + node.d + ", f : " + node.f);
                if (node.color != null) {
                    printString.append(", color : " + node.color.desc);
                }
                System.out.println(printString.toString());
            } else {
                System.out.println("node : " + node.value + ", no next");
            }
        }
    }


    public static void main(String[] args) {
        int count = 5;
        List directedGraph = generateDirectedGraph(count);
        System.out.println("=====================directedGraph====================");
        printGraph(directedGraph);

        dukstra(directedGraph, directedGraph.get(0));
        System.out.println("=====================after dukstra====================");
        printGraph(directedGraph);

    }
}

参考文档

《算法导论》

你可能感兴趣的:(心得体会,算法)