Я ищу алгоритм поиска нерекурсивной глубины первого недвоичного дерева. Любая помощь очень ценится.
Нерекурсивный алгоритм первого поиска глубины
Ответ 1
ДФС:
list nodes_to_visit = {root};
while( nodes_to_visit isn't empty ) {
currentnode = nodes_to_visit.take_first();
nodes_to_visit.prepend( currentnode.children );
//do something
}
BFS:
list nodes_to_visit = {root};
while( nodes_to_visit isn't empty ) {
currentnode = nodes_to_visit.take_first();
nodes_to_visit.append( currentnode.children );
//do something
}
Симметрия двух довольно крутая.
Обновление: Как указано, take_first()
удаляет и возвращает первый элемент в списке.
Ответ 2
Вы бы использовали stack, который содержит узлы, которые еще не были посещены:
stack.push(root)
while !stack.isEmpty() do
node = stack.pop()
for each node.childNodes do
stack.push(stack)
endfor
// …
endwhile
Ответ 3
Если у вас есть указатели на родительские узлы, вы можете сделать это без дополнительной памяти.
def dfs(root):
node = root
while True:
visit(node)
if node.first_child:
node = node.first_child # walk down
else:
while not node.next_sibling:
if node is root:
return
node = node.parent # walk up ...
node = node.next_sibling # ... and right
Обратите внимание, что если дочерние узлы хранятся в виде массива, а не через указатели для сиблинга, следующий брат может быть найден как:
def next_sibling(node):
try:
i = node.parent.child_nodes.index(node)
return node.parent.child_nodes[i+1]
except (IndexError, AttributeError):
return None
Ответ 4
Использование стека для отслеживания ваших узлов
Stack<Node> s;
s.prepend(tree.head);
while(!s.empty) {
Node n = s.poll_front // gets first node
// do something with q?
for each child of n: s.prepend(child)
}
Ответ 5
В то время как "использование стека" может работать как ответ на надуманный вопрос интервью, на самом деле он просто делает явно то, что рекурсивная программа делает за кулисами.
Рекурсия использует встроенный стек программ. Когда вы вызываете функцию, она подталкивает аргументы к функции в стек, и когда функция возвращает ее, она выдает стек программы.
Ответ 6
Реализация ES6, основанная на biziclops отличный ответ:
root = {
text: "root",
children: [{
text: "c1",
children: [{
text: "c11"
}, {
text: "c12"
}]
}, {
text: "c2",
children: [{
text: "c21"
}, {
text: "c22"
}]
}, ]
}
console.log("DFS:")
DFS(root, node => node.children, node => console.log(node.text));
console.log("BFS:")
BFS(root, node => node.children, node => console.log(node.text));
function BFS(root, getChildren, visit) {
let nodesToVisit = [root];
while (nodesToVisit.length > 0) {
const currentNode = nodesToVisit.shift();
nodesToVisit = [
...nodesToVisit,
...(getChildren(currentNode) || []),
];
visit(currentNode);
}
}
function DFS(root, getChildren, visit) {
let nodesToVisit = [root];
while (nodesToVisit.length > 0) {
const currentNode = nodesToVisit.shift();
nodesToVisit = [
...(getChildren(currentNode) || []),
...nodesToVisit,
];
visit(currentNode);
}
}
Ответ 7
PreOrderTraversal is same as DFS in binary tree. You can do the same recursion
taking care of Stack as below.
public void IterativePreOrder(Tree root)
{
if (root == null)
return;
Stack s<Tree> = new Stack<Tree>();
s.Push(root);
while (s.Count != 0)
{
Tree b = s.Pop();
Console.Write(b.Data + " ");
if (b.Right != null)
s.Push(b.Right);
if (b.Left != null)
s.Push(b.Left);
}
}
Общая логика: нажмите node (начиная с корня) в значения Stack, Pop() it и Print(). Затем, если у него есть дети (слева и справа), вставьте их в стек - сначала нажмите "Вперёд", чтобы вы сначала посетили левого ребенка (после посещения самой node). Когда стек пуст(), вы будете посещать все узлы в предварительном порядке.
Ответ 8
Предположим, вы хотите выполнить уведомление, когда каждый node в графике посещается. Простая рекурсивная реализация:
void DFSRecursive(Node n, Set<Node> visited) {
visited.add(n);
for (Node x : neighbors_of(n)) { // iterate over all neighbors
if (!visited.contains(x)) {
DFSRecursive(x, visited);
}
}
OnVisit(n); // callback to say node is finally visited, after all its non-visited neighbors
}
Хорошо, теперь вам нужна реализация на основе стека, потому что ваш пример не работает. Сложные графики могут, например, привести к тому, что это приведет к удалению стека вашей программы, и вам нужно реализовать нерекурсивную версию. Самая большая проблема заключается в том, чтобы знать, когда выдать уведомление.
Следующий псевдокод работает (сочетание Java и С++ для удобочитаемости):
void DFS(Node root) {
Set<Node> visited;
Set<Node> toNotify; // nodes we want to notify
Stack<Node> stack;
stack.add(root);
toNotify.add(root); // we won't pop nodes from this until DFS is done
while (!stack.empty()) {
Node current = stack.pop();
visited.add(current);
for (Node x : neighbors_of(current)) {
if (!visited.contains(x)) {
stack.add(x);
toNotify.add(x);
}
}
}
// Now issue notifications. toNotifyStack might contain duplicates (will never
// happen in a tree but easily happens in a graph)
Set<Node> notified;
while (!toNotify.empty()) {
Node n = toNotify.pop();
if (!toNotify.contains(n)) {
OnVisit(n); // issue callback
toNotify.add(n);
}
}
Он выглядит сложным, но дополнительная логика, необходимая для выдачи уведомлений, существует, потому что вам нужно уведомить в обратном порядке посещения - DFS начинается с корня, но уведомляет об этом последний, в отличие от BFS, который очень прост в реализации.
Для ударов, попробуйте следующий график: узлами являются s, t, v и w. направленные ребра: s- > t, s- > v, t- > w, v- > w и v- > t. Запустите собственную реализацию DFS и порядок, в котором следует посещать узлы, должен быть: w, t, v, s Неуклюжая реализация DFS может сначала уведомить t, а это означает ошибку. Рекурсивная реализация DFS всегда будет достигать последней.
Ответ 9
Нерекурсивная DFS с использованием генераторов ES6
class Node {
constructor(name, childNodes) {
this.name = name;
this.childNodes = childNodes;
this.visited = false;
}
}
function *dfs(s) {
let stack = [];
stack.push(s);
stackLoop: while (stack.length) {
let u = stack[stack.length - 1]; // peek
if (!u.visited) {
u.visited = true; // grey - visited
yield u;
}
for (let v of u.childNodes) {
if (!v.visited) {
stack.push(v);
continue stackLoop;
}
}
stack.pop(); // black - all reachable descendants were processed
}
}
Он отклоняется от типичной нерекурсивной DFS, чтобы легко обнаружить, когда обработаны все доступные потомки данных node и для поддержания текущего пути в списке/стеке.
Ответ 10
http://www.youtube.com/watch?v=zLZhSSXAwxI
Просто посмотрел это видео и вышел с реализацией. Мне легко понять. Пожалуйста, критикуйте это.
visited_node={root}
stack.push(root)
while(!stack.empty){
unvisited_node = get_unvisited_adj_nodes(stack.top());
If (unvisited_node!=null){
stack.push(unvisited_node);
visited_node+=unvisited_node;
}
else
stack.pop()
}
Ответ 11
Вы можете использовать стек. Я реализовал графики с матрицей смежности:
void DFS(int current){
for(int i=1; i<N; i++) visit_table[i]=false;
myStack.push(current);
cout << current << " ";
while(!myStack.empty()){
current = myStack.top();
for(int i=0; i<N; i++){
if(AdjMatrix[current][i] == 1){
if(visit_table[i] == false){
myStack.push(i);
visit_table[i] = true;
cout << i << " ";
}
break;
}
else if(!myStack.empty())
myStack.pop();
}
}
}
Ответ 12
Иерархия DFS в Java:
//DFS: Iterative
private Boolean DFSIterative(Node root, int target) {
if (root == null)
return false;
Stack<Node> _stack = new Stack<Node>();
_stack.push(root);
while (_stack.size() > 0) {
Node temp = _stack.peek();
if (temp.data == target)
return true;
if (temp.left != null)
_stack.push(temp.left);
else if (temp.right != null)
_stack.push(temp.right);
else
_stack.pop();
}
return false;
}
Ответ 13
Используя Stack
, выполните следующие действия: Нажмите первую вершину в стеке, затем
- Если возможно, посетите соседнюю невидимую вершину, отметьте ее, и надавите на стек.
- Если вы не можете выполнить шаг 1, то, если это возможно, вытащите вершину с стек.
- Если вы не можете выполнить шаг 1 или шаг 2, вы сделали.
Здесь программа Java выполняет следующие шаги:
public void searchDepthFirst() {
// begin at vertex 0
vertexList[0].wasVisited = true;
displayVertex(0);
stack.push(0);
while (!stack.isEmpty()) {
int adjacentVertex = getAdjacentUnvisitedVertex(stack.peek());
// if no such vertex
if (adjacentVertex == -1) {
stack.pop();
} else {
vertexList[adjacentVertex].wasVisited = true;
// Do something
stack.push(adjacentVertex);
}
}
// stack is empty, so we're done, reset flags
for (int j = 0; j < nVerts; j++)
vertexList[j].wasVisited = false;
}
Ответ 14
Stack<Node> stack = new Stack<>();
stack.add(root);
while (!stack.isEmpty()) {
Node node = stack.pop();
System.out.print(node.getData() + " ");
Node right = node.getRight();
if (right != null) {
stack.push(right);
}
Node left = node.getLeft();
if (left != null) {
stack.push(left);
}
}