I'm writing a spatial data structure and I have a doubt about what's the best NODE implementation.
According to my design I have an abstract node entity and three classes which inherit from it: EMPTYNODE, FULLNODE, INTERNALNODE.
The first one has no particular data.
The second one has 1 reference to a generic element.
The third one has 2 references to other nodes.
I have found several ways to implement this situation (that I have already coded) but I can't decide what's the best.
The first solution that I have found is to use a single class Node that potentially performs all the operation in this way:
private static class Node {
private Elem elem = null;
private Node left = null, right = null;
public Elem getElem() {
assert isFull();
return elem;
}
public boolean isEmpty() {
return elem == null && left == null;
}
public boolean isFull() {
return elem != null;
}
public boolean isInternal() {
return elem == null && left != null;
}
}
The second solution is to write an explicit division by classes where every class offers only its methods. Obviously in this way we are obliged to perform several casts to the node objects.
private static abstract class Node {
public abstract boolean isEmpty();
public abstract boolean isFull();
public abstract boolean isInternal();
}
private static class FullNode extends Node{
private ITriangle elem;
#Override
public boolean isEmpty() {
return false;
}
#Override
public final boolean isFull() {
return true;
}
#Override
public final boolean isInternal() {
return false;
}
public Elem getElem() {
return elem;
}
}
The third solution is to use the inheritance allowing every classes to offer all the methods, but the object type should by check by "isEmpty()" and similar methods. In case of wrong call we'll throw an exception.
private static abstract class Node {
public abstract boolean isEmpty();
public abstract boolean isFull();
public abstract boolean isInternal();
public abstract Elem getElem();
}
private static class Empty extends Node{
#Override
public boolean isEmpty() {
return true;
}
#Override
public final boolean isFull() {
return false;
}
#Override
public final boolean isInternal() {
return false;
}
#Override
public Elem getElem() {
throw new AssertionError();
}
}
What do you think about these three solutions?
Which one would you use?
Any ideas will be appreciated.
The answer would depend on how the nodes are used. Once a node is created would it ever need to change from empty to internal to full, or is it immutable?
From the options given if a node is immutable then I'd go for option 3 if you're expecting the internal state to change then I'd go with option 1.
If you wanted a mutable node where the behaviour would change I'd look at using a Node class to hold the data with an enumeration to hold the states, the node would then delegate to the appropriate enumeration for it's implementation. For example:
public class Node {
private enum NodeState {
/* each state overrides specific methods to implement custom behaviour */
FULL { public boolean isFull() { return true; } },
INTERNAL { public boolean isInternal() { return true; } },
EMPTY { public boolean isEmpty() { return true; } };
/* the default behaviour */
public boolean isFull() { return false; }
public boolean isEmpty() { return false; }
public boolean isInternal() { return false; }
}
private NodeState state = NodeState.EMPTY;
private Elem elem = null;
private Node left = null, right = null;
public Elem getElem() {
assert isFull();
return elem;
}
/* TODO: constructors/mutators implement state changes go here */
public boolean isEmpty() {
return state.isEmpty();
}
public boolean isFull() {
return state.isFull();
}
public boolean isInternal() {
return state.isInternal();
}
}
class Elem {
/* implementation of this class */
}
Related
I have a simple class that wraps an unmodifiable list (it is used as a context for a query):
public class Context<T extends Node> implements Iterable<T> {
private final List<T> m_nodes;
Context(List<T> nodes) {
m_nodes = Collections.unmodifiableList(nodes);
}
#Override
public Iterator<T> iterator() {
return m_nodes.iterator();
}
public int indexOf(T node) {
return m_nodes.indexOf(node);
}
public boolean isEmpty() {
return m_nodes.isEmpty();
}
// context are always sorted by pre value
public boolean containsAll(FDMContext<T> other) {
Iterator<T> oit = other.iterator();
Iterator<T> sit = iterator();
int c = 0;
while( oit.hasNext()) {
T o = oit.next();
while( sit.hasNext()) {
T s = sit.next();
if( s.getPre() == o.getPre()) {
c++;
break;
}
}
}
return c == other.size();
}
public int size() {
return m_nodes.size();
}
public List<T> getNodes() {
return m_nodes;
}
#Override
public String toString() {
return m_nodes.toString();
}
}
The Node class has a Value subclass. I don't think the details of the Node and Value class are important, except that they share a common getPre() method defining a unique node identifier.
If there is a method that expects an Context<Value> parameter but I have an Context<Node> instance as a result of a query where I am certain it only contains Value instances, is it safe to suppress warnings?
e.g.
static Entry makeEntry(Event event, Group head, Group tail, Context<Value> values) {
/* code */
}
...
Context<Node> ctx = query(anotherCtx,somePath); // the result ctx contains only Value objects. The query method returns a Context(Node) object
#SuppressWarnings({ "rawtypes", "unchecked" })
Entry ret = makeEntry( this, headGrp, tailGrp, (Context)tail);
I could create a new context of type Context<Value>, but I'd rather avoid the copy if possible.
for example, I want to create a parent class Node, and subclasses IntegerNode and CharacterNode.
and try to find if a value already exists in a list without knowing what the type of values are.
for that, I will send my Node object and during runtime, I want to get the appropriate value.
there is a way to do that without using an instance of?
public class CharNode extends Node {
private Character charNode;
CharNode(char digit){
this.charNode = digit;
}
Character getValue(){
return charNode;
}
}
public class IntegerNode extends Node {
private Integer integerNode;
IntegerNode(int number){
this.integerNode = number;
}
Integer getValue(){
return integerNode;
}
}
public class Node {
Node getNode();
}
boolean isExists(List<Node> list, Node value){
///// Here I want to check if the value inside the node already exists in that list without checking the type. It can be Lists of characters or a list of integers.
}
I've changed your classes a bit, so it's easier to work with them.
public abstract class Node<T> {
public abstract T getValue();
// I guess you implemented this method, but didn't copy it in your example.
//Node getNode();
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Node<?> otherNode = (Node<?>) o;
T value = getValue();
if (value == null) return otherNode.getValue() == null;
return getValue().equals(otherNode.getValue());
}
// If you implement eqauls you should also always implement hashCode.
public int hashCode() {
T value = getValue();
return value != null ? value.hashCode() : 0;
}
}
public class CharNode extends Node<Character> {
private Character value;
public CharNode(char value){
this.value = value;
}
#Override
public Character getValue(){
return value;
}
}
public class IntegerNode extends Node<Integer> {
private Integer value;
public IntegerNode(int value){
this.value = value;
}
#Override
public Integer getValue(){
return value;
}
}
Node is now abstract and has a abstract method getValue added to it. Any class that inherits from Node is now forced to implement getValue. Additionally I added simple implementations of equals & hashCode. In your case you would probably only need equals, but not implementing hashCode when implemeneting equals is very bad practice and can break classes that rely on a working implementation.
Now just iterate over the list and check equals every time.
public boolean isExists(List<? extends Node<?>> list, Node<?> value) {
for (Node<?> node : list) {
if (node.equals(value)) {
return true;
}
}
return false;
}
Or use List.contains which does the same for us.
public boolean isExists(List<? extends Node<?>> list, Node<?> value) {
return list.contains(value);
}
Here is an example for using a list of CharNodes.
CharNode sNode = new CharNode('s');
CharNode cNode = new CharNode('c');
IntegerNode oneNode = new IntegerNode(1);
IntegerNode twoNode = new IntegerNode(2);
List<CharNode> charNodes = Arrays.asList(sNode, cNode);
System.out.println(isExists(charNodes, new CharNode('s'))); // true
System.out.println(isExists(charNodes, new CharNode('x'))); // false
You can also create a list of nodes with mixed types.
List<Node<?>> allNodes = Arrays.asList(sNode, cNode, oneNode, twoNode);
System.out.println(isExists(allNodes, new CharNode('s'))); // true
System.out.println(isExists(allNodes, new IntegerNode(1))); // true
System.out.println(isExists(allNodes, new CharNode('x'))); // false
You can use Node.getValue() to get the value, but without knowing the type of getValue() there is only so much you can do.
Object nodeValue = allNodes.get(3).getValue();
System.out.println(nodeValue); // 2
As you mentioned you can use instanceof to get the type and write codefor each instanceof check, but there is a much better solution: Add another method in your Node class and implement appropriate behavior for this method in your children.
The easiest way to do that is to implement the equals method for both classes:
// equals for the CharNode class
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
// add here the logic specific to each class
return this.charNode.equals(((CharNode)o).charNode);
}
// equals for the IntegerNode class
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
// add here the logic specific to each class
return this.integerNode.equals(((IntegerNode)o).integerNode);
}
After that you'll be able to use the list.contains(node) method
Try this.
static abstract class Node {
protected Object value;
public Node(Object value) {
this.value = value;
}
public Object getValue() {
return value;
}
}
static class CharacterNode extends Node {
public CharacterNode(char value) {
super(value);
}
}
static class IntegerNode extends Node {
public IntegerNode(int value) {
super(value);
}
}
public static void main(String[] args) {
List<Node> nodes = List.of(new CharacterNode('a'), new IntegerNode(3));
for (Node node : nodes)
if (node.getValue().equals(3))
System.out.println("found value 3");
}
output:
found value 3
I have been following along in the book Data Structures (Into Java) by Paul Hilfinger and I am having trouble implementing some part of a Tree structure.
When during the implementation, the book suggested that we have a nested static class represent an empty tree to make so methods using a Tree do not have to check for null pointers. The example code looks like this
public class Tree<T> {
public Tree(T label) ...
public Tree(T label, int k) ...
public T label() ...
public int degree() ...
public int numChildren() ...
public Tree<T> child(int k) ...
public void setChild(int k, Tree<T> C) ...
public boolean isEmpty() { return false }
public final Tree<T> EMPTY = new EmptyTree();
static class EmptyTree<T> extends Tree<T> {
private EmptyTree() {}
public boolean isEmpty() { return true }
public int degree() { return 0 }
public int numChildren() { return 0 }
public Tree<T> getChild(int i) {
throw new Exception;
}
public T label() {
throw new Exception;
}
}
}
Here is my implementation:
public class NonEmptyGTree<T> {
public NonEmptyGTree(T label, int arity) {
this.label = label;
children = (NonEmptyGTree<T>[]) new Object[arity];
for (int i = 0; i < arity; i++)
children[i] = EMPTY;
}
public NonEmptyGTree() {
}
public NonEmptyGTree<T> getChild(int i) {
return children[i];
}
public void setChild(int i, NonEmptyGTree<T> set) {
if (children[i].isEmpty()) deg += 1;
children[i] = set;
}
public T getLabel() {
return label;
}
public void setLabel(T label) {
this.label = label;
}
public int numChildren() {
return children.length;
}
public int degree() {
return deg;
}
public boolean isLeaf() {
return deg == 0;
}
public boolean isEmpty() {
return false;
}
public class EmptyGTree<T> extends NonEmptyGTree<T> {
private EmptyGTree() {}
public int degree() { return 0; }
public int numChildren() {
return 0;
}
public NonEmptyGTree<T> getChild(int i) {
throw new IllegalStateException();
}
public void setChild(int i, NonEmptyGTree<T> set) {
throw new IllegalStateException();
}
public T getLabel() {
throw new IllegalStateException();
}
public void setLabel(T label) {
throw new IllegalStateException();
}
public boolean isEmpty() {
return true;
}
}
private T label;
private NonEmptyGTree[] children;
private int deg = 0;
public final NonEmptyGTree<T> EMPTY = new EmptyGTree<T>();
}
This made sense to me since that way we won't have to check for null pointers when we use trees elsewhere, but when I try to initialize a tree, it goes into a loop with the Tree initializing EMPTY then EMPTY calling super() which then initializes Tree again looping.
I then tried to use a Null design pattern where I made a Tree interface and and then had two files implementing it, one for an empty tree and a nonempty tree. This seems messy to me because then for any subtype of a Tree, I would have to split it up into a nonempty tree and empty tree for every subtype. It seems like the idea of making an empty tree should stop with just this one implementation since functionally all empty trees are the same (if you do not need to access the parent nodes).
Is it not possible to make it so that I would only have to implement the EmptyTree once? Or is what I am asking to do not possible?
Here is my class:
public class LinkedListSet implements Set {
private class Node //much easier as a private class; don't have to extend
{
private int data;
private Node next;
public Node (){}
public Node (int x)
{
data = x;
}
public int data()
{
return data;
}
public Node next()
{
return next;
}
}
private Node first;
private int Size;
private int whichList; //used to identify the particular LL object
Here is my interface:
public interface Set {
public boolean isEmpty();
public void makeEmpty();
public boolean isMember(int x);
public void add(int x);
public void remove(int y);
public void union(Set other, Set result);
public void intersection (Set other, Set result);
public void difference (Set other, Set result);
#Override
public String toString();
#Override
public boolean equals(Object other);
public void setList(int i); //i added this to use it as an identifier for each
//list element in the set array
public String getListId(); //these two extra methods make life easier
}
I have a method like this (in the LinkedListSet class):
public void difference (Set other, Set result)
{
if (other.isEmpty())
{
System.out.println("The set is empty before cast");
}
LinkedListSet othr = (LinkedListSet) other;
LinkedListSet res = (LinkedListSet) result;
if (this.isEmpty() || othr.isEmpty())
{
if (othr.isEmpty())
System.out.println("The set is empty after cast");
if (this.isEmpty())
System.out.println("This is also empty");
return;
}
differenceHelper(this.first, othr.first, res);
result = res;
}// the print statements were added for debugging
The problem is, in the above method I am unable to cast the Set Other into its linked list implementation. When I call this method in the main program, the parameter is actually of type linked list (so I don't get any errors obviously).
However, all the instance variables are null. The list is empty before and after I cast it (when it actually isn't empty). I know this is because the interface doesn't include any information about the Nodes, but is there anything I can do other than editing the interface to incorporate the Node?
I hope I've made this clear enough. Any help would be appreciated.
edit:
In the main program I created an array of Sets.
Set[] sets = new Set[7];
for (int i = 0; i< sets.length; i++) //initialize each element
{
sets[i] = new LinkedListSet();
}
each list has nodes with data values which are added on later on in the code...
then I call the difference method.
sets[0].difference(sets[1], sets[4])
sets[1].isEmpty returns true for some reason (even though it is not).
If I were to do something like:
System.out.println(sets[1].first.data()) I would have no problem whatsoever.
For some reason all the values become null when the parameters are passed to the difference method.
public boolean isEmpty()
{
return first == null;
}
I tested what you are trying to do with the following code and I see no problems:
import org.junit.Test;
public class RandomCastTest {
public interface Set {
boolean isEmpty();
void add(int x);
void difference(Set other, Set result);
#Override
String toString();
#Override
boolean equals(Object other);
}
public class LinkedListSet implements Set {
private class Node //much easier as a private class; don't have to extend
{
private int data;
private Node next;
public Node() {
}
public Node(int x) {
data = x;
}
public int data() {
return data;
}
public Node next() {
return next;
}
public void next(Node node) {
next = node;
}
}
private Node first;
private int Size;
private int whichList; //used to identify the particular LL object
#Override
public boolean isEmpty() {
return first == null;
}
#Override
public void add(int x) {
Node node = new Node(x);
if (first == null) {
first = node;
} else {
Node currentNode;
Node nextNode = first;
do {
currentNode = nextNode;
nextNode = currentNode.next();
} while (nextNode != null);
currentNode.next(node);
}
Size++;
}
#Override
public void difference(Set other, Set result) {
if (other.isEmpty()) {
System.out.println("The set is empty before cast");
}
LinkedListSet othr = (LinkedListSet) other;
LinkedListSet res = (LinkedListSet) result;
if (this.isEmpty() || othr.isEmpty()) {
if (othr.isEmpty())
System.out.println("The set is empty after cast");
if (this.isEmpty())
System.out.println("This is also empty");
return;
}
result = res;
}
}
#Test
public void test() {
Set[] sets = new Set[7];
for (int i = 0; i < sets.length; i++) {
sets[i] = new LinkedListSet();
}
for (int i = 0; i < 5; i++) {
sets[1].add(i);
}
for (int i = 5; i < 10; i++) {
sets[0].add(i);
}
sets[0].difference(sets[1], sets[4]);
// ... find difference
}
}
To simplify I removed unimplemented methods from the interface. Also added the add method implementation. Please see if it works for you.
These are my fields:
public class BSTSet <E> extends AbstractSet <E> {
// Data fields
private BSTNode root;
private int count = 0;
private Comparator<E> comp; // default comparator
/** Private class for the nodes.
* Has public fields so methods in BSTSet can access fields directly.
*/
private class BSTNode {
// Data fields
public E value;
public BSTNode left = null;
public BSTNode right = null;
// Constructor
public BSTNode(E v) {
value = v;
}
}
// Constructors - can either use a default comparator or provide one
public BSTSet() {
comp = new ComparableComparator(); // Declared below
}
public BSTSet(Comparator <E> c) {
comp = c;
}
// Methods
/** Return true iff the set is empty */
public boolean isEmpty() {
return count == 0;
}
/** Return the number of elements in set */
public int size() {
return count;
}
and this is the method i am trying to fix:
/** Return true iff (if and only if) the set contains an item
* (the item must be non null)
*/
public boolean contains(Object item) {
// YOUR CODE HERE
//changes item to E so it can be used in the comparator
E value1 = (E) item;
if (root.value.equals(item)){
return true;
}
int s = comp.compare(value1,root.value);
if(s<0){
if (root.left == null)
return false;
else
return root.left.contains(item);
}
else if(s>0){
if (root.right == null)
return false;
else
return root.right.contains(item);
}
}
so far everything seems to go okay, but it fails at return root.left.contains(item); and says it cannot find symbol - method contains. How do i fix this so that i can run my contains method which should return whether or not the value is in the BST?
Both left and right are declared as BSTNode instances. BSTNode doesn't have a method called contains, so you need to add one:
public boolean contains(Object item) {
return value.equals(item);
}
Ideally, you'd want both your nodes and sets to implement the same interface, so you don't know which implementation you're actually calling.