Java 迪克斯特拉';用二进制堆实现s算法

Java 迪克斯特拉';用二进制堆实现s算法,java,heap,dijkstra,minimum-spanning-tree,min-heap,Java,Heap,Dijkstra,Minimum Spanning Tree,Min Heap,我一直在尝试用二进制堆为我的算法类实现Dijkstra算法,目标是找到通过Dijkstra找到的最小生成树的长度。我以前使用过,但使用优先级队列。我发现我被堆管理绊倒了,如果有人能发现错误的话。主要方法如下: import java.io.File; import java.util.regex.*; import java.util.ArrayList; public class main { public static void main(String[] args) {

我一直在尝试用二进制堆为我的算法类实现Dijkstra算法,目标是找到通过Dijkstra找到的最小生成树的长度。我以前使用过,但使用优先级队列。我发现我被堆管理绊倒了,如果有人能发现错误的话。主要方法如下:

import java.io.File;
import java.util.regex.*;
import java.util.ArrayList;
public class main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        try {
            File input = new File("filepath\1000.txt");
            Scanner scanner = new Scanner(input);

            //Regex patterns used to find input size, nodes, and edges
            String size = "n=([0-9]*)";
            String node = "^[0-9]+";
            String edge = "^[\\s]+([0-9]+)[\\s]+([0-9]+)";

            Pattern sizePattern = Pattern.compile(size);
            Pattern edgePattern = Pattern.compile(edge);
            Pattern nodePattern = Pattern.compile(node);


            //Loop to fill nodeList
            ArrayList <Integer> finalDistances = new ArrayList<>();
            MinHeap list = null;
            Node currentNode = null;
            Edge currentEdge = null;
            while(scanner.hasNextLine()) {

                String line = scanner.nextLine();
                Matcher match1 = sizePattern.matcher(line);
                Matcher match2 = nodePattern.matcher(line);
                Matcher match3 = edgePattern.matcher(line);
                //catches size
                if(match1.find()) {
                    int numberOfNodes = Integer.parseInt(match1.group(1));
                    //Holds all the nodes to process with Dijkstra's Algo
                    list = new MinHeap(numberOfNodes);
                }
                //catches node
                if (match2.find()) {
                    if (!list.contains(Integer.parseInt(line))) {
                        currentNode = new Node(Integer.parseInt(line));
                        currentNode.seen = false;
                        currentNode.distance = Integer.MAX_VALUE;
                        list.insert(currentNode);
                    }
                    else {
                        currentNode = list.getNode(Integer.parseInt(line));
                    }
                }
                //catches edge
                if(match3.find()) {
                    if (!list.contains(Integer.parseInt(match3.group(1)))) {
                        Node temp = new Node(Integer.parseInt(match3.group(1)));
                        temp.seen = false;
                        temp.distance = Integer.MAX_VALUE;
                        list.insert(temp);
                        currentEdge = new Edge(Integer.parseInt(match3.group(1)), Integer.parseInt(match3.group(2)));
                        currentNode.add(currentEdge);
                    } else {
                        currentEdge = new Edge(Integer.parseInt(match3.group(1)), Integer.parseInt(match3.group(2)));
                        currentNode.add(currentEdge);
                    }
                }
            }
            Node source = list.getNode(0);
            source.distance=0;
            list.updateNode(source);
            int treeLength = 0;
            while(!list.isEmpty()) {
                currentNode = list.extractMin();
                currentNode.seen = true;
                ArrayList<Edge> edgeList = currentNode.edges;
                for (int i = 0; i < edgeList.size(); i++) {
                    currentEdge = edgeList.get(i);
                    if (list.contains(currentEdge.end)) {
                        int calcDist = currentNode.distance + currentEdge.weight;
                        if (calcDist < list.getNode(currentEdge.end).distance) {
                            list.decreaseKey(list.getNode(currentEdge.end), calcDist);
                        }
                    }
                }
                System.out.println(currentNode.toString() + "with distance" +currentNode.distance);
                finalDistances.add(currentNode.distance);
            }
            for (int j = 0; j < finalDistances.size(); j++) treeLength+= finalDistances.get(j);
            System.out.println("Tree length is: "+treeLength);
        }

        //fail safe
        catch (Exception ex){
            System.out.println("Shit broke!");
        }
    }

}
第一行是节点和边的数量。线上的数字本身就是一个节点,后面的数字是带权重的边。我的节点类只有一个int值、边的arraylist和与源的距离。我的Edge类有一个int值和int权重

