diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f83e8cf --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.idea +target +*.iml diff --git a/src/main/java/ua/javarush/map/SimplifiedMap.java b/src/main/java/ua/javarush/map/SimplifiedMap.java new file mode 100644 index 0000000..100c18b --- /dev/null +++ b/src/main/java/ua/javarush/map/SimplifiedMap.java @@ -0,0 +1,8 @@ +package ua.javarush.map; + +public interface SimplifiedMap { + boolean add(K key, V value); + boolean remove(K key); + boolean contains(K key); + int size(); +} diff --git a/src/main/java/ua/javarush/map/SimplifiedTreeMap.java b/src/main/java/ua/javarush/map/SimplifiedTreeMap.java index 457a8ff..8c7d104 100644 --- a/src/main/java/ua/javarush/map/SimplifiedTreeMap.java +++ b/src/main/java/ua/javarush/map/SimplifiedTreeMap.java @@ -1,5 +1,172 @@ package ua.javarush.map; -public class SimplifiedTreeMap { +import java.util.Comparator; +public class SimplifiedTreeMap, V> implements SimplifiedMap { + private final Comparator comparator; + private Entry root; + private int size; + + public SimplifiedTreeMap() { + comparator = null; + } + + public SimplifiedTreeMap(Comparator comparator) { + this.comparator = comparator; + } + + @Override + public boolean add(K key, V value) { + if (size == 0) { + root = new Entry<>(key, value, null); + size++; + return true; + } + + Entry temp = root; + Entry parent; + int diff; + + do { + parent = temp; + diff = compare(key, temp.key); + if (diff < 0) { + temp = temp.left; + } else if (diff > 0) { + temp = temp.right; + } else { + temp.value = value; + return false; + } + } while (temp != null); + + Entry newEntry = new Entry<>(key, value, parent); + + if (diff > 0) { + parent.right = newEntry; + } else { + parent.left = newEntry; + } + + size++; + return true; + } + + public Entry getEntry(K key) { + Entry temp = root; + + do { + int diff = compare(key, temp.key); + if (diff < 0) { + temp = temp.left; + } else if (diff > 0) { + temp = temp.right; + } else { + return temp; + } + } while (temp != null); + return null; + } + + @Override + public boolean remove(K key) { + Entry forRemove = getEntry(key); + if (forRemove == null) { + return false; + } + + size--; + + if (size == 1) { + if (root.key == key) { + root = null; + } + return true; + } + + if (forRemove.left == null && forRemove.right == null) { + return removeLeaf(forRemove); + } + + if (forRemove.right != null && forRemove.left == null) { + if (compare(forRemove.parent.key, forRemove.key) > 0) { + forRemove.parent.left = forRemove.right; + } else { + forRemove.parent.right = forRemove.right; + } + return true; + } else if (forRemove.right == null && forRemove.left != null) { + if (compare(forRemove.parent.key, forRemove.key) > 0) { + forRemove.parent.left = forRemove.left; + } else { + forRemove.parent.right = forRemove.left; + } + return true; + } + + removeWithTwoChildren(forRemove); + return true; + } + + private void removeWithTwoChildren(Entry forRemove) { + Entry lowestLeftChild; + Entry temp = forRemove.right; + + do { + lowestLeftChild = temp; + temp = temp.left; + } while (temp != null); + + lowestLeftChild.right = forRemove.right; + lowestLeftChild.left = forRemove.left; + + if (compare((forRemove.parent).key, forRemove.key) > 0) { + (forRemove.parent).left = lowestLeftChild; + } else { + (forRemove.parent).right = lowestLeftChild; + } + } + + private boolean removeLeaf(Entry forRemove) { + if (compare(forRemove.parent.key, forRemove.key) > 0) { + forRemove.parent.left = null; + } else { + forRemove.parent.right = null; + } + return true; + } + + @Override + public int size() { + return size; + } + + @Override + public boolean contains(K key) { + return getEntry(key) != null; + } + + private int compare(K k1, K k2) { + return comparator == null ? (k1).compareTo(k2) + : comparator.compare(k1, k2); + } + + private class Entry { + private final K key; + private V value; + private Entry left; + private Entry right; + private Entry parent; + + private Entry(K key, V value, Entry parent) { + this.key = key; + this.value = value; + this.parent = parent; + } + + @Override + public String toString() { + return "key = " + key + ", value = " + value; + } + } }