Java 二叉树的无序遍历有什么问题?
我使用java实现了BinaryTree,并尝试实现有序遍历。我在副本上干运行代码,在这种情况下它工作得很好,但是当我在IDE上运行它时,我得到了无限循环。但是为什么呢? 请帮忙Java 二叉树的无序遍历有什么问题?,java,data-structures,binary-tree,inorder,Java,Data Structures,Binary Tree,Inorder,我使用java实现了BinaryTree,并尝试实现有序遍历。我在副本上干运行代码,在这种情况下它工作得很好,但是当我在IDE上运行它时,我得到了无限循环。但是为什么呢? 请帮忙 class BinaryTree{ class Node{ private int data; private Node left, right; public Node(int data) {
class BinaryTree{
class Node{
private int data;
private Node left, right;
public Node(int data)
{
this.data = data;
left=null;
right=null;}
}
public void inOrderTraversal(Node root)
{
Stack<Node> stack = new Stack<>();
Node temp = root;
stack.push(root);
while(!stack.isEmpty())
{
temp = stack.peek();
if(temp.left!=null)
{
stack.push(temp.left);
}
else
{
temp = stack.pop();
System.out.print(temp.data+" ");
if(temp.right!=null)
{
stack.push(temp.right);
}
}
}
}
public static void main(String[] args) {
Node one = new Node(1);
Node two = new Node (2);
Node three = new Node(3);
Node four = new Node(4);
Node five = new Node(5);
Node six = new Node(6);
one.left = two;
one.right = three;
two.left = four;
two.right = five;
three.left = six
BinaryTrees bn = new BinaryTrees();
bn.inOrderTraversal(one);
}
}
类二进制树{
类节点{
私有int数据;
私有节点左、右;
公共节点(int数据)
{
这个数据=数据;
左=空;
right=null;}
}
OrderTraversal中的公共void(节点根)
{
堆栈=新堆栈();
节点温度=根;
栈.推(根);
而(!stack.isEmpty())
{
temp=stack.peek();
如果(左侧温度!=null)
{
堆栈推送(左侧温度);
}
其他的
{
temp=stack.pop();
系统输出打印(温度数据+“”);
如果(临时正确!=null)
{
堆栈推送(右侧温度);
}
}
}
}
公共静态void main(字符串[]args){
节点1=新节点(1);
节点二=新节点(2);
节点三=新节点(3);
节点4=新节点(4);
节点5=新节点(5);
节点6=新节点(6);
一左=二;
一。右=三;
2.左=四;
二。右=五;
3.左=六
BinaryTrees bn=新的BinaryTrees();
bn.有序旅行(一);
}
}
您的代码以节点根开始
等于一
。one
左侧为two
,two
左侧为four
。在执行else
条件之前,遍历将two
然后four
推送到堆栈中。然后你弹出四个四个,由于四个在右边没有任何内容,你的循环重新开始。但是堆栈的顶部现在是两个。在two
的左边仍然是four
,因此您将four
推到堆栈上,从而开始无限循环
您需要一种方法来指示已经访问过的节点。如果确实必须使用堆栈,则应向节点类添加一个新属性,如private
,并将其初始化为false
。在每次temp=stack.pop()
之后,您需要设置temp.visted=True
,并且只推送到尚未访问的堆栈节点上。例如:
class Node {
private int data;
private Node left, right;
private boolean visited;
public Node(int data) {
this.data = data;
left = null;
right = null;
visited = false;
}
}
public void inOrderTraversal(Node root) {
Stack<Node> stack = new Stack<>();
Node temp = root;
stack.push(root);
while(!stack.isEmpty()) {
temp = stack.peek();
if(temp.left != null && !temp.left.visited) {
stack.push(temp.left);
}
else {
temp = stack.pop();
temp.visited = true;
System.out.print(temp.data + " ");
if(temp.right != null && !temp.right.visited) {
stack.push(temp.right);
}
}
}
}
为了解决上述问题,我们可以在这里使用队列和堆栈进行实现
public void inOrderTraversal(Node root) {
Stack<Node> stack = new Stack<>();
Queue<Node> out = new LinkedList<>();
Node temp = root;
stack.push(root);
while (!stack.isEmpty()) {
temp = stack.peek();
if (temp.left != null && !temp.left.visited) {
stack.push(temp.left);
} else {
temp = stack.pop();
temp.visited = true;
out.offer(temp);
if (temp.right != null && !temp.right.visited) {
stack.push(temp.right);
}
}
}
while(!out.isEmpty())
{
Node tempo = out.poll();
System.out.print(tempo.data+" ");
tempo.visited=false;
}
}
orderTraversal中的公共void(节点根){
堆栈=新堆栈();
Queue out=new LinkedList();
节点温度=根;
栈.推(根);
而(!stack.isEmpty()){
temp=stack.peek();
if(temp.left!=null&!temp.left.visitored){
堆栈推送(左侧温度);
}否则{
temp=stack.pop();
访问温度=真;
报价(临时);
if(临时权限!=null&!临时权限已访问){
堆栈推送(右侧温度);
}
}
}
而(!out.isEmpty())
{
节点速度=out.poll();
系统输出打印(节拍数据+“”);
节拍=假;
}
}
这是正确的解决方案。什么是节点
?调用函数时,Node root
的值是多少?这里的Node是我定义树的左、右指针的内部类,数据和root是树的根(第一个节点)。请在您的问题中提供Node
的定义,因为它是高度相关的。此外,如果调用函数时节点根恰好指向自身,那么它将递归地继续将自身推到堆栈上,代码将永远循环。太棒了!我会查看您的代码并返回给您。您有机会查看我的答案吗?或者在推堆栈时,检查temp==temp.left
?temp==temp.left
仅当它们是同一个对象时有效。在本例中,OP提供的这种条件无法解析无限循环。适当的解决方法是使用递归。@h0r53先生,我的PostOrderTraversal也有同样的问题。如果我在一次遍历中标记访问的每个节点,那么在其他遍历中它们将不会被打印。你能给我一个具体的解决办法吗。但是,如果我只在程序中使用顺序,那么这个解决方案是有效的。注意在这里使用“正确”这个词。最理想的解决方案是使用递归。通过简单地将print语句上下移动一行,可以修改我提供的递归示例,以实现pre、post和顺序遍历。
public void inOrderTraversal(Node root) {
Stack<Node> stack = new Stack<>();
Queue<Node> out = new LinkedList<>();
Node temp = root;
stack.push(root);
while (!stack.isEmpty()) {
temp = stack.peek();
if (temp.left != null && !temp.left.visited) {
stack.push(temp.left);
} else {
temp = stack.pop();
temp.visited = true;
out.offer(temp);
if (temp.right != null && !temp.right.visited) {
stack.push(temp.right);
}
}
}
while(!out.isEmpty())
{
Node tempo = out.poll();
System.out.print(tempo.data+" ");
tempo.visited=false;
}
}