Dijkstra relies on Heap

41 阅读1分钟
public class Heap {
    GNode[] heapNodes;
    int size;
    HashMap<GNode,Integer> nodeIndex; //记录节点在数组中的索引
    HashMap<GNode,Integer> distances;//记录每个节点的最短距离

    public class Record{
        GNode node;
        int distance;

        public Record(GNode node, int distance) {
            this.node = node;
            this.distance = distance;
        }
    }
    public Heap(int size) {
       heapNodes = new GNode[size];
       this.size = size;
    }
    public boolean isEmpty(){
        return size==0;
    }

    public boolean isEntered(GNode node){
        return nodeIndex.containsKey(node);
    }

    public boolean isInHeap(GNode node){
        return isEntered(node)&&nodeIndex.get(node)!=-1;
    }

    public void addOrUpdateOrIgnore(GNode node , int distance){
        if(!isEntered(node)){
            heapNodes[size] = node;
            nodeIndex.put(node,size);
            distances.put(node,distance);
            heapInsert(node,size);
            size++;
        }
        if(isInHeap(node)){
            distances.put(node,Math.min(distances.get(node),distance));
            heapInsert(node,nodeIndex.get(node));
        }

    }

    public Record pop(){
        Record record = new Record(heapNodes[0], distances.get(heapNodes[0]));
        swap(0,size-1);
        nodeIndex.put(heapNodes[size-1],-1);
        distances.remove(heapNodes[size-1]);
        heapify(heapNodes[0],--size);
        return record;
    }


    public  void heapInsert(GNode node){
        int index = size;
        this.heapNodes[index] = node;

    }

    public void heapInsert(GNode node,int index){
        while (distances.get(node)<distances.get(heapNodes[(index-1)/2])){
            swap(index,(index-1)/2);
            index = (index-1)/2;
        }
    }


    public void heapify(GNode node,int size){
        int index = nodeIndex.get(node);
        int left = index*2+1;
        int right = index*2+2;
        while (left<size){
            int smallest = right<size && distances.get(heapNodes[left])<distances.get(heapNodes[right])?left:right;
            smallest = distances.get(heapNodes[index])<distances.get(heapNodes[smallest])?index:smallest;
            if(smallest==index) break;
            swap(smallest,index);
            index = smallest;
            left = index*2+1;
            right = index*2+2;
        }
    }


    public void swap(int x,int y){
        nodeIndex.put(heapNodes[x], y);
        nodeIndex.put(heapNodes[y],x);
        GNode help = heapNodes[x];
        heapNodes[x] = heapNodes[y];
        heapNodes[y] = help;
    }


    public static HashMap<GNode,Integer> dijkstra(GNode head,int size){
        Heap heap = new Heap(size);
        HashMap<GNode, Integer> res = new HashMap<>();
        heap.addOrUpdateOrIgnore(head,0);
        while (!heap.isEmpty()){
            Record record = heap.pop();
            res.put(record.node,record.distance);
            for (Edge edge : record.node.edges) {
                heap.addOrUpdateOrIgnore(edge.to,edge.weight+record.distance);
            }
        }
        return res;
    }





}