我有一张如下图:
root : {
nodeType : "root",
children: [
"A",
"B",
"C"
]
}
nodes : [
"A": {
nodeType : "node",
children: [
"D",
"E"
]
},
"B": {
nodeType : "node",
children: [
"D",
"F"
]
},
"C": {
nodeType : "leaf"
},
"D": {
nodeType : "node",
children: [
"G"
]
},
"E": {
nodeType : "leaf"
},
"F": {
nodeType : "leaf"
},
"G": {
nodeType : "leaf"
},
]
我需要编写一个javascript函数,给定一个起点(例如“B”),它将以最接近起始点优先级的方式遍历图形。例如对于B,它会得到孩子D,F,然后是根,然后是兄弟姐妹B,C,然后是granchild G,然后是B和C的孩子,依此类推。
即使只是让算法没问题
PS:我知道我可以在那里使用dijkstra,但我真的不知道如何答案 0 :(得分:1)
您可以使用Breadth-first search实施,例如here。如果树中的边缘具有与之相关的权重,则需要Dijkstra的算法。
由于您未将父项保留在节点对象中,因此需要添加预处理步骤以将父字段添加到所有节点。这是必需的,以便在B
开始时您知道访问根。这可以使用简单的遍历来完成。
广度优先搜索会将您需要访问的节点保留在队列中。新节点将添加到队列的末尾。该算法从队列的前面选择要访问的新节点。
但要小心,因为如果允许复制节点,队列可能会变得非常大。
答案 1 :(得分:0)
感谢关于使用广度优先算法的cyon建议,我想出了这个 (基于http://java.dzone.com/articles/algorithm-week-graph-breadth):
var graph = {
A : [B, C],
B : [A, D],
C : [A, D],
D : [A, C ,E],
E : [B, F],
F : [E]
};
function init (visited, graph)
{
for (var key in graph) {
var vertex = graph[key];
visited[key] = false;
}
}
function breadthFirst (graph, start, visited)
{
// Create an empty queue
var queue = [];
// Initially enqueue only the starting vertex
queue.push(start);
//Set the starting vertex to visited
visited[start] = true;
//Add it to the result
result.push( start );
//While there is still remaining vertexes in queue
while (queue.length > 0) {
//Remove first vertex from queue and save it in "t"
var currentVertexID = queue.shift();
//For each key in graph at "t"
var currentVertex = graph[currentVertexID];
for (var key in currentVertex) {
var target = currentVertex[key];
//If it has not been visited yet
if (!visited[target]) {
//Mark it as visited
visited[target] = true;
//Add it to queue
queue.push(target);
//Save it in result
result.push(target);
//console.log(result);
}
}
}
}
var result = [];
var visited = [];
init(visited, graph);
breadthFirst(graph, 2, visited);
console.log(result);
因为我有一个分离的根,并且我的图中只有父子关系(因为我从树中迁移),所以我必须在使用广度之前建立一个完整的关系矩阵(以便它可以查找父母)。
我发布它是因为它可以用于预处理,以便首先在树上使用广度
generateNodesAdjacencyMatrix : function(){
var adjacencyMatrix = {};
function recursiveFindNestedAndSaveLinks(parentKey, childrenKeys){
//Add the links to parent pointing to his children
if(!_.isArray(adjacencyMatrix[parentKey])){
adjacencyMatrix[parentKey] = [];
}
adjacencyMatrix[parentKey] = adjacencyMatrix[parentKey].concat(childrenKeys);
//For each children
_.each(childrenKeys, function (childKey){
//Add a link to parent
if(!_.isArray(adjacencyMatrix[childKey])){
adjacencyMatrix[childKey] = [];
}
adjacencyMatrix[childKey].push(parentKey);
//If it has children as well, do recursive on him
var child = childs[childKey];
if(!_.isUndefined(child) && !_.isUndefined(child.children)){
recursiveFindNestedAndSaveLinks(childKey, child.children);
}
}, this);
}
recursiveFindNestedAndSaveLinks('root', root.children);
return adjacencyMatrix;
},