假设您想递归地实现一个二叉树的宽度优先搜索。你会怎么做?
是否可以只使用调用堆栈作为辅助存储?
假设您想递归地实现一个二叉树的宽度优先搜索。你会怎么做?
是否可以只使用调用堆栈作为辅助存储?
当前回答
下面使用Haskell对我来说似乎很自然。在树的各个层次上递归迭代(这里我将名字收集到一个大的有序字符串中,以显示树的路径):
data Node = Node {name :: String, children :: [Node]}
aTree = Node "r" [Node "c1" [Node "gc1" [Node "ggc1" []], Node "gc2" []] , Node "c2" [Node "gc3" []], Node "c3" [] ]
breadthFirstOrder x = levelRecurser [x]
where levelRecurser level = if length level == 0
then ""
else concat [name node ++ " " | node <- level] ++ levelRecurser (concat [children node | node <- level])
其他回答
我找不到一种完全递归的方法(没有任何辅助数据结构)。但是如果队列Q是通过引用传递的,那么你可以得到下面这个愚蠢的尾部递归函数:
BFS(Q)
{
if (|Q| > 0)
v <- Dequeue(Q)
Traverse(v)
foreach w in children(v)
Enqueue(Q, w)
BFS(Q)
}
Here is a JavaScript Implementation that fakes Breadth First Traversal with Depth First recursion. I'm storing the node values at each depth inside an array, inside of a hash. If a level already exists(we have a collision), so we just push to the array at that level. You could use an array instead of a JavaScript object as well since our levels are numeric and can serve as array indices. You can return nodes, values, convert to a Linked List, or whatever you want. I'm just returning values for the sake of simplicity.
BinarySearchTree.prototype.breadthFirstRec = function() {
var levels = {};
var traverse = function(current, depth) {
if (!current) return null;
if (!levels[depth]) levels[depth] = [current.value];
else levels[depth].push(current.value);
traverse(current.left, depth + 1);
traverse(current.right, depth + 1);
};
traverse(this.root, 0);
return levels;
};
var bst = new BinarySearchTree();
bst.add(20, 22, 8, 4, 12, 10, 14, 24);
console.log('Recursive Breadth First: ', bst.breadthFirstRec());
/*Recursive Breadth First:
{ '0': [ 20 ],
'1': [ 8, 22 ],
'2': [ 4, 12, 24 ],
'3': [ 10, 14 ] } */
下面是一个使用迭代方法的实际广度优先遍历的示例。
BinarySearchTree.prototype.breadthFirst = function() {
var result = '',
queue = [],
current = this.root;
if (!current) return null;
queue.push(current);
while (current = queue.shift()) {
result += current.value + ' ';
current.left && queue.push(current.left);
current.right && queue.push(current.right);
}
return result;
};
console.log('Breadth First: ', bst.breadthFirst());
//Breadth First: 20 8 22 4 12 24 10 14
我已经用c++做了一个程序,它是在联合和不联合图工作。
#include <queue>
#include "iostream"
#include "vector"
#include "queue"
using namespace std;
struct Edge {
int source,destination;
};
class Graph{
int V;
vector<vector<int>> adjList;
public:
Graph(vector<Edge> edges,int V){
this->V = V;
adjList.resize(V);
for(auto i : edges){
adjList[i.source].push_back(i.destination);
// adjList[i.destination].push_back(i.source);
}
}
void BFSRecursivelyJoinandDisjointtGraphUtil(vector<bool> &discovered, queue<int> &q);
void BFSRecursivelyJointandDisjointGraph(int s);
void printGraph();
};
void Graph :: printGraph()
{
for (int i = 0; i < this->adjList.size(); i++)
{
cout << i << " -- ";
for (int v : this->adjList[i])
cout <<"->"<< v << " ";
cout << endl;
}
}
void Graph ::BFSRecursivelyJoinandDisjointtGraphUtil(vector<bool> &discovered, queue<int> &q) {
if (q.empty())
return;
int v = q.front();
q.pop();
cout << v <<" ";
for (int u : this->adjList[v])
{
if (!discovered[u])
{
discovered[u] = true;
q.push(u);
}
}
BFSRecursivelyJoinandDisjointtGraphUtil(discovered, q);
}
void Graph ::BFSRecursivelyJointandDisjointGraph(int s) {
vector<bool> discovered(V, false);
queue<int> q;
for (int i = s; i < V; i++) {
if (discovered[i] == false)
{
discovered[i] = true;
q.push(i);
BFSRecursivelyJoinandDisjointtGraphUtil(discovered, q);
}
}
}
int main()
{
vector<Edge> edges =
{
{0, 1}, {0, 2}, {1, 2}, {2, 0}, {2,3},{3,3}
};
int V = 4;
Graph graph(edges, V);
// graph.printGraph();
graph.BFSRecursivelyJointandDisjointGraph(2);
cout << "\n";
edges = {
{0,4},{1,2},{1,3},{1,4},{2,3},{3,4}
};
Graph graph2(edges,5);
graph2.BFSRecursivelyJointandDisjointGraph(0);
return 0;
}
设v为起始顶点
设G是问题中的图
下面是不使用队列的伪代码
Initially label v as visited as you start from v
BFS(G,v)
for all adjacent vertices w of v in G:
if vertex w is not visited:
label w as visited
for all adjacent vertices w of v in G:
recursively call BFS(G,w)
二进制(或n-ary)树的BFS可以在没有队列的情况下递归完成,如下所示(在Java中):
public class BreathFirst {
static class Node {
Node(int value) {
this(value, 0);
}
Node(int value, int nChildren) {
this.value = value;
this.children = new Node[nChildren];
}
int value;
Node[] children;
}
static void breathFirst(Node root, Consumer<? super Node> printer) {
boolean keepGoing = true;
for (int level = 0; keepGoing; level++) {
keepGoing = breathFirst(root, printer, level);
}
}
static boolean breathFirst(Node node, Consumer<? super Node> printer, int depth) {
if (depth < 0 || node == null) return false;
if (depth == 0) {
printer.accept(node);
return true;
}
boolean any = false;
for (final Node child : node.children) {
any |= breathFirst(child, printer, depth - 1);
}
return any;
}
}
按升序遍历打印数字1-12的示例:
public static void main(String... args) {
// 1
// / | \
// 2 3 4
// / | | \
// 5 6 7 8
// / | | \
// 9 10 11 12
Node root = new Node(1, 3);
root.children[0] = new Node(2, 2);
root.children[1] = new Node(3);
root.children[2] = new Node(4, 2);
root.children[0].children[0] = new Node(5, 2);
root.children[0].children[1] = new Node(6);
root.children[2].children[0] = new Node(7, 2);
root.children[2].children[1] = new Node(8);
root.children[0].children[0].children[0] = new Node(9);
root.children[0].children[0].children[1] = new Node(10);
root.children[2].children[0].children[0] = new Node(11);
root.children[2].children[0].children[1] = new Node(12);
breathFirst(root, n -> System.out.println(n.value));
}