适用范围:不存在任何一个环的各个边的权值累加起来为负值的图(可以存在边的权值为负数)

    1. import java.util.HashMap;
    2. import java.util.HashSet;
    3. import java.util.Map.Entry;
    4. // no negative weight
    5. public class Code06_Dijkstra {
    6. public static HashMap<Node, Integer> dijkstra1(Node head) {
    7. HashMap<Node, Integer> distanceMap = new HashMap<>();
    8. distanceMap.put(head, 0);
    9. HashSet<Node> selectedNodes = new HashSet<>();
    10. Node minNode = getMinDistanceAndUnselectedNode(distanceMap, selectedNodes);
    11. while (minNode != null) {
    12. int distance = distanceMap.get(minNode);
    13. for (Edge edge : minNode.edges) {
    14. Node toNode = edge.to;
    15. if (!distanceMap.containsKey(toNode)) {
    16. distanceMap.put(toNode, distance + edge.weight);
    17. }
    18. distanceMap.put(edge.to, Math.min(distanceMap.get(toNode), distance + edge.weight));
    19. }
    20. selectedNodes.add(minNode);
    21. minNode = getMinDistanceAndUnselectedNode(distanceMap, selectedNodes);
    22. }
    23. return distanceMap;
    24. }
    25. public static Node getMinDistanceAndUnselectedNode(HashMap<Node, Integer> distanceMap,
    26. HashSet<Node> touchedNodes) {
    27. Node minNode = null;
    28. int minDistance = Integer.MAX_VALUE;
    29. for (Entry<Node, Integer> entry : distanceMap.entrySet()) {
    30. Node node = entry.getKey();
    31. int distance = entry.getValue();
    32. if (!touchedNodes.contains(node) && distance < minDistance) {
    33. minNode = node;
    34. minDistance = distance;
    35. }
    36. }
    37. return minNode;
    38. }
    39. public static class NodeRecord {
    40. public Node node;
    41. public int distance;
    42. public NodeRecord(Node node, int distance) {
    43. this.node = node;
    44. this.distance = distance;
    45. }
    46. }
    47. public static class NodeHeap {
    48. private Node[] nodes;
    49. private HashMap<Node, Integer> heapIndexMap;
    50. private HashMap<Node, Integer> distanceMap;
    51. private int size;
    52. public NodeHeap(int size) {
    53. nodes = new Node[size];
    54. heapIndexMap = new HashMap<>();
    55. distanceMap = new HashMap<>();
    56. this.size = 0;
    57. }
    58. public boolean isEmpty() {
    59. return size == 0;
    60. }
    61. public void addOrUpdateOrIgnore(Node node, int distance) {
    62. if (inHeap(node)) {
    63. distanceMap.put(node, Math.min(distanceMap.get(node), distance));
    64. insertHeapify(node, heapIndexMap.get(node));
    65. }
    66. if (!isEntered(node)) {
    67. nodes[size] = node;
    68. heapIndexMap.put(node, size);
    69. distanceMap.put(node, distance);
    70. insertHeapify(node, size++);
    71. }
    72. }
    73. public NodeRecord pop() {
    74. NodeRecord nodeRecord = new NodeRecord(nodes[0], distanceMap.get(nodes[0]));
    75. swap(0, size - 1);
    76. heapIndexMap.put(nodes[size - 1], -1);
    77. distanceMap.remove(nodes[size - 1]);
    78. nodes[size - 1] = null;
    79. heapify(0, --size);
    80. return nodeRecord;
    81. }
    82. private void insertHeapify(Node node, int index) {
    83. while (distanceMap.get(nodes[index]) < distanceMap.get(nodes[(index - 1) / 2])) {
    84. swap(index, (index - 1) / 2);
    85. index = (index - 1) / 2;
    86. }
    87. }
    88. private void heapify(int index, int size) {
    89. int left = index * 2 + 1;
    90. while (left < size) {
    91. int smallest = left + 1 < size && distanceMap.get(nodes[left + 1]) < distanceMap.get(nodes[left])
    92. ? left + 1 : left;
    93. smallest = distanceMap.get(nodes[smallest]) < distanceMap.get(nodes[index]) ? smallest : index;
    94. if (smallest == index) {
    95. break;
    96. }
    97. swap(smallest, index);
    98. index = smallest;
    99. left = index * 2 + 1;
    100. }
    101. }
    102. private boolean isEntered(Node node) {
    103. return heapIndexMap.containsKey(node);
    104. }
    105. private boolean inHeap(Node node) {
    106. return isEntered(node) && heapIndexMap.get(node) != -1;
    107. }
    108. private void swap(int index1, int index2) {
    109. heapIndexMap.put(nodes[index1], index2);
    110. heapIndexMap.put(nodes[index2], index1);
    111. Node tmp = nodes[index1];
    112. nodes[index1] = nodes[index2];
    113. nodes[index2] = tmp;
    114. }
    115. }
    116. public static HashMap<Node, Integer> dijkstra2(Node head, int size) {
    117. NodeHeap nodeHeap = new NodeHeap(size);
    118. nodeHeap.addOrUpdateOrIgnore(head, 0);
    119. HashMap<Node, Integer> result = new HashMap<>();
    120. while (!nodeHeap.isEmpty()) {
    121. NodeRecord record = nodeHeap.pop();
    122. Node cur = record.node;
    123. int distance = record.distance;
    124. for (Edge edge : cur.edges) {
    125. nodeHeap.addOrUpdateOrIgnore(edge.to, edge.weight + distance);
    126. }
    127. result.put(cur, distance);
    128. }
    129. return result;
    130. }
    131. }