需要用java实现一个程序来求出根据所给出的起始节点和目标节点(在约束条件下,必须经过某些点,必须不经过某些点)来求出两个结点的最短路径。
我有思路,但是转化为代码,还有些困难,在算法方面想请教一下大虾们。
首先:实现本例的算法是否应选择Dsijkstra算法,有没有更优的算法?
第二:必须经过某些点的约束条件,我是这样想的,先求出起始节点到第一个约束节点的最短路径,再继续求出第一个约束点到第二个点的最短路径...一直到最后一个约束点到目标节点的最短路径。但是觉得这样效率不是很高。而且好像我试了好多次Dsijkstra算法实现的是一个结点到其他所有节点的最短路径,我只需要特定的两个节点的路径该怎么做呢?谢谢。
第三:在必须不经过某些点的约束条件,我认为,先把要求不能经过的那些点删除掉,然后再求出最短路径。
现在请求大虾支支招,要是有个带注释的源码参考参考那就更好了,谢谢。
我有思路,但是转化为代码,还有些困难,在算法方面想请教一下大虾们。
首先:实现本例的算法是否应选择Dsijkstra算法,有没有更优的算法?
第二:必须经过某些点的约束条件,我是这样想的,先求出起始节点到第一个约束节点的最短路径,再继续求出第一个约束点到第二个点的最短路径...一直到最后一个约束点到目标节点的最短路径。但是觉得这样效率不是很高。而且好像我试了好多次Dsijkstra算法实现的是一个结点到其他所有节点的最短路径,我只需要特定的两个节点的路径该怎么做呢?谢谢。
第三:在必须不经过某些点的约束条件,我认为,先把要求不能经过的那些点删除掉,然后再求出最短路径。
现在请求大虾支支招,要是有个带注释的源码参考参考那就更好了,谢谢。
上面有楼说不太清楚GIS哦,我字面解释下,GIS就是 地理信息系统 。GIS在国内发展的比较晚,国外有做的很好的了,GoogleEath就是GIS的应用之一.
Dsijkstra 使用于求出最短路径
而对于求最短路径,贪婪算法的Dsijkstra则应该是最佳的了,,
所以,我觉得LZ的方法应该还OK的。。
但有一个方法,,LZ可以试下,
就是利用JAVA的线程,,来优化你的效率
参考了一些资料和网上的代码。现在实现了从一个点到其他点的路径输出,先在程序中初始化了所需数据,然后进行算法。后来想实现从键盘输入任意的节点和权值,但是改过代码出现错,调试定位了错误的代码,但还没解决。先给出修改前的代码:
第一个类:package cn.gis;
import java.util.ArrayList;
public class Dijkstra {
static ArrayList<Side> map = null;
static ArrayList<Integer> redAgg = null;
static ArrayList<Integer> blueAgg = null;
static Side[] parents = null;
public static void main(String[] args) {
// 初始化顶点集
int[] nodes = { 0, 1, 3, 2, 4, 5,6 };
// 初始化有向权重图
map = new ArrayList<Side>();
map.add(new Side(0, 1, 10));
map.add(new Side(0, 3, 30));
map.add(new Side(0, 4, 100));
map.add(new Side(1, 2, 50));
map.add(new Side(2, 4, 10));
map.add(new Side(3, 2, 20));
map.add(new Side(3, 4, 60));
map.add(new Side(4, 5, 50));
map.add(new Side(3, 5, 60));
map.add(new Side(5, 6, 10));
map.add(new Side(3, 6, 80));
// 初始化已知最短路径的顶点集,即红点集,只加入顶点0
redAgg = new ArrayList<Integer>();
redAgg.add(nodes[0]);//***************************************写成入口点;
// 初始化未知最短路径的顶点集,即蓝点集
blueAgg = new ArrayList<Integer>();
for (int i = 1; i < nodes.length; i++)
blueAgg.add(nodes[i]);
// 初始化每个顶点在最短路径中的父结点,及它们之间的权重,权重-1表示无连通
parents = new Side[nodes.length];
parents[0] = new Side(-1, nodes[0], 0);//************************************************************
for (int i = 0; i < blueAgg.size(); i++) {
int n = blueAgg.get(i);
parents[i + 1] = new Side(nodes[0], n, getWeight(nodes[0], n));//
}
// 找从蓝点集中找出权重最小的那个顶点,并把它加入到红点集中
while (blueAgg.size() > 0) {
MinShortPath msp = getMinSideNode();
if(msp.getWeight()==-1)
msp.outputPath(nodes[0]);
else
msp.outputPath();
int node = msp.getLastNode();
redAgg.add(node);
// 如果因为加入了新的顶点,而导致蓝点集中的顶点的最短路径减小,则要重要设置
setWeight(node);
}
}
/**
* 得到一个节点的父节点
*
* @param parents
* @param node
* @return
*/
public static int getParent(Side[] parents, int node) {
if (parents != null) {
for (Side nd : parents) {
if (nd.getNode() == node) {
return nd.getPreNode();
}
}
}
return -1;
}
/**
* 重新设置蓝点集中剩余节点的最短路径长度
*
* @param preNode
* @param map
* @param blueAgg
*/
public static void setWeight(int preNode) {
if (map != null && parents != null && blueAgg != null) {
for (int node : blueAgg) {
MinShortPath msp=getMinPath(node);
int w1 = msp.getWeight();
if (w1 == -1)
continue;
for (Side n : parents) {
if (n.getNode() == node) {
if (n.getWeight() == -1 || n.getWeight() > w1) {
n.setWeight(w1);
n.setPreNode(preNode);//重新设置顶点的父顶点
break;
}
}
}
}
}
}
/**
* 得到两点节点之间的权重
*
* @param map
* @param preNode
* @param node
* @return
*/
public static int getWeight(int preNode, int node) {
if (map != null) {
for (Side s : map) {
if (s.getPreNode() == preNode && s.getNode() == node)
return s.getWeight();
}
}
return -1;
}
/**
* 从蓝点集合中找出路径最小的那个节点
*
* @param map
* @param blueAgg
* @return
*/
public static MinShortPath getMinSideNode() {
MinShortPath minMsp = null;
if (blueAgg.size() > 0) {
int index = 0;
for (int j = 0; j < blueAgg.size(); j++) {
MinShortPath msp = getMinPath(blueAgg.get(j));
if (minMsp == null || msp.getWeight()!=-1 && msp.getWeight() < minMsp.getWeight()) {
minMsp = msp;
index = j;
}
}
blueAgg.remove(index);
}
return minMsp;
}
/**
* 得到某一节点的最短路径(实际上可能有多条,现在只考虑一条)
* @param node
* @return
*/
public static MinShortPath getMinPath(int node) {
MinShortPath msp = new MinShortPath(node);
if (parents != null && redAgg != null) {
for (int i = 0; i < redAgg.size(); i++) {
MinShortPath tempMsp = new MinShortPath(node);
int parent = redAgg.get(i);
int curNode = node;
while (parent > -1) {
int weight = getWeight(parent, curNode);
if (weight > -1) {
tempMsp.addNode(parent);
tempMsp.addWeight(weight);
curNode = parent;
parent = getParent(parents, parent);
} else
break;
}
if (msp.getWeight() == -1 || tempMsp.getWeight()!=-1 && msp.getWeight() > tempMsp.getWeight())
msp = tempMsp;
}
}
return msp;
}
}
第二个类:package cn.gis;/**
* @author Administrator
*
*/
public class Side { private int preNode;
private int node;
private int weight;
/**
*
* @param preNode:前向节点
* @param node:::后向节点
* @param weight:权值
*/
public Side(int preNode, int node, int weight) {
this.preNode = preNode;
this.node = node;
this.weight = weight; } public int getPreNode() {
return preNode;
} public void setPreNode(int preNode) {
this.preNode = preNode;
} public int getNode() {
return node;
} public void setNode(int node) {
this.node = node;
} public int getWeight() {
return weight;
} public void setWeight(int weight) {
this.weight = weight;
}
}第三个类:package cn.gis;import java.util.ArrayList;/**
* @author Administrator
*
*/
public class MinShortPath {
/**
* nodeList:最短路径集
* weight:最短路径
*/
private ArrayList<Integer> nodeList;
private int weight; public MinShortPath(int node) {
nodeList = new ArrayList<Integer>();
nodeList.add(node);
weight = -1;
} public ArrayList<Integer> getNodeList() {
return nodeList;
} public void setNodeList(ArrayList<Integer> nodeList) {
this.nodeList = nodeList;
} public void addNode(int node) {
if (nodeList == null)
nodeList = new ArrayList<Integer>();
nodeList.add(0, node);
} public int getLastNode() {
int size = nodeList.size();
return nodeList.get(size - 1);
} public int getWeight() {
return weight;
} public void setWeight(int weight) {
this.weight = weight;
} public void outputPath() {
outputPath(-1);
} public void outputPath(int srcNode) {
String result = "[";
if (srcNode != -1)
nodeList.add(srcNode);
for (int i = 0; i < nodeList.size(); i++) {
result += "" + nodeList.get(i);
if (i < nodeList.size() - 1)
result += "->";
}
result += "]:" + weight;
System.out.println(result);
} public void addWeight(int w) {
if (weight == -1)
weight = w;
else {
weight += w;
}
}
}
package cn.gis;import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;public class Dijkstra { static ArrayList<Side> map = null; static ArrayList<Integer> redAgg = null; static ArrayList<Integer> blueAgg = null; static Side[] parents = null;
static int first; static int second; static int weight1; /**
*
* @param args
*/
public static void main(String[] args) {
// 初始化顶点集
Scanner inSanner = new Scanner(System.in);
System.out.println("Input the number of the nodes:");// 输入结点个数
int j = inSanner.nextInt();
int[] nodes = new int[j];
System.out.println("\ninput the nodes:");// 输入节点;
// int[] nodes = { 0, 1, 3, 2, 4, 5,6 };
for (int i = 0; i < nodes.length; i++) {
nodes[i] = inSanner.nextInt();
} // 初始化有向权重图
/*
* map = new ArrayList<Side>(); map.add(new Side(0, 1, 10));
* map.add(new Side(0, 3, 30)); map.add(new Side(0, 4, 100));
* map.add(new Side(1, 2, 50)); map.add(new Side(2, 4, 10)); map.add(new
* Side(3, 2, 20)); map.add(new Side(3, 4, 60)); map.add(new Side(4, 5,
* 50)); map.add(new Side(3, 5, 60)); map.add(new Side(5, 6, 10));
* map.add(new Side(3, 6, 80));
*/
System.out.println("input the starting point:");// 输入起始节点;;
/**
*
* 排序nodes数组中的元素,原因是int k = Arrays.binarySearch(nodes,
* p)执行前必须排序,否则返回值错误,在api中有说;
*/
Arrays.sort(nodes);
int p = inSanner.nextInt();
int k = Arrays.binarySearch(nodes, p);// 寻找起始节点在nodes数组中的位置;
/**
* 交换nodes[0]与起始节点,使得nodes[0]中存的总是起始节点;
*/
int temp = nodes[k];
nodes[k] = nodes[0];
nodes[0] = temp;
System.out.println("Input the number of the edgs");
int edges = inSanner.nextInt(); for (int i = 0; i < edges; i++) {
System.out.println("Input the first node:");
first = inSanner.nextInt();
System.out.println("Input the sceond node:");
second = inSanner.nextInt();
System.out.println("Input the weight1:");
weight1 = inSanner.nextInt();
/**
* 调试发现下面这句出问题,但不知错哪里?###########################################################################
*/
map.add(new Side(first, second, weight1));
} // 初始化已知最短路径的顶点集,即红点集,只加入顶点0
redAgg = new ArrayList<Integer>();
redAgg.add(nodes[0]); // 初始化未知最短路径的顶点集,即蓝点集
blueAgg = new ArrayList<Integer>();
for (int i = 1; i < nodes.length; i++)
blueAgg.add(nodes[i]); // 初始化每个顶点在最短路径中的父结点,及它们之间的权重,权重-1表示无连通
parents = new Side[nodes.length];
parents[0] = new Side(-1, nodes[0], 0);
for (int i = 0; i < blueAgg.size(); i++) {
int n = blueAgg.get(i);
parents[i + 1] = new Side(nodes[0], n, getWeight(nodes[0], n));//
} // 找从蓝点集中找出权重最小的那个顶点,并把它加入到红点集中
while (blueAgg.size() > 0) {
MinShortPath msp = getMinSideNode();
if (msp.getWeight() == -1)
msp.outputPath(nodes[0]);
else
msp.outputPath(); int node = msp.getLastNode();
redAgg.add(node);
// 如果因为加入了新的顶点,而导致蓝点集中的顶点的最短路径减小,则要重要设置
setWeight(node);
} } /**
* 得到一个节点的父节点
*
* @param parents
* @param node
* @return
*/
public static int getParent(Side[] parents, int node) {
if (parents != null) {
for (Side nd : parents) {
if (nd.getNode() == node) {
return nd.getPreNode();
}
}
}
return -1;
} /**
* 重新设置蓝点集中剩余节点的最短路径长度
*
* @param preNode
* @param map
* @param blueAgg
*/
public static void setWeight(int preNode) {
if (map != null && parents != null && blueAgg != null) {
for (int node : blueAgg) {
MinShortPath msp = getMinPath(node);
int w1 = msp.getWeight();
if (w1 == -1)
continue;
for (Side n : parents) {
if (n.getNode() == node) {
if (n.getWeight() == -1 || n.getWeight() > w1) {
n.setWeight(w1);
n.setPreNode(preNode);// 重新设置顶点的父顶点
break;
}
}
}
}
}
} /**
* 得到两点节点之间的权重
*
* @param map
* @param preNode
* @param node
* @return
*/
public static int getWeight(int preNode, int node) {
if (map != null) {
for (Side s : map) {
if (s.getPreNode() == preNode && s.getNode() == node)
return s.getWeight();
}
}
return -1;
} /**
* 从蓝点集合中找出路径最小的那个节点
*
* @param map
* @param blueAgg
* @return
*/
public static MinShortPath getMinSideNode() {
MinShortPath minMsp = null;
if (blueAgg.size() > 0) {
int index = 0;
for (int j = 0; j < blueAgg.size(); j++) {
MinShortPath msp = getMinPath(blueAgg.get(j));
if (minMsp == null || msp.getWeight() != -1
&& msp.getWeight() < minMsp.getWeight()) {
minMsp = msp;
index = j;
}
}
blueAgg.remove(index); }
return minMsp;
} /**
* 得到某一节点的最短路径(实际上可能有多条,现在只考虑一条)
*
* @param node
* @return
*/
public static MinShortPath getMinPath(int node) {
MinShortPath msp = new MinShortPath(node);
if (parents != null && redAgg != null) {
for (int i = 0; i < redAgg.size(); i++) {
MinShortPath tempMsp = new MinShortPath(node);
int parent = redAgg.get(i);
int curNode = node;
while (parent > -1) {
int weight = getWeight(parent, curNode);
if (weight > -1) {
tempMsp.addNode(parent);
tempMsp.addWeight(weight);
curNode = parent;
parent = getParent(parents, parent);
} else
break;
} if (msp.getWeight() == -1 || tempMsp.getWeight() != -1
&& msp.getWeight() > tempMsp.getWeight())
msp = tempMsp;
}
} return msp;
}}
今天明天要去兼职,晚上回来才能做了...大家帮忙看看啊~~
而且先在离还好远啊。先在实现的是没有两种约束情况的简单代码。还要继续研究算法!!!GABADE!!!:)
大家帮忙看看偶的程序,还有400分,搞定这个问题,全部散掉,Thankyou~~~~~~~~~~~
:)
应该会有收获的。谢谢拉