0

I am trying to check whether my levelorder of my Binary Search Tree is equal to the other one. To do this, I tried to make a compareTo method. I only give equal values to the method, but it keeps on saying the condition is false. When I place breakpoints, I see that the values are still equal. I am probably not understanding it correctly. Does anyone know how to solve this?

Here is what I did, as you can see below, the compareTo returns a 1 instead of a 0:

import edu.princeton.cs.algs4.BST;
import java.util.*;

public class MyBST implements Comparable<MyBST>{

    private Object e;

    public MyBST(Object e){
        this.e = e;
    }

    private Object getE(){
        return e;
    }

    public static void main(String[] args) {

        int size = 4;

        Random r = new Random();
        Set<Integer> tes = new LinkedHashSet<>(size);
        Stack<Integer> stack = new Stack<>();

        while (tes.size() < size) {
            tes.add(r.nextInt(10));
        }

        System.out.println("possible combinations");
        Set<Stack<Integer>> combos = combos(tes, stack, tes.size());

        Object[] arr = combos.toArray();
        List<String> d = new ArrayList<>();
        for (Object s : arr) {
            String b = s.toString();
            b = b.replaceAll("\\[", "").replaceAll("\\]", "");
            d.add(b);
        }

        int index = 0;

        do {
            BST<String, Integer> bst1 = new BST<String, Integer>();
            BST<String, Integer> bst2 = new BST<String, Integer>();
            String key1 = d.get(index);
            String key2 = d.get(index);
            key1 = key1.replaceAll(" ", "");
            String[] m = key1.split(",");

            key2 = key2.replaceAll(" ", "");
            String[] n = key2.split(",");

            System.out.println("1e order");
            for (int j = 0; j < m.length; j++) {

                System.out.println(m[j]);
                bst1.put(m[j], 0);
            }

            System.out.println("2e order");
            for (int j = 0; j < n.length; j++) {

                System.out.println(n[j]);
                bst2.put(n[j], 0);
            }

            System.out.println("levelorder 1e BST");

            MyBST e = new MyBST(bst1.levelOrder());
            MyBST y = new MyBST(bst2.levelOrder());

            System.out.println(bst1.levelOrder());

            System.out.println("levelorder 2e BST");

            System.out.println(bst2.levelOrder());

            System.out.println(e.compareTo(y) + "\n");
            index++;
        } while (index < arr.length - 1);

    }
    public static Set<Stack<Integer>> combos(Set<Integer> items, Stack<Integer> stack, int size) {
        Set<Stack<Integer>> set = new HashSet<>();

        if (stack.size() == size) {
            set.add((Stack) stack.clone());
        }
        Integer[] itemz = items.toArray(new Integer[0]);
        for (Integer i : itemz) {
            stack.push(i);
            items.remove(i);
            set.addAll(combos(items, stack, size));
            items.add(stack.pop());
        }
        return set;
    }

    @Override
    public int compareTo(MyBST o) {
        if (this.e == o.e) {
            return 0;
        }
        else
            return 1;
    }
}

Here you can find the BST.java class: BST.java

And the output is something like:

enter image description here

The breakpoint at the compareTo method says:

enter image description here

