[英]DFS and BFS on a Trie in Java
I have a Trie which looks like this: 我有一个Trie,看起来像这样:
Root
/ \
b c
/ / \
a a h
/ / / \
t t a e
/ /
t e
/ \
r s
/ \
s e
I'm trying to implement a DFS, and BFS. 我正在尝试实现DFS和BFS。 The BFS works fine, using a queue:
BFS使用队列可以正常工作:
public String breadthFirstSearch() {
//FIFO Queue to hold nodes
Queue<TrieNode> nodeQueue = new LinkedList<TrieNode>();
//Output array
ArrayList<Integer> out = new ArrayList<Integer>();
//Start from root
nodeQueue.add(this.root);
//While queue is not empty
while (nodeQueue.isEmpty() == false) {
//Remove and return first queue element
TrieNode current = nodeQueue.poll();
//For node's children
for (int i=0; i<26; i++) {
//If not null
if (current.offspring[i] != null) {
//Add node to queue
nodeQueue.add(current.offspring[i]);
//Add node's index (char) to output array
out.add(i);
}
}
}
//Return result
return indexArrayToString(out);
}
Output: 输出:
b,c,a,a,h,t,t,a,e,t,e,r,s,s,e
Now, I'm trying to implement the DFS (same algorithm, but using a stack) however the output isn't correct: 现在,我正在尝试实现DFS(相同的算法,但是使用堆栈),但是输出不正确:
public String depthFirstSearch() {
//LIFO Stack to hold nodes
Stack<TrieNode> nodeStack = new Stack<TrieNode>();
//Output array
ArrayList<Integer> out = new ArrayList<Integer>();
//Start from root
nodeStack.push(this.root);
//While stack is not empty
while (nodeStack.isEmpty() == false) {
//Remove and return first stack element
TrieNode current = nodeStack.pop();
//For node's children
for (int i=0; i<26; i++) {
//If not null
if (current.offspring[i] != null) {
//Add node to stack
nodeStack.push(current.offspring[i]);
//Add node's index (char) to output array
out.add(i);
}
}
}
//Return result
return indexArrayToString(out);
}
This gives: 这给出:
b,c,a,h,a,e,e,r,s,e,s,t,t,a,t
When I want it to give: 当我想给它:
t,a,b,t,a,t,a,s,r,e,s,e,e,h,c
I can't figure out what's going wrong. 我不知道怎么了。
I have implemented the map-based approach that I mentioned in my comment, ie without modifying the original TrieNode
class: 我已经实现了我在评论中提到的基于地图的方法,即
TrieNode
原始TrieNode
类:
public String depthFirstSearch() {
//LIFO Stack to hold nodes
Stack<TrieNode> nodeStack = new Stack<TrieNode>();
//keep set of processed nodes (processed node is a node whose children were already pushed into the stack)
Set<TrieNode> processed = new HashSet<TrieNode>();
//boolean for checking presence of at least one child
boolean hasChild=false;
//map for trienode->char
Map<TrieNode, Integer> map = new HashMap<TrieNode, Integer>();
//Output array
List<Integer> out = new ArrayList<Integer>();
//Start from root
nodeStack.push(this.root);
//While stack is not empty
while (nodeStack.isEmpty() == false) {
//Peek at the top of stack
TrieNode topNode = nodeStack.peek();
//if it is not processed AND if it has at least one child, push its children into the stack from right to left. otherwise pop the stack
hasChild=false;
if(!processed.contains(topNode))
{
for (int i=25; i>=0; i--)
{
//If not null
if (topNode.offspring[i] != null)
{
//Add node to stack and map
nodeStack.push(topNode.offspring[i]);
map.put(topNode.offspring[i], i);
hasChild=true;
}
}//end for
processed.add(topNode); //after discovering all children, put the top into set of processed nodes
if(!hasChild) //top node has no children so we pop it and put into the list
{
TrieNode popNode = nodeStack.pop();
if(map.get(popNode)!=null)
out.add(map.get(popNode));
}
}
else //the node has been processed already so we pop it and put into the list
{
TrieNode popNode = nodeStack.pop();
if(map.get(popNode)!=null)
out.add(map.get(popNode));
}
}//end while stack not empty
//Return result
return indexArrayToString(out);
}//end method
To get the output that you wanted, you need to think about when a node is added to the out list. 要获得所需的输出,您需要考虑何时将节点添加到“出站”列表中。 In your code, you start at the root and iterate throught it's offspring in a kind-of recursive style while adding them directly to your output.
在您的代码中,您从根开始,以一种递归样式迭代它的后代,同时将它们直接添加到输出中。 Therefore your output has more in common with a BFS than a DFS.
因此,与DFS相比,您的输出与BFS有更多的共同点。
Although there are very simple DFS implementations like 虽然有非常简单的DFS实现,例如
DFS(TrieNode current){
for(int i = 26; i >= 0; i--){
if(current.offspring[i] != null){
DFS(current.offspring[i]);
}
}
out.add(current);
}
if you want to keep most of your code for any reason, you could create a second stack that keeps track for you where in the tree you are and when which node is supposed to be added to the output. 如果您出于某种原因想要保留大部分代码,则可以创建第二个堆栈,该堆栈可以跟踪您在树中的位置以及何时将哪个节点添加到输出中。 Explicitly, this could look something like this:
明确地,这可能看起来像这样:
public String depthFirstSearch() {
//LIFO Stack to hold nodes
Stack<TrieNode> nodeStack = new Stack<TrieNode>();
//Second stack that keeps track of visited nodes
Stack<TrieNode> helpStack = new Stack<TrieNode>();
//Output array
ArrayList<Integer> out = new ArrayList<Integer>();
//Start from root
nodeStack.push(this.root);
//While stack is not empty
while (nodeStack.isEmpty() == false) {
//Remove and return first stack element
TrieNode current = nodeStack.peek();
//We visited this node -> push it on the second stack
helpStack.push(current);
//We want to add nodes to the output once we reach a leaf node, so we need a
//helper variable
boolean hasOffspring = false;
//For node's children - since we want to go the left path first we push the
//children in right-to-left fashion on the stack. Can vary with implementation.
for (int i=25; i>=0; i--) {
//If not null
if (current.offspring[i] != null) {
//Add node to stack
nodeStack.push(current.offspring[i]);
//not a leaf
hasOffspring = true;
}
}
//if we reached a leaf node add it and all previous nodes to the output until
//we reach a fork where we didn't already fo the other path
if(!hasOffspring){
TrieNode node1 = nodeStack.peek();
TrieNode node2 = helpStack.peek();
while(node1.equals(node2)){
nodeStack.pop();
helpStack.pop();
//Add node's index (char) to output array
out.add(node1);
//we are back at the root and completed the DFS
if(nodeStack.isEmpty() || helpStack.isEmpty()) break;
node1 = nodeStack.peek();
node2 = nodeStack.peek();
}
}
}
//Return result
return indexArrayToString(out);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.