现在我有
private static void iterateall(BinaryTree foo) {
if(foo!= null){
System.out.println(foo.node);
iterateall(foo.left);
iterateall(foo.right);
}
}
您可以将其更改为迭代而不是递归吗?
答案 0 :(得分:40)
您正在寻找的是后继算法。
以下是如何定义:
正如您所看到的,为此,您需要一个父节点指针。
(1)
(1)
没有正确的子树,我们最多可以(3)
。这是右转,所以接下来是(3)
。(3)
有一个正确的子树,因此该子树中最左边的节点是下一个:(4)
。(4)
没有正确的子树,我们最多可以(6)
。这是右转,接下来是(6)
。(6)
有一个正确的子树,因此该子树中最左边的节点是下一个:(7)
。(7)
没有正确的子树,我们最多可以(6)
。这是一个左转,所以我们继续前进到(3)
。这是一个左转,所以我们继续前进到(8)
。这是右转,接下来是(8)
。(8)
有一个正确的子树,因此该子树中最左边的节点是下一个:(10)
。(10)
有一个正确的子树,因此该子树中最左边的节点是下一个:(13)
。(13)
没有正确的子树,我们最多可以(14)
。这是右转,接下来是(14)
。(14)
没有正确的子树,我们最多可以(10)
。这是一个左转,所以我们继续前进到(8)
。这是一个左转,所以我们想继续上升,但由于(8)
没有父母,我们已经到了最后。 (14)
没有继任者。Node getLeftMost(Node n)
WHILE (n.leftChild != NULL)
n = n.leftChild
RETURN n
Node getFirst(Tree t)
IF (t.root == NULL) RETURN NULL
ELSE
RETURN getLeftMost(t.root);
Node getNext(Node n)
IF (n.rightChild != NULL)
RETURN getLeftMost(n.rightChild)
ELSE
WHILE (n.parent != NULL AND n == n.parent.rightChild)
n = n.parent;
RETURN n.parent;
PROCEDURE iterateOver(Tree t)
Node n = getFirst(t);
WHILE n != NULL
visit(n)
n = getNext(n)
以上是上述算法的简单实现:
public class SuccessorIteration {
static class Node {
final Node left;
final Node right;
final int key;
Node parent;
Node(int key, Node left, Node right) {
this.key = key;
this.left = left;
this.right = right;
if (left != null) left.parent = this;
if (right != null) right.parent = this;
}
Node getLeftMost() {
Node n = this;
while (n.left != null) {
n = n.left;
}
return n;
}
Node getNext() {
if (right != null) {
return right.getLeftMost();
} else {
Node n = this;
while (n.parent != null && n == n.parent.right) {
n = n.parent;
}
return n.parent;
}
}
}
}
然后你可以拥有这样的测试工具:
static Node C(int key, Node left, Node right) {
return new Node(key, left, right);
}
static Node X(int key) { return C(key, null, null); }
static Node L(int key, Node left) { return C(key, left, null); }
static Node R(int key, Node right) { return C(key, null, right); }
public static void main(String[] args) {
Node n =
C(8,
C(3,
X(1),
C(6,
X(4),
X(7)
)
),
R(10,
L(14,
X(13)
)
)
);
Node current = n.getLeftMost();
while (current != null) {
System.out.print(current.key + " ");
current = current.getNext();
}
}
打印:
1 3 4 6 7 8 10 13 14
答案 1 :(得分:9)
您可以将其更改为迭代而不是递归吗?
您可以使用显式堆栈。伪代码:
private static void iterateall(BinaryTree foo) {
Stack<BinaryTree> nodes = new Stack<BinaryTree>();
nodes.push(foo);
while (!nodes.isEmpty()) {
BinaryTree node = nodes.pop();
if (node == null)
continue;
System.out.println(node.node);
nodes.push(node.right);
nodes.push(node.left);
}
}
但这并不比递归代码优越(除了代码中缺少的基本条件)。
答案 2 :(得分:2)
当然,您有两种常规算法,depth first search和breadth first search。
如果遍历顺序对您来说并不重要,请先考虑广度,实现迭代更容易。你的算法看起来应该是这样的。
LinkedList queue = new LinkedList();
queue.add(root);
while (!queue.isEmpty()){
Object element = queue.remove();
queue.add(element.left);
queue.add(element.right);
// Do your processing with element;
}
答案 3 :(得分:1)
与每次递归一样,您可以使用其他数据结构 - 即堆栈。 解决方案的草图:
private static void visitall(BinaryTree foo) {
Stack<BinaryTree> iterationStack = new Stack<BinaryTree>();
iterationStack.push(foo);
while (!iterationStack.isEmpty()) {
BinaryTree current = iterationStack.pop();
System.out.println(current.node);
current.push(current.right); // NOTE! The right one comes first
current.push(current.left);
}
}
答案 4 :(得分:0)
是的,您可以将其更改为迭代而不是递归,但随后会变得更加复杂,因为您需要有一些方法来记住从当前节点 back 的去向。在递归的情况下,Java调用堆栈处理它,但在迭代解决方案中,您需要构建自己的堆栈,或者可能在节点中存储指针。
答案 5 :(得分:0)
我有一棵树(不是二进制),最终用这个非常简单的算法解决了它。其他解决方案使用 left 和 right ,这些解决方案与示例中无关或甚至未实现。
我的结构是:每个父节点包含子节点列表的节点,每个子节点包含一个指向父节点的指针。很常见...
经过一系列的重构后,我想出了使用Kotlin的以下示例。转换为您选择的语言应该是微不足道的。
首先,节点必须提供2个简单的功能。这取决于您的Node类的实现:
leftMost - 这是第一个子节点。如果该节点有子节点,则它是第一个子节点等。如果没有子节点,则返回 this 。
fun leftMost(): Node {
if (children.isEmpty()) {
return this
}
var n = this
while (n.children.isNotEmpty()) {
n = n.children[0]
}
return n
}
nextSibling - 此节点的下一个兄弟,或NULL
fun nextSibling(): Node? {
if (parent == null) return null
val siblingIndex = parent.children.indexOf(this) + 1
return if (siblingIndex < parent.children.size) {
parent.children[siblingIndex]
} else {
null
}
}
迭代从root的leftMost开始。
然后检查下一个兄弟。
就是这样。
这是一个Kotlin迭代器函数。
fun iterator(): Iterator<Node> {
var next: Node? = this.leftMost()
return object : Iterator<Node> {
override fun hasNext(): Boolean {
return next != null
}
override fun next(): Node {
val ret = next ?: throw NoSuchElementException()
next = ret.nextSibling()?.leftMost() ?: ret.parent
return ret
}
}
}
这是相同的next()函数,但没有用于处理NULL值的Kotlin简写,对于那些不熟悉语法的人来说。
fun next(): Node {
val ret = next
if (ret == null) throw NoSuchElementException()
val nextSibling = ret.nextSibling()
if (nextSibling != null) {
next = nextSibling.leftMost()
}
else {
next = ret.parent
}
return ret
}