简体   繁体   中英

Edit the nodes in a binary tree in Java

Okay. I have a binary tree, and this is what I want to do with it:

For each node in original tree: If it's not a leaf, replace it with a leaf node. Do a calculation on the original tree updated with the removed branch. Revert the node back to how it was (so now the tree is the same as at the beginning).

The problem is this: I am traversing the tree using a stack. If I change the stack.pop() node to a leaf, this does NOT remove any branches in the original tree. It's the same reasoning behind why you can do:

int x=1
int y=x
y++

And x still equals 1. There's a technical term for this but I forgot it.

So how can I edit the nodes in an original tree and still traverse it?

This is basically what I'm doing to traverse the tree right now:

public void iterativePreorder(Node root) {
        Stack nodes = new Stack();
        nodes.push(root);

        Node currentNode;

        while (!nodes.isEmpty()) {
                currentNode = nodes.pop();
                Node right = currentNode.right();
                if (right != null) {
                        nodes.push(right);
                }
                Node left = currentNode.left();
                if (left != null) {
                        nodes.push(left);      
                }
                //This is where you do operations on the currentNode
        }
}

From what I can tell from your question, for every Node you want to calculate something about the tree as if that node was a leaf.

To do this there is no reason to actually make that node a leaf and then reattach it. Instead, your logic can simply remember which node to treat as a leaf for each computation.

Traverse the tree, and for each Node , let's call it outerCurrentNode , once again traverse the tree doing your calculation - but now for each Node , let's call it innerCurrentNode , test to see if outerCurrentNode == innerCurrentNode . If the test returns true , treat that innerCurrentNode as if it's a leaf, ignoring its children.

EDIT: Here's a mock up of what I'm suggesting (untested):

//entry point - called from directing code
public void iterativePreorder(Node root) {
   iterativePreorderKernel(root, root);
}

//recursive method - keeps track of root in addition to current Node
private void iterativePreorderKernel(Node root, Node current) {

    if (current.left() != null) {
        iterativePreorderKernel(root, current.left());
    }
    if (current.right() != null) {
        iterativePreorderKernel(root, current.right());
    }

    //for each Node in the tree, do calculations on the entire tree, pretending
    //the current Node is a leaf
    doCalculation(root, current);
}

//calculation method (also recursive) - takes a current Node, plus
//the Node to treat as a leaf
public void doCalculation(Node innerCurrent, Node pretendLeaf) {

   //do calculation with inner current node

   if (innerCurrent != pretendLeaf) {
      if (innerCurrent.left() != null) {
         doCalculation(innerCurrent.left(), pretendLeaf);
      }
      if (innerCurrent.right() != null) {
         doCalculation(innerCurrent.right(), pretendLeaf);
      }
   }
}

I'm using recursion instead of a Stack , but either will work. iterativePreorder() does a traversal, calling doCalculation() for each Node , passing it in along with the root (to keep track of the entire tree). That method then does its own traversal, doing your calculation, but stopping short when it reaches the specially marked Node .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM