如果已添加项的值发生更改,如何管理堆(最小堆)

时间:2015-07-05 15:44:10

标签: java algorithm heap minimum-spanning-tree prims-algorithm

我是一名java开发人员(但是来自NON CS / IT教育背景)。我对算法感兴趣,目前我正在尝试实现Prim的计算MST算法。我告诉你这是为了让你知道背景,但我的问题与MST无关。

我已经实现了自己的MinHeap而不是使用Java.util.PriorityQueue(尽管即使我改变了我的代码并使用它,我也遇到了我前面提到过的同样的问题)。

我将项目添加到堆中,但是即使在堆中添加了项目之后,决定比较的项目的值也会发生变化。现在一旦值发生变化,堆就不会改变,因此在删除项目后,我会弹出错误的项目。

如何解决这种情况..

我正在粘贴我的代码以供参考。我在MinHeap中添加了Vertex类型的项目。每个Vertex都有一个“成本”和“成本”。关联,用于比较Vertex的两个对象。现在我在堆中添加Vertex的对象,并根据' cost'的当前值调整堆。但是一旦添加了Vertex的对象,那么如果它的成本发生了变化,那么我需要帮助来调整并将其反映在我的堆中。请在这方面帮助我,如果我的方向错误,请纠正我。

<div id="content">
        <script>
            function myFunction() {
                document.getElementById("contentp").innerHTML = leftside;
                var x = document.getElementById("leftside")
                x.style.display = "normal";
            }


        </script>
        <button id="buttonI" type="button" onclick="myFunction()">Show left side!</button>

        <p id="leftside" style="display: none">Left side</p>

        <p id="contentp"></p>

1 个答案:

答案 0 :(得分:0)

