Given the task to create your own implementation of a TreeSet , which should have the add(E e) and List<E> get() methods.
Does my code correctly illustrate the operation of a TreeSet ? If it is incorrect, then in what?
If it is at least partially correct, then how can I test that I created the tree, because my get method according to the condition of the problem returns a List ?
Implemented interface:
public interface Tree<E> extends Iterable<E> { boolean add(E e); List<E> get(); int size(); } The implementation itself:
public class SimpleTreeSet<E> implements Tree<E> { private Leaf<E> root; private List<E> list; private int size = 0; public SimpleTreeSet() { list = new LinkedList<>(); } @Override public boolean add(E e) { if (size == 0) { return initRootLeaf(e); } Leaf<E> newNode = new Leaf<>(e); Leaf<E> lastNode = findLastLeaf(root, newNode); if (lastNode == null) { return false; } // храню элементы для итератора и get list.add(newNode.element); if (lastNode.compareTo(newNode) > 0) { lastNode.right = newNode; size++; return true; } else { lastNode.left = newNode; size++; return true; } } // ищу последний лист дерева private Leaf<E> findLastLeaf( final Leaf<E> oldLeaf, final Leaf<E> newLeaf ) { Leaf<E> lastLeaf = oldLeaf; int compare = oldLeaf.compareTo(newLeaf); if (compare > 0 && oldLeaf.right != null) { lastLeaf = findLastLeaf(oldLeaf.right, newLeaf); return lastLeaf; } if (compare < 0 && oldLeaf.left != null) { lastLeaf = findLastLeaf(oldLeaf.left, newLeaf); return lastLeaf; } if (compare == 0) return null; return lastLeaf; } private boolean initRootLeaf(final E e) { root = new Leaf<>(e); list.add(e); size++; return true; } @Override public List<E> get() { return list; } @Override public int size() { return size; } @Override public Iterator<E> iterator() { return list.iterator(); } private class Leaf<E> implements Comparable<E> { private Leaf<E> right; private Leaf<E> left; private E element; private Leaf(E element) { this.element = element; } @Override public int compareTo(Object obj) { if (obj instanceof SimpleTreeSet.Leaf) { Leaf<E> node = (Leaf<E>) obj; return this.hashCode() - node.hashCode(); } throw new ClassCastException(); } @Override public int hashCode() { int hash = 31; hash = hash * 17 + element.hashCode(); return hash; } } }
Treeinterface code in the question, because without it an example cannot be reproduced. 2. It is incorrect to store theListin this case, because thegetmethod returns an unsorted list — the meaning in the entire tree disappears abruptly. The list is worth collecting from scratch right ingetThis at the same time protects against breakage of wood from the outside. 3. Inif (lastNode.compareTo(newNode) > 0) - elsestringsize++;andreturn true;there are in both branches - it means that they can be taken out for anif-else. - RegentLeafhashCode()method not to return justelement.hashCode()? Adding a constant (31 * 17) doesn't help anything. - Regentif (obj instanceof SimpleTreeSet.Leaf). First, otherwiseClassCastExceptionis still thrown, and second, it is aprivateclass, so you can be more or less sure thatobjisLeaf<E>. Yes that there: it is possible to refuse in generalimplements Comparable<E>and to make thecompareTo(Leaf<E> leaf)methodcompareTo(Leaf<E> leaf). This is perhaps a controversial statement, but why make the small auxiliary inner class "universal"? - Regent527? - Regent