Java 迪克斯特拉';用二进制堆实现s算法
我一直在尝试用二进制堆为我的算法类实现Dijkstra算法,目标是找到通过Dijkstra找到的最小生成树的长度。我以前使用过,但使用优先级队列。我发现我被堆管理绊倒了,如果有人能发现错误的话。主要方法如下: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) {
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;
}
}