import java.util.ArrayList;

public class Node {
    int value;
    ArrayList<Edge> edges;
    boolean seen;
    int distance;
    public Node(int value) {
        edges = new ArrayList<>();
        this.value = value;
        seen = false;
    }
    public void add (Edge edge) {
        edges.add(edge);
    }
    @Override
    //debugging use
    public String toString() {
        String listOfEdges= "";
        //for (int i = 0; i < edges.size(); i++) {
        //  listOfEdges = listOfEdges + " ," + Integer.toString(edges.get(i).end);
        //}
        return "Node: "+Integer.toString(value); //+" Edges: "+listOfEdges;
    }
}
似乎在运行算法的某个点之后,某些顶点保持无穷大,而另一些顶点保持负无穷大。我使用两个数组:第一个是存储节点的堆,第二个是存储堆中节点的索引。全套课程如下:

    private int capacity;
    private int currentSize;
    private Node[] heap;
    private int[] locations;
    //private HashMap<Integer, Integer> locations = new HashMap<>();

    public MinHeap(int capacity) {
        this.capacity = capacity;
        heap = new Node[capacity];
        locations = new int[capacity];
        //heap[0] = new Node(-1);
        //heap[0].distance = Integer.MIN_VALUE;
        currentSize = 0;
    }
    private int getParent(int index) {
        return (index-1)/2;
    }
    private int getLeftChild(int index) {
        return index*2+1;
    }
    private int getRightChild(int index) {
        return index*2+2;
    }
    private void swap(int a, int b) {
        Node temp = heap[a];
        heap[a] = heap[b];
        heap[b] = temp;
        //maybe bug


    }
    Node extractMin() {
        Node min = heap[0];
        Node last = heap[currentSize-1];
        swap (0,currentSize-1);
        locations[last.value] = 0;
        locations[min.value] = -1;
        currentSize--;
        heapifyDown(0);
        System.out.println("heap size: "+currentSize);
        return min;
    }
    void heapifyDown(int index) {
        int currentIndex = index;
        int leftIndex = getLeftChild(currentIndex);
        int rightIndex = getRightChild(currentIndex);
        if (leftIndex < currentSize && heap[currentIndex].distance > heap[leftIndex].distance) {
            currentIndex = leftIndex;
        }
        if (rightIndex < currentSize && heap[currentIndex].distance > heap[rightIndex].distance) {
            currentIndex = rightIndex;
        }
        if (currentIndex != index) {
            Node newTop = heap[currentIndex];
            Node oldTop = heap[index];

            locations[newTop.value] = index;
            locations[oldTop.value] = currentIndex;
            swap(index,currentIndex);
            heapifyDown(currentIndex);
        }
    }
    void heapifyUp(int index) {
        int parentIndex = getParent(index);
        int currentIndex = index;
        Node currentNode = heap[currentIndex];
        Node parentNode = heap[parentIndex];
        while (currentIndex > 0 && heap[parentIndex].distance > heap[currentIndex].distance) {
            System.out.println("Swapped: "+heap[getParent(currentIndex)].toString()+" That has a distance of: "+heap[getParent(currentIndex)].distance+ " With: "+heap[currentIndex]+" Which has a distance of: "+heap[currentIndex].distance);
            swap(parentIndex,currentIndex);
            locations[currentNode.value] = parentIndex;
            locations[parentNode.value] = currentIndex;
            currentIndex = parentIndex;
            parentIndex = getParent(parentIndex);

            System.out.println("min: "+heap[0].toString());
        }
    }
    public void decreaseKey(Node node, int distance) {
        int location = locations[node.value];
        heap[location].distance = distance;
        heapifyUp(location);
    }
    public void insert(Node node) {
        //currentSize++;
        int index = currentSize;
        heap[currentSize] = node;
        locations[node.value] = currentSize;
        currentSize++;
        heapifyUp(index);
    }
    public boolean contains(int node) {
        return locations[node] != 0 && locations[node] != -1;
    }
    public boolean isEmpty() {
        return currentSize==0;
    }
    public Node getNode(Node node) {
        return heap[locations[node.value]];
    }
    public Node getNode(int nodeValue) {
        return heap[locations[nodeValue]];
    }
    public void updateNode(Node node) {
        heap[locations[node.value]] = node;
    }
    public void print() {
        for (int i = 0; i < currentSize; i++) {
            System.out.println(heap[i].toString());
        }
    }
    public Node peek() {
        return heap[0];
    }
    public int size() {
        return currentSize;
    }
}
private-int-capacity;
私有int-currentSize;
私有节点[]堆;
私人场所;
//私有HashMap位置=新HashMap();
公共MinHeap(整数容量){
这个。容量=容量;
heap=新节点[容量];
位置=新的整数[容量];
//堆[0]=新节点(-1);
//堆[0]。距离=整数。最小值;
currentSize=0;
}
私有int getParent(int索引){
收益率(指数-1)/2;
}
私有int getLeftChild(int索引){
收益率指数*2+1;
}
私有整数getRightChild(整数索引){
收益率指数*2+2;
}
私有无效交换(内部a、内部b){
节点温度=堆[a];
堆[a]=堆[b];
堆[b]=温度;
//也许是虫子
}
节点extractMin(){
节点最小值=堆[0];
最后一个节点=堆[currentSize-1];
交换(0,currentSize-1);
位置[last.value]=0;
位置[最小值]=-1;
当前大小--;
heapifyDown(0);
System.out.println(“堆大小:+currentSize”);
返回最小值;
}
void heapifyDown(整数索引){
int currentIndex=索引;
int leftIndex=getLeftChild(currentIndex);
int rightIndex=getRightChild(currentIndex);
if(leftIndexheap[leftIndex].distance){
currentIndex=leftIndex;
}
if(rightIndexheap[rightIndex].distance){
currentIndex=rightIndex;
}
if(currentIndex!=索引){
节点newTop=堆[currentIndex];
节点oldTop=堆[索引];
位置[newTop.value]=索引;
位置[oldTop.value]=当前索引;
掉期(指数,当前指数);
heapifyDown(当前指数);
}
}
无效堆集(整数索引){
int parentIndex=getParent(index);
int currentIndex=索引;
节点currentNode=堆[currentIndex];
节点parentNode=堆[parentIndex];
while(currentIndex>0&&heap[parentIndex].distance>heap[currentIndex].distance){
System.out.println(“交换:“+heap[getParent(currentIndex)].toString()+”,其距离为:“+heap[getParent(currentIndex)].distance+”,其中“+heap[currentIndex]+”的距离为:“+heap[currentIndex].distance+”;
交换(父索引、当前索引);
位置[currentNode.value]=父索引;
位置[parentNode.value]=当前索引;
currentIndex=父索引;
parentIndex=getParent(parentIndex);
System.out.println(“min:+heap[0].toString());
}
}
public void decreaseKey(节点,整数距离){
int location=位置[node.value];
堆[位置]。距离=距离;
heapifyUp(位置);
}
公共空白插入(节点){
//currentSize++;
int index=当前大小;
堆[currentSize]=节点;
位置[节点值]=当前大小;
currentSize++;
heapifyUp(指数);
}
公共布尔包含(int节点){
返回位置[节点]!=0和位置[节点]!=-1;
}
公共布尔值为空(){
返回currentSize==0;
}
公共节点getNode(节点节点){
返回堆[locations[node.value]];
}
公共节点getNode(int nodeValue){
返回堆[locations[nodeValue];
}
公共void updateNode(节点){
堆[locations[node.value]]=节点;
}
公开作废印刷品(){
对于(int i=0;i

非常感谢您的反馈。

您能解释一下输入文件吗?例如,前3个数字的含义是什么?0 25 2440是第一个节点,节点25以244的权重连接到0。您是否将代码和输入文件上传到github以进行克隆和调试?当然可以:请解释输入文件?例如,前3个数字的含义是什么?0 25 2440是第一个节点,节点25以244的权重连接到0。您是否将代码和输入文件上传到github上以进行克隆和调试?请确定:
public class Edge {
    int end;
    int weight;
    public Edge(int end, int weight) {
        this.end = end;
        this.weight = weight;
    }
    @Override
    //debugging use
    public String toString() {
        return "Edge: "+end+" Weight: "+weight;
    }
}
    private int capacity;
    private int currentSize;
    private Node[] heap;
    private int[] locations;
    //private HashMap<Integer, Integer> locations = new HashMap<>();

    public MinHeap(int capacity) {
        this.capacity = capacity;
        heap = new Node[capacity];
        locations = new int[capacity];
        //heap[0] = new Node(-1);
        //heap[0].distance = Integer.MIN_VALUE;
        currentSize = 0;
    }
    private int getParent(int index) {
        return (index-1)/2;
    }
    private int getLeftChild(int index) {
        return index*2+1;
    }
    private int getRightChild(int index) {
        return index*2+2;
    }
    private void swap(int a, int b) {
        Node temp = heap[a];
        heap[a] = heap[b];
        heap[b] = temp;
        //maybe bug


    }
    Node extractMin() {
        Node min = heap[0];
        Node last = heap[currentSize-1];
        swap (0,currentSize-1);
        locations[last.value] = 0;
        locations[min.value] = -1;
        currentSize--;
        heapifyDown(0);
        System.out.println("heap size: "+currentSize);
        return min;
    }
    void heapifyDown(int index) {
        int currentIndex = index;
        int leftIndex = getLeftChild(currentIndex);
        int rightIndex = getRightChild(currentIndex);
        if (leftIndex < currentSize && heap[currentIndex].distance > heap[leftIndex].distance) {
            currentIndex = leftIndex;
        }
        if (rightIndex < currentSize && heap[currentIndex].distance > heap[rightIndex].distance) {
            currentIndex = rightIndex;
        }
        if (currentIndex != index) {
            Node newTop = heap[currentIndex];
            Node oldTop = heap[index];

            locations[newTop.value] = index;
            locations[oldTop.value] = currentIndex;
            swap(index,currentIndex);
            heapifyDown(currentIndex);
        }
    }
    void heapifyUp(int index) {
        int parentIndex = getParent(index);
        int currentIndex = index;
        Node currentNode = heap[currentIndex];
        Node parentNode = heap[parentIndex];
        while (currentIndex > 0 && heap[parentIndex].distance > heap[currentIndex].distance) {
            System.out.println("Swapped: "+heap[getParent(currentIndex)].toString()+" That has a distance of: "+heap[getParent(currentIndex)].distance+ " With: "+heap[currentIndex]+" Which has a distance of: "+heap[currentIndex].distance);
            swap(parentIndex,currentIndex);
            locations[currentNode.value] = parentIndex;
            locations[parentNode.value] = currentIndex;
            currentIndex = parentIndex;
            parentIndex = getParent(parentIndex);

            System.out.println("min: "+heap[0].toString());
        }
    }
    public void decreaseKey(Node node, int distance) {
        int location = locations[node.value];
        heap[location].distance = distance;
        heapifyUp(location);
    }
    public void insert(Node node) {
        //currentSize++;
        int index = currentSize;
        heap[currentSize] = node;
        locations[node.value] = currentSize;
        currentSize++;
        heapifyUp(index);
    }
    public boolean contains(int node) {
        return locations[node] != 0 && locations[node] != -1;
    }
    public boolean isEmpty() {
        return currentSize==0;
    }
    public Node getNode(Node node) {
        return heap[locations[node.value]];
    }
    public Node getNode(int nodeValue) {
        return heap[locations[nodeValue]];
    }
    public void updateNode(Node node) {
        heap[locations[node.value]] = node;
    }
    public void print() {
        for (int i = 0; i < currentSize; i++) {
            System.out.println(heap[i].toString());
        }
    }
    public Node peek() {
        return heap[0];
    }
    public int size() {
        return currentSize;
    }
}