Home > Software design >  OOP Implementing Clear for Binary Tree - do all nodes need to disown their children for proper GC, o
OOP Implementing Clear for Binary Tree - do all nodes need to disown their children for proper GC, o

Time:10-03

I wrote an example code about binary tree. Adding and traversing nodes to the binary tree both start from the root node. What should I do if I want to empty the whole binary tree? Use clear1 method or clear2 method? The clear1 method only sets the root node to null. The clear2 method traverses each node and then sets each node to null. It seems that both can achieve the goal of clearing. I don't know the difference between the two. If clear1 is used, I don't know whether the node that is not set to null will affect garbage collection

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class BinaryTree<T> {

public int size;

public Node root;

private Queue<Node> queue;

public class Node {
    public T value;
    public Node leftNode;
    public Node rightNode;

    private Node(T value, Node leftNode, Node rightNode) {
        this.value = value;
        this.leftNode = leftNode;
        this.rightNode = rightNode;
    }
}


public void add(T addValue) {
    Node node = new Node(addValue, null, null);
    if (null == root) {
        root = node;
        queue = new LinkedList<>();
        queue.offer(node);
    } else {
        Node queNode = queue.peek();
        if (null == queNode.leftNode) {
            queNode.leftNode = node;
            queue.offer(queNode.leftNode);
        } else if (null == queNode.rightNode) {
            queNode.rightNode = node;
            queue.poll();
            queue.offer(queNode.rightNode);
        }
    }
    size  ;
}


/**
 * Postorder Traversal
 */
public List<T> postTraverse() {
    return postTraverse(new ArrayList<>(), root);
}

private List<T> postTraverse(List<T> list, Node node) {
    if (list.size() != size && null != node) {
        postTraverse(list, node.leftNode);
        postTraverse(list, node.rightNode);
        list.add(node.value);
    }
    return list;
}

/**
 * clear Binary Tree method1
 */
public void clear1() {
    queue = null;
    size = 0;
    root = null;
}

/**
 * clear Binary Tree method2
 */
public void clear2() {
    queue = null;
    clear2(root);
    size = 0;
}

private void clear2(Node node) {
    if (null != node) {
        clear2(node.leftNode);
        clear2(node.rightNode);
        node = null;
    }
}
}

test:

 public static void main(String[] args) {
    BinaryTree<String> binaryTree = new BinaryTree<>();
    binaryTree.add("A");
    binaryTree.add("B");
    binaryTree.add("C");
    binaryTree.add("D");
    binaryTree.add("E");
    binaryTree.add("F");
    binaryTree.add("G");
    binaryTree.add("H");
    binaryTree.add("i");
    binaryTree.add("j");
    binaryTree.add("k");
    binaryTree.add("L");
    binaryTree.add("M");
    binaryTree.add("N");
    binaryTree.add("O");

    System.out.println(binaryTree.postTraverse());
    binaryTree.clear1();
}

CodePudding user response:

Just setting the root to null is the most efficient solution.

I don't know whether the node that is not set to null will affect garbage collection.

Assuming that nothing else has a reference to any of the Node objects (which should be the case if the code is implemented correctly), then setting root to null renders the entire tree of Node objects unreachable. They will typically be collected in the next new space collection.

Traversing the tree and clearing all of the references will achieve nothing, and will actually waste time.


For all existing Java GC implementations (with the possible exception of some "fall-back" collectors) minimal work is actually performed on heap nodes that are not reachable. The GC does not need to mark them, or visit them to check mark bits. Instead it copies all of the reachable objects out of the "space" being collected and ... eventually ... erases the rest.

So, since the unreachable tree is not going to be traversed, marked or looked at in any way, any changes your code makes to the nodes while clearing are pointless.

CodePudding user response:

Use the first method. There is no benefit to clear2 it just does a lot of useless work.

  • Related