Liza Darwesh
  • 401
  • 1
  • 3
  • 20
  • 2
    Your comparator does not respect comparator contract, eg: a < b => b > a. So you should have a.compareTo(b) = - b.compareTo(a). With returning 0 and 1, you fail to validate that. Beside, Object is hardly comparable to another (= there is no natural ordering here). – NoDataFound Mar 28 '21 at 15:28
  • 2
    Your implementation of `compareTo` is broken: it can never return a negative value. Please check [the documentation of the method](https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html#compareTo-T-) to understand the requirements of an implementation. – Andy Turner Mar 28 '21 at 15:28
  • @NoDataFound nit: `sgn(a.compareTo(b)) == -sgn(b.compareTo(a))`: they don't have to be exactly equal in magnitude. – Andy Turner Mar 28 '21 at 15:29
  • @NoDataFound I don't know what you mean.. I am trying to compare a levelorder with another levelorder. But I just can't figure out how to make these Objects comparable. I tried casting them to Integers, but that wasn't possible – Liza Darwesh Mar 28 '21 at 15:33
  • @LizaDarwesh if `something.compareTo(somethingElse) > 0`, then `somethingElse.compareTo(something) < 0`. (e.g. `3 > 1` means that `1 < 3` as well). Your comparator can't do this because it only returns a positive value or zero, never a negative value. – Andy Turner Mar 28 '21 at 15:34
  • @LizaDarwesh provide the definition of levelOrder. – NoDataFound Mar 28 '21 at 15:34
  • You should not compare objects directly instead use looping to compare them value by value. – Raghav Joshi Mar 28 '21 at 15:36
  • @NoDataFound Traversal level order, where you visit every node on a level before going to a lower level. It is the same as Breadth–first search. – Liza Darwesh Mar 28 '21 at 15:37
  • define `private Object e;` as specific object then use `this.e.equals(o.e)` in the compareTo method. `==` is not same as `equals` method. – the Hutt Mar 28 '21 at 15:39
  • What I meant, was what is the function definition : what does it returns? – NoDataFound Mar 28 '21 at 15:39
  • @onkar ruikar you meant e.compareTo(o.e)... :) – NoDataFound Mar 28 '21 at 15:39
  • @onkarruikar But my bst1.levelorder() is not an Integer, but a Iterable – Liza Darwesh Mar 28 '21 at 15:44
  • Share BST implementation as well. Don't compare collections using `==`. – the Hutt Mar 28 '21 at 15:46
  • @NoDataFound If I'm not mistaken, the levelOrder method in the BST class returns keys, which is defined as Queue keys = new Queue(); – Liza Darwesh Mar 28 '21 at 15:46
  • Does this answer your question? [Comparing two Collections in Java](https://stackoverflow.com/questions/4085353/comparing-two-collections-in-java) – the Hutt Mar 28 '21 at 15:47
  • @onkarruikar I updated my question, you can find the BST.java code. Also, I am not allowed to use equals.. My assignment was to use the compareTo method from the Comparable class – Liza Darwesh Mar 28 '21 at 15:52

2 Answers2

2

When you're using the == operator you're actually checking to see if the references point to the same object in memory. From your debugging screenshot you can see that they are not. this.e points to object Queue@817 while o.e points to Queue@819.

ALex
  • 673
  • 1
  • 6
  • 19
  • [Comparing Collections](https://stackoverflow.com/questions/4085353/comparing-two-collections-in-java) – the Hutt Mar 28 '21 at 15:51
  • Is there a way to compare the value in that queue, because I am a little lost right now. – Liza Darwesh Mar 28 '21 at 15:54
  • Well it depends on what you want to achieve. I guess you want to see if all elements in `this.e` are in `o.e` or vice versa? If yes, then iterate over the elements and check if the other queue has them. – ALex Mar 28 '21 at 16:22
0

If all you want to do is test for equality, then just override equals and hashCode. You can do it like this (rest of class omitted):


public class MyBST {  

   private Object e;
  
   public MyBST(Object e) {
        this.e = e;
    }

    public Object getE(){
        return e;
    }
    
    @Override
    public int hashCode() {
        return Objects.hashCode(e);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (!(obj instanceof MyBST))
            return false;
        MyBST me = (MyBST) obj;
        if (e == null) {
            if (me.e != null)
                return false;
        } else if (!e.equals(me.e))
            return false;
        return true;
    }
}

Implementing Comparable is more involved since you need to check for less, equal, or greater than other instances of MyBST. Unfortunately, the only field in MyBST is an Object which does not tell you anything about its actual fields. So without specific fields with which to test you need to ensure that the Object you pass also implements Comparable. Then you can declare your class like this. Rest of class omitted.

It simply says that

  • MyBST is comparable.
  • And the object that is passed in the constructor is comparable.
class MyBST<T extends Comparable<? super T>> implements Comparable<MyBST<T>>{

    private T e;

    public MyBST(T e){
        this.e = e;
    }

    public T getE(){
        return e;
    }
    
    @Override
    public int compareTo(MyBST<T> o) {
        return e.compareTo(o.e);    
    }
}

The other alternative is to simply pass the actual object type and store it as such, not as Object. Then just implement Comparable in MyBST and use the appropriate fields of the passed object. Lets say the object was an Apple object, you could do this.

class Apple {
    String type;
    int weight;
}

class MyBST implements Comparable<MyBST> {
    
    private Apple apple;
    
    public MyBST(Apple apple) {
        this.apple = apple;
    }
    
    @Override
    public int compareTo(MyBST e) {
        // this could be different depending on how you wanted
        // to compare one apple to another. This comparison favors
        // type over weight.

        // check type - String class implements comparable
        int ret = apple.type.compareTo(e.apple.type);
        if (ret != 0) { 
            return ret;
        }
        
        // same type so check weight
        if (apple.weight < e.apple.weight) {
            return -1;
        }
        if (apple.weight > e.apple.weight) {
            return 1;
        }
        return 0;  // equals apples based on criteria
    }
}

Finally, you have this.

    private Object getE(){
        return e;
    }

A private getter is not usually very useful. Make it public.

WJS
  • 36,363
  • 4
  • 24
  • 39