感谢朋友们为我的问题投入时间,但我认为我的实施中几乎没有错误,因为我得到了错误的回答。

  1. 我将顶点的状态更正为添加到MinHeap

  2. 我纠正了输出MST边缘的逻辑,我得到了正确答案....

  3. 最重要的是Karthik建议(非常感谢他)删除并重新添加费用为&#39;它在堆中时会发生变化。我实际上应用了冒泡方法,而不是删除并再次添加哪个工作!!

  4. 修改了以上3点后,我的代码正在运行,因为我希望它可以正常工作。

    另外@Karthik我没有两个方法可以在删除之前和之后但是我有一个用于添加项目时(在最后我使用方法heapifyAfterAdd()和其他方法当我删除第一个项目然后我使用heapifyAfterRemove())

    更正后请在下面找到我的代码。

    public class MSTRevisited {
    
        public static void main(String[] args) {
            Graph graph = new Graph(6);
            /*
             * graph.addNode('a'); graph.addNode('b'); graph.addNode('c');
             * graph.addNode('d'); graph.addNode('e'); graph.addNode('f');
             * graph.addEdege('a', 'b', 4); graph.addEdege('a', 'f', 2);
             * graph.addEdege('b', 'f', 3); graph.addEdege('b', 'c', 6);
             * graph.addEdege('c', 'f', 1); graph.addEdege('c', 'd', 3);
             * graph.addEdege('d', 'e', 2); graph.addEdege('f', 'e', 4);
             */
            graph.addNode('a');
            graph.addNode('b');
            graph.addNode('c');
            graph.addNode('d');
            graph.addEdege('a', 'b', 4);
            graph.addEdege('a', 'c', 2);
            graph.addEdege('b', 'c', 1);
            graph.addEdege('b', 'd', 2);
            graph.addEdege('c', 'd', 3);
            graph.applyPrimAlgo();
        }
    
        public static class Graph {
            private Vertex verticies[];
            private int maxSize;
            private int size;
            private HashMap map;
            private MinHeap Q;
    
            public Graph(int maxSize) {
                this.maxSize = maxSize;
                verticies = new Vertex[maxSize];
                map = new HashMap(maxSize);
                Q = new MinHeap(maxSize);
            }
    
            public void addNode(char data) {
                verticies[size] = new Vertex(data, size);
                map.put(data, size);
                size++;
            }
    
            public void addEdege(char sourceData, char destinationData, int weight) {
                int sourceIndex = map.get(sourceData);
                int destinationIndex = map.get(destinationData);
                verticies[sourceIndex].adj = new Neighbour(destinationIndex,
                        weight, verticies[sourceIndex].adj);
                verticies[destinationIndex].adj = new Neighbour(sourceIndex,
                        weight, verticies[destinationIndex].adj);
            }
    
            public void applyPrimAlgo() {
                // add all the keys to the Q
    
                PrimEdege pe = null;
                Vertex vertex = verticies[0];
                vertex.cost = 0;
                vertex.state = Vertex.IN_Q;
                Q.add(vertex);
                while (!Q.isEmpty()) {
                    Vertex poppedVertex = Q.remove();
                    poppedVertex.state = Vertex.VISITED;
                    Neighbour temp = poppedVertex.adj;
                    if (poppedVertex.parentIndex != -1) {
                        char source = verticies[poppedVertex.index].data;
                        char destination = verticies[poppedVertex.parentIndex].data;
                        pe = new PrimEdege(source, destination, pe);
                    }
                    while (temp != null) {
                        Vertex adjVertex = verticies[temp.index];
                        if (adjVertex.state != Vertex.VISITED) {
                            if (adjVertex.cost > temp.weight) {
                                adjVertex.cost = temp.weight;
                                adjVertex.parentIndex = poppedVertex.index;
                            }
                            if (adjVertex.state != Vertex.IN_Q) {
                                Q.add(adjVertex);
                                adjVertex.state = Vertex.IN_Q;
                            } else {
                                // bubble up this Node in the heap
                                Q.bubbleUp(adjVertex);
                            }
                        }
                        temp = temp.next;
                    }
                }
    
                PrimEdege temp = pe;
                while (temp != null) {
                    System.out.print("(" + temp.source + "," + temp.destination
                            + ") ");
                    temp = temp.next;
                }
                System.out.println();
            }
    
            private static class PrimEdege {
                public char source;
                public char destination;
                private PrimEdege next;
    
                public PrimEdege(char source, char destination, PrimEdege next) {
                    this.source = source;
                    this.destination = destination;
                    this.next = next;
                }
            }
    
            public static class MinHeap {
                private Vertex[] items;
                private int maxSize;
                private int size;
    
                public MinHeap(int maxSize) {
                    this.maxSize = maxSize;
                    items = new Vertex[maxSize];
                }
    
                public void bubbleUp(Vertex vertex) {
                    // @TODO
                    int i = 0;
                    for (; i < size; i++) {
                        if (items[i] == vertex) {
                            break;
                        }
                    }
                    if (i < size) {
                        int currentIndex = i;
                        Vertex currentItem = items[currentIndex];
                        int parentIndex = (currentIndex-1) / 2;
                        Vertex parentItem = items[parentIndex];
                        while (currentItem.compareTo(parentItem) == -1) {
                            swap(currentIndex, parentIndex);
                            currentIndex = parentIndex;
                            currentItem = items[currentIndex];
                            parentIndex = (currentIndex-1) / 2;
                            parentItem = items[parentIndex];
                        }
                    }
                }
    
                public void add(Vertex item) {
                    items[size] = item;
                    heapifyAfterAdd();
                    size++;
                }
    
                private void swap(int index1, int index2) {
                    Vertex temp = items[index1];
                    items[index1] = items[index2];
                    items[index2] = temp;
                }
    
                private void heapifyAfterAdd() {
                    int currIndex = size;
                    Vertex currItem = items[currIndex];
                    int parentIndex = (currIndex-1) / 2;
                    Vertex parentItem = items[parentIndex];
                    while (currItem.compareTo(parentItem) == -1) {
                        swap(parentIndex, currIndex);
                        currIndex = parentIndex;
                        currItem = items[currIndex];
                        parentIndex = (currIndex-1) / 2;
                        parentItem = items[parentIndex];
                    }
                }
    
                public Vertex remove() {
                    return remove(0);
                }
    
                public Vertex remove(Vertex vertex) {
                    int i = 0;
                    for (; i < size; i++) {
                        if (items[i] == vertex) {
                            break;
                        }
                    }
                    if (i < size) {
                        return remove(i);
                    }
                    return null;
    
                }
    
                private Vertex remove(int index) {
                    Vertex vertex = items[index];
                    swap(index, size - 1);
                    items[size - 1] = null;
                    size--;
                    heapifyAfterRemove(index);
                    return vertex;
                }
    
                private void heapifyAfterRemove(int index) {
                    int currIndex = index;
                    Vertex currItem = items[currIndex];
                    int childIndex;
                    Vertex childItem;
                    int left = 2 * currIndex + 1;
                    int right = 2 * currIndex + 2;
                    if (left > size - 1) {
                        return;
                    }
                    if (right > size - 1) {
                        childIndex = left;
                    } else if (items[left].compareTo(items[right]) == -1) {
                        childIndex = left;
                    } else {
                        childIndex = right;
                    }
                    childItem = items[childIndex];
    
                    while (childItem.compareTo(currItem) == -1) {
                        swap(currIndex, childIndex);
                        currIndex = childIndex;
                        currItem = items[currIndex];
                        left = 2 * currIndex + 1;
                        right = 2 * currIndex + 2;
                        if (left > size - 1) {
                            return;
                        }
                        if (right > size - 1) {
                            childIndex = left;
                        } else if (items[left].compareTo(items[right]) == -1) {
                            childIndex = left;
                        } else {
                            childIndex = right;
                        }
                        childItem = items[childIndex];
                    }
                }
    
                public boolean isEmpty() {
                    return size == 0;
                }
            }
    
            public static class HashMap {
                private MapNode[] map;
                private char[] keySet;
                private int maxSize;
                private int size;
    
                public HashMap(int maxSize) {
                    this.maxSize = maxSize;
                    map = new MapNode[maxSize];
                    keySet = new char[maxSize];
                }
    
                private static class MapNode {
                    char key;
                    int value;
                    MapNode next;
    
                    public MapNode(char key, int value, MapNode next) {
                        this.key = key;
                        this.value = value;
                        this.next = next;
                    }
                }
    
                public int hash(char key) {
                    return 31 * key;
                }
    
                public int getmapIndexOfkey(char key) {
                    return hash(key) % maxSize;
                }
    
                public void put(char key, int value) {
                    int index = getmapIndexOfkey(key);
                    map[index] = new MapNode(key, value, map[index]);
                    keySet[index] = key;
                    size++;
                }
    
                public int get(char key) {
                    int index = getmapIndexOfkey(key);
                    MapNode temp = map[index];
                    while (temp != null) {
                        if (temp.key == key) {
                            break;
                        }
                    }
                    if (temp != null) {
                        return temp.value;
                    } else {
                        return -1;
                    }
                }
    
                public char[] keyset() {
                    return keySet;
                }
            }
    
            public static class Vertex {
                public static final int NEW = 0;
                public static final int IN_Q = 1;
                public static final int VISITED = 2;
                private int state = NEW;
                private int cost = Integer.MAX_VALUE;
                private char data;
                private Neighbour adj;
                private int index;
                private int parentIndex = -1;
    
                public int compareTo(Vertex other) {
                    if (cost < other.cost) {
                        return -1;
                    }
                    if (cost > other.cost) {
                        return 1;
                    }
                    return 0;
                }
    
                public Vertex(char data, int index) {
                    this.data = data;
                    this.index = index;
                }
    
                public void addAdjacentVertex(Neighbour adj) {
                    this.adj = adj;
                }
    
                public void updateCost(int newCost, int parentIndex) {
                    this.cost = newCost;
                    this.parentIndex = parentIndex;
                }
            }
    
            public static class Neighbour {
                private Neighbour next;
                private int index;
                private int weight;
    
                public Neighbour(int index, int weight, Neighbour next) {
                    this.next = next;
                    this.index = index;
                    this.weight = weight;
                }
            }
        }
    }