- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
以下代码使用邻接表结构执行广度优先搜索算法。我很好奇。如果我要实现这个邻接矩阵,我必须对代码进行哪些类型的编辑?
我知道我必须创建一个网格(n x n 矩阵),但我的数据文件是否必须与该网格结构相对应?或者我会只填充一个空的网格结构并实现我的文本文件已有的关卡设计吗?
我觉得在实际代码中实现这一点是我最困惑的地方,关于下面的代码(使用堆栈)。我从来没有用矩阵做过 bfs,只做过邻接表。
这里是:
import java.io.*;
import java.util.*;
public class MainM {
private Graph graph;
/**
* Constructor.
*/
public MainM(Graph g) {
graph = g;
}
/**
* 1 - Create a stack to store all the vertices of our path on.
* 2 - First push the 'end' vertex on our stack.
* 3 - Now loop from the highest level back to the first level and
* a. loop through each level and
* b. check each vertex in that level if it's connected to the
* vertex on the top of our stack, if we find a match, push that
* match on the stack and break out of the loop.
* 4 - Now we only need to reverse the collection (stack) before returning
* the path in the "correct" order (from start to finish).
*
* Here's an example ASCII drawing of backtracking from the end vertex "n"
* to the starting vertex "g". The arrows, <-, denote the path that was
* found.
*
* level: 0 1 2 3 4 5 6 7 8
* ---------------------------------------------------------
* g <-+ IV e I a +- III <- o <- VI <- n
* +- V <-+ f +- II <-+ b | p
* +- c <-+ | d |
* j +- h <-+
* q
* r
*/
private List<String> backTrack(List<List<String>> container, String end) {
Stack<String> path = new Stack<String>(); // 1
path.push(end); // 2
for(int i = container.size()-1; i >= 0; i--) { // 3
List<String> level = container.get(i);
String last = path.peek();
for(String s : level) { // a
if(graph.isConnectedTo(last, s)) { // b
path.push(s);
break;
}
}
}
Collections.reverse(path); // 4
return path;
}
/**
* 1 - Get the level from the 'container' which was added last.
* 2 - Create a new level to store (possible) unexplored verices in.
* 3 - Loop through each of the vertices from the last added level, and
* a. get the neighboring vertices connected to each vertex,
* b. loop through each connecting vertex and if the connecting vertex
* has not yet been visited,
* c. only then add it to the newly created level-list and mark it as
* visited in our set.
* 4 - We don't need to search any further if we stumble upon the 'end'
* vertex. In that case, just "return" from this method.
* 5 - Only make the recursive call if we have found vertices which have
* not been explored yet.
*/
private void bfs(List<List<String>> container,
String end, Set<String> visited) {
List<String> lastLevel = container.get(container.size()-1); // 1
List<String> newLevel = new ArrayList<String>(); // 2
for(String vertex : lastLevel) { // 3
List<String> edges = graph.getEdges(vertex); // a
for(String edge : edges) { // b
if(!visited.contains(edge)) { // c
visited.add(edge);
newLevel.add(edge);
}
if(edge.equals(end)) return; // 4
}
}
if(newLevel.size() > 0) { // 5
container.add(newLevel);
bfs(container, end, visited);
}
}
/**
* 1 - Create an empty 'container' to store all the levels from the
* 'start'-vertex in. A level is also a list with one or more vertices.
* 2 - The first level only holds the 'start' vertex, which is added first,
* this is the 'init' list.
* 3 - The 'start' vertex is also stored in a Set which keeps track of all
* the vertices we have encountered so that we don't traverse vertices
* twice (or more).
* 4 - Once we initialized the steps 1-3, we can call the actual BFS-
* algorithm.
* 5 - Once the BFS-algorithm is done, we call the backTrack(...) method
* to find the shortest path between 'end' and 'start' between the
* explored levels of the graph.
*/
public List<String> getShortestPath(String start, String end) {
List<List<String>> container = new ArrayList<List<String>>(); // 1
List<String> init = new ArrayList<String>(); // 2
init.add(start);
container.add(init);
Set<String> visited = new HashSet<String>(); // 3
visited.add(start);
bfs(container, end, visited); // 4
return backTrack(container, end); // 5
}
/**
* Main method:
* 1 - Create a Graph.
* 2 - Get a shortest path between two vertices.
* 3 - Print the shortest path.
*/
public static void main(String[] args) throws FileNotFoundException {
Graph graph = new Graph("data.txt"); // 1
MainM bfsAlgorithm = new MainM(graph);
Scanner sc = new Scanner(System.in);
System.out.println("Please enter starting city: ");
String shortPath = sc.nextLine();
System.out.println("Please enter ending city: ");
String shortPath2 = sc.nextLine();
List<String> shortestPath = bfsAlgorithm.getShortestPath(shortPath, shortPath2);
//List<String> shortestPath =
// bfsAlgorithm.getShortestPath("g", "n"); // 2
for(int i = 0; i < shortestPath.size(); i++) {
System.out.print(shortestPath.get(i)); // 3
System.out.print(i < shortestPath.size()-1 ? " --> " : " ");
}
}
}
这是图形类:
import java.io.*;
import java.util.*;
public class Graph {
private Map<String, List<String>> adjacencyList;
/**
* Instatiates the 'adjacencyList' and then parse the data file.
*/
public Graph(String fileName) throws FileNotFoundException {
adjacencyList = new HashMap<String, List<String>>();
parseDataFile(fileName);
}
/**
* This is an undirected graph, so we connect 'vertexA' to 'vertexB'
* and the other way around.
*/
public void addConnection(String vertexA, String vertexB) {
connect(vertexA, vertexB);
connect(vertexB, vertexA);
}
/**
* A private helper-method to connect 'vertexA' to 'vertexB'.
* If 'vertexA' alreay exists in our 'adjacencyList', get it's
* edges-list and add 'vertexB' to it. If it doesn't exist,
* create a new ArrayList, add 'vertexB' to it and put it all
* in our 'adjacencyList'.
*/
private void connect(String vertexA, String vertexB) {
List<String> edges;
if(adjacencyList.containsKey(vertexA)) {
edges = adjacencyList.get(vertexA);
edges.add(vertexB);
} else {
edges = new ArrayList<String>();
edges.add(vertexB);
this.adjacencyList.put(vertexA, edges);
}
}
/**
* Returns true iff 'vertexA' poits to to 'vertexB'.
* Note that since this is an undirected graph, we do not
* need to check the other way around, the case if 'vertexB'
* is points to 'vertexA'.
*/
public boolean isConnectedTo(String vertexA, String vertexB) {
List<String> edges = getEdges(vertexA);
return edges.contains(vertexB);
}
/**
* Returns all the edges of a certain vertex, or throws an
* exception if the vertex doesn't exist in this graph.
*/
public List<String> getEdges(String vertex) {
List<String> edges = adjacencyList.get(vertex);
if(edges == null) {
throw new RuntimeException(vertex+" not present in the graph.");
}
return edges;
}
/**
* Reads a text file with the graph-data. The text file contains
* N-blocks of lines where each block starts with the city followed
* by N-lines of text representing the city2s and ending with an
* empty line.
*/
private void parseDataFile(String fileName) throws FileNotFoundException {
Scanner file = new Scanner(new File(fileName));
while(file.hasNextLine()) {
String city = file.nextLine().trim();
while(file.hasNextLine()) {
String city2 = file.nextLine().trim();
if(city2.length() == 0) break;
addConnection(city, city2);
}
}
}
/**
* A Sting representation if this Graph.
*/
public String toString() {
StringBuilder builder = new StringBuilder();
Iterator<String> vertices = adjacencyList.keySet().iterator();
while(vertices.hasNext()) {
String vertex = vertices.next();
List<String> edges = adjacencyList.get(vertex);
builder.append(vertex);
builder.append(" --> ");
builder.append(edges);
builder.append('\n');
}
return builder.toString();
}
/**
* main
*/
public static void main(String[] args) {
try {
Graph graph = new Graph("data.txt");
System.out.println(graph);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
这是一个文本测试文件:
Seattle
a
b
01
d
e
II
c
h
q
r
III
h
o
p
IV
e
f
g
V
c
g
j
VI
k
m
n
o
最佳答案
这是面向对象编程的有趣部分:-)
如果您为 Graph
创建一个通用接口(interface)并提供 2 个实现(例如,AdjListGraph
和 AdjMxGraph
),您没有更改 MainM
类中除声明之外的任何内容。只需在新的基于邻接矩阵的实现中实现常用函数(addConnection()
、isConnectedTo()
等)即可。
我不会考虑更改我的输入数据结构。顺便说一句,有很多选项可以使用,最常见的是 Pajek format -- 乍一看可能有点奇怪。
此外,还有许多图形库(GraphStream、JUNG 等),请查看它们。只需浏览这些代码库,您就可以学到很多东西。
希望有所帮助;]
关于java - java中的邻接矩阵,广度优先搜索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22036647/
假设我有两个矩阵,每个矩阵有两列和不同的行数。我想检查并查看一个矩阵的哪些对在另一个矩阵中。如果这些是一维的,我通常只会做 a %in% x得到我的结果。 match似乎只适用于向量。 > a
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 9 个月前。 Improv
我只处理过 DirectX 矩阵 我读过一些文章,说不能将 DirectX 矩阵数学库用于 openGL 矩阵。 但我也读过,如果你的数学是一致的,你可以获得类似的结果。那只会让我更加困惑。 任何人都
我编写了一个C++代码来解决线性系统A.x = b,其中A是一个对称矩阵,方法是首先使用LAPACK(E)对角矩阵A = V.D.V^T(因为以后需要特征值),然后求解x = A^-1.b = V^T
我遇到了问题。我想创建二维数组 rows=3 cols=2我的代码如下 int **ptr; int row=3; int col=2; ptr=new int *[col]; for (int i=
我有一个 3d mxnxt 矩阵,我希望能够提取 t 2d nxm 矩阵。在我的例子中,我有一个 1024x1024x10 矩阵,我想要 10 张图像显示给我。 这不是 reshape ,我每次只需要
我在 MATLAB 中有一个 3d 矩阵 (n-by-m-by-t) 表示一段时间内网格中的 n-by-m 测量值.我想要一个二维矩阵,其中空间信息消失了,只剩下 n*m 随着时间 t 的测量值(即:
作为一个简化的示例,我有一个 3D numpy 矩阵,如下所示: a = np.array([[[1,2], [4,np.nan], [7,
作为一个简化的示例,我有一个 3D numpy 矩阵,如下所示: a = np.array([[[1,2], [4,np.nan], [7,
使用 eigen2 , 并给定一个矩阵 A a_0_0, a_0_1, a_0_2, ... a_1_0, a_1_0, a_1_2, ... ... 和一个矩阵B: b_0_0, b_0_1, b_
我想知道如何获得下面的布局。 在中型和大型设备上,我希望有 2 行和 2 列的布局(2 x 2 矩阵)。 在小型(和超小型)设备上或调整为小型设备时,我想要一个 4 行和 1 列的矩阵。 我将通过 a
有什么方法可以向量化以下内容: for i = 1:6 te = k(:,:,:,i).*(c(i)); end 我正在尝试将 4D 矩阵 k 乘以向量 c,方法是将其
如何从填充有 1 和 0 的矩阵中抽取 n 个随机点的样本? a=rep(0:1,5) b=rep(0,10) c=rep(1,10) dataset=matrix(cbind(a,b,c),nrow
我正在尝试创建一个包含 X 个 X 的矩阵。以下代码生成从左上角到右下角的 X 对 Angular 线,而不是从右上角到左下角的 X 对 Angular 线。我不确定从哪里开始。是否应该使用新变量创建
我想在 python 中创建一个每行三列的矩阵,并能够通过任何一行对它们进行索引。矩阵中的每个值都是唯一的。 据我所知,我可以设置如下矩阵: matrix = [["username", "name"
我有点迷茫 我创建了一个名为 person 的类,它具有 age 和 name 属性(以及 get set 方法)。然后在另一个类中,我想创建一个 persons 数组,其中每个人都有不同的年龄和姓名
我有 n 个类,它们要么堆叠,要么不堆叠。所有这些类都扩展了同一个类 (CellObject)。我知道更多类将添加到此列表中,我想创建一种易于在一个地方操纵“可堆叠性”的方法。 我正在考虑创建一个矩阵
我有一个包含 x 个字符串名称及其关联 ID 的文件。本质上是两列数据。 我想要的是一个格式为 x x x 的相关样式表(将相关数据同时作为 x 轴和 y 轴),但我想要 fuzzywuzzy 库的函
机器学习与传统编程的一个重要区别在于机器学习比传统编程涉及了更多的数学知识。不过,随着机器学习的飞速发展,各种框架应运而生,在数据分析等应用中使用机器学习时,使用现成的库和框架成为常态,似乎越来越不需
当我在 julia 中输入这个错误跳转但我不知道为什么,它应该工作。/ julia> A = [1 2 3 4; 5 6 7 8; 1 2 3 4; 5 6 7 8] 4×4 Array{Int64,
我是一名优秀的程序员,十分优秀!