1

I have implemented a simple Binary Search Tree. I want to create a subclass Red-Black Tree, but I'm having problems. The code for the BST is as follows, with the irrelevant details removed. The BST works perfectly fine.

Node:

public Node {
    private int key;

    public Node left;
    public Node right;
    public Node parent;

    public Node(int key){
        // init
    }
}

BST:

public BinarySearchTree {
    protected Node root;

    public void insert(int key){
        Node insertNode = new Node(key); // This is problematic
        // perform insertion
    }
}

I need to subclass Node to add a color property:

RbtNode:

public RbtNode extends Node {
    private boolean isBlack;

    public RbtNode(int key){
        // init
    }
}

And the RedBlackTree class

RedBlackTree

public RedBlackTree {

    public void insert(int key){
        super.insert(key);
        // perform RBT fixes
    }
}

As you can see, I want to reuse the insert method of BinarySearchTree, but since it inserts a Node and not an RbtNode, it won't work.

A solution I came up with is to create a separate method createNode(int key) that I can override, but I would need to do quite a bit of typecasting when accessing/manipulating nodes on the subclass.

Is there any cleaner solution, preferrably one without typecasts?

EDIT: The problem is when calling super.insert from the subclass (RedBlackTree), it uses the parent's root field instead of the subclass's root field.

  • You could keep `RbtNode` object in `RedBlackTree` and not reuse `protected Node root` from `BinarySearchTree` – miradham Aug 17 '18 at 01:17
  • This old question might help https://stackoverflow.com/questions/1090458/instantiating-a-generic-class-in-java – paisanco Aug 17 '18 at 01:25
  • You need a null check when insert the key value pair and where (the node) to insert it. Also use @Override instead on insert. – Arielle Nguyen Aug 17 '18 at 01:35
  • @miradham The BST insert uses the `root` field directly. So when calling `super.insert` from RBT, the method uses the parent's `root` instead of the subclass. What can I do about it? – Juan Dela Cruz Aug 17 '18 at 04:21
  • @paisanco It's not really about generics but the `Node` itself. The generics takes care of the value contained, not the subclassing of the node. – Juan Dela Cruz Aug 17 '18 at 04:22

2 Answers2

0

Try moving the tree logic you want to reuse to a generic super class with a factory method for Node creation:

public abstract class AbstractBinarySearchTree<T extends Node> {
    protected T root;

    public T insert(int key) {
        T insertNode = newNode(key);
        // perform insertion
        return insertNode;
    }

    public abstract T newNode(int key);
}

Concrete BST just needs the factory method to complete it:

public class BinarySearchTree extends AbstractBinarySearchTree<Node> {
    @Override
    public Node newNode(int key) {
        return new Node(key);
    }
}

RBT overrides the insert method and factory method:

public class RedBlackTree extends AbstractBinarySearchTree<RbtNode> {
    @Override
    public RbtNode insert(int key){
        RbtNode node = super.insert(key);
        // perform RBT fixes
        return node;
    }

    @Override
    public RbtNode newNode(int key) {
        return new RbtNode(key);
    }
}
teppic
  • 7,051
  • 1
  • 29
  • 35
0

You could keep root node for BST and RBT seperately and move common logic to single insert method

public class BST {
    private Node root;
    protected Node createNode(int key) {
        //System.out.println("create BST node");
        return new Node(key);
    }
    public void insert (int key) {
        insert(key, root);
    }
    protected Node insert(int key, Node root) {
        if (root == null) {
            root = createNode(key);
            return root;
        }
        if (key > root.key) {
            root.left = insert(key, root.left);
        } else if (key < root.key) {
            root.right = insert(key, root.right);
        }
        return root;
    }
 } 

RBT will have to override createNode and insert

public class RBTree extends BST {
    private RBNode root;
    @Override
    protected RBNode createNode(int key) {
        System.out.println("create RB node");
        return new RBNode(key);
    }
    @Override
    public void insert(int k) {
        super.insert(k, root);
    }
}
miradham
  • 2,285
  • 16
  • 26