-
Notifications
You must be signed in to change notification settings - Fork 14
ДЗ 1, Симиютин Борис, подгруппа 2 #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 01-string-set
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,144 @@ | ||
| package ru.spbau.mit; | ||
|
|
||
| public class StringSetImpl implements StringSet { | ||
|
|
||
| private int size; | ||
| private Node root; | ||
|
|
||
| StringSetImpl() { | ||
| root = new Node('a'); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean add(String element) { | ||
|
|
||
| if (contains(element)) { | ||
| return false; | ||
| } | ||
|
|
||
| Node node = root; | ||
| for (char value : element.toCharArray()) { | ||
| Node child = node.getChild(value); | ||
| if (child == null) { | ||
| child = new Node(value); | ||
| child.parent = node; | ||
| node.addChild(child); | ||
|
|
||
| } | ||
| node.howManyStartsWithPrefix++; | ||
| node = child; | ||
| } | ||
|
|
||
| node.isFullWord = true; | ||
| node.howManyStartsWithPrefix++; | ||
| size++; | ||
|
|
||
| return true; | ||
|
|
||
| } | ||
|
|
||
| private Node findLastNode(String element) { | ||
|
|
||
| Node node = root; | ||
| for (char value : element.toCharArray()) { | ||
| Node child = node.getChild(value); | ||
| if (child == null) { | ||
| return null; | ||
| } | ||
| node = child; | ||
| } | ||
|
|
||
| return node; | ||
|
|
||
| } | ||
|
|
||
| @Override | ||
| public boolean contains(String element) { | ||
|
|
||
| Node node = findLastNode(element); | ||
|
|
||
| return node != null && node.isFullWord; | ||
| } | ||
|
|
||
| private int getIndexByChar(char value) { | ||
| final int asciiOffset = 65; | ||
| return value - asciiOffset; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean remove(String element) { | ||
|
|
||
| if (!contains(element)) { | ||
| return false; | ||
| } | ||
|
|
||
| Node lastNode = findLastNode(element); | ||
| lastNode.isFullWord = false; | ||
| lastNode.howManyStartsWithPrefix--; | ||
| size--; | ||
|
|
||
| char[] array = element.toCharArray(); | ||
| Node parent = lastNode.parent; | ||
|
|
||
| // decrement value on path to root | ||
| for (int i = element.length() - 1; i >= 0; i--) { | ||
| parent.howManyStartsWithPrefix--; | ||
| parent = parent.parent; | ||
| } | ||
|
|
||
| // delete unused prefix | ||
| if (lastNode.numberOfChildren == 0) { | ||
| parent = lastNode.parent; | ||
| for (int i = element.length() - 1; i >= 0; i--) { | ||
| parent.numberOfChildren--; | ||
| parent.children[getIndexByChar(array[i])] = null; | ||
| if (parent.isFullWord || parent.numberOfChildren > 0) { | ||
| break; | ||
| } | ||
| parent = parent.parent; | ||
| } | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| @Override | ||
| public int size() { | ||
| return size; | ||
| } | ||
|
|
||
| @Override | ||
| public int howManyStartsWithPrefix(String prefix) { | ||
| Node lastNode = findLastNode(prefix); | ||
| if (lastNode == null) { | ||
| return 0; | ||
| } | ||
| return lastNode.howManyStartsWithPrefix; | ||
| } | ||
|
|
||
| class Node { | ||
|
|
||
| private Node[] children; | ||
| private char value; | ||
| private int numberOfChildren; | ||
| private int howManyStartsWithPrefix; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Действительно, они полностью друг друга дублируют, и от одного поля можно избавиться |
||
| private boolean isFullWord; | ||
| private Node parent; | ||
|
|
||
|
|
||
| Node(char value) { | ||
| final int sizeOfFrameInAscii = 58; | ||
| this.value = value; | ||
| this.children = new Node[sizeOfFrameInAscii]; | ||
| } | ||
|
|
||
| Node getChild(char value) { | ||
| return children[getIndexByChar(value)]; | ||
| } | ||
|
|
||
| void addChild(final Node newChild) { | ||
| children[getIndexByChar(newChild.value)] = newChild; | ||
| numberOfChildren++; | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,11 +15,141 @@ public void testSimple() { | |
| assertTrue(stringSet.contains("abc")); | ||
| assertEquals(1, stringSet.size()); | ||
| assertEquals(1, stringSet.howManyStartsWithPrefix("abc")); | ||
| assertTrue(stringSet.remove("abc")); | ||
| assertTrue(!stringSet.contains("abc")); | ||
| } | ||
|
|
||
| @Test | ||
| public void moreGeneralTest() { | ||
| StringSet stringSet = instance(); | ||
|
|
||
| assertTrue(stringSet.add("A")); | ||
| assertTrue(stringSet.add("in")); | ||
| assertTrue(stringSet.add("inn")); | ||
| assertTrue(stringSet.add("to")); | ||
| assertTrue(stringSet.add("tea")); | ||
| assertTrue(stringSet.add("ted")); | ||
| assertTrue(stringSet.add("ten")); | ||
|
|
||
| assertTrue(stringSet.contains("A")); | ||
| assertTrue(stringSet.contains("to")); | ||
| assertTrue(stringSet.contains("tea")); | ||
| assertTrue(stringSet.contains("ted")); | ||
| assertTrue(stringSet.contains("ten")); | ||
| assertTrue(stringSet.contains("inn")); | ||
| assertTrue(stringSet.contains("in")); | ||
|
|
||
| final int size = 7; | ||
| assertTrue(stringSet.size() == size); | ||
|
|
||
| assertTrue(stringSet.howManyStartsWithPrefix("i") == 2); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. см assertEquals, в случае несовпадения он распечатает оба значения |
||
| assertTrue(stringSet.howManyStartsWithPrefix("in") == 2); | ||
| assertTrue(stringSet.howManyStartsWithPrefix("te") | ||
| == size - (size / 2) - 1); // :) | ||
|
|
||
| assertTrue(stringSet.remove("in")); | ||
|
|
||
| assertTrue(stringSet.size() == size - 1); | ||
| assertTrue(!stringSet.contains("in")); | ||
| assertTrue(stringSet.contains("inn")); | ||
| assertTrue(stringSet.howManyStartsWithPrefix("in") == 1); | ||
| assertTrue(stringSet.howManyStartsWithPrefix("te") | ||
| == size - (size / 2) - 1); | ||
| assertTrue(stringSet.howManyStartsWithPrefix("tea") == 1); | ||
| assertTrue(stringSet.howManyStartsWithPrefix("ted") == 1); | ||
| assertTrue(stringSet.howManyStartsWithPrefix("ten") == 1); | ||
|
|
||
| assertTrue(!stringSet.remove("te")); | ||
| assertTrue(stringSet.size() == size - 1); | ||
|
|
||
| assertTrue(stringSet.howManyStartsWithPrefix("te") | ||
| == size - (size / 2) - 1); | ||
| assertTrue(stringSet.howManyStartsWithPrefix("tea") == 1); | ||
| assertTrue(stringSet.howManyStartsWithPrefix("ted") == 1); | ||
| assertTrue(stringSet.howManyStartsWithPrefix("ten") == 1); | ||
|
|
||
| assertTrue(stringSet.remove("tea")); | ||
| assertTrue(stringSet.size() == size - 2); | ||
|
|
||
| assertTrue(stringSet.howManyStartsWithPrefix("te") == 2); | ||
| assertTrue(stringSet.howManyStartsWithPrefix("tea") == 0); | ||
| assertTrue(stringSet.howManyStartsWithPrefix("ted") == 1); | ||
| assertTrue(stringSet.howManyStartsWithPrefix("ten") == 1); | ||
|
|
||
| } | ||
|
|
||
| @Test | ||
| public void addContainsSizeRemoveSizeContains() { | ||
| StringSet stringSet = instance(); | ||
|
|
||
| stringSet.add("abc"); | ||
| stringSet.add("abd"); | ||
| stringSet.add("bcd"); | ||
|
|
||
| assertTrue(stringSet.contains("abc")); | ||
| assertTrue(stringSet.size() == 1 + 1 + 1); | ||
| assertTrue(stringSet.remove("abc")); | ||
| assertTrue(stringSet.size() == 2); | ||
| assertTrue(!stringSet.contains("abc")); | ||
| } | ||
|
|
||
| @Test | ||
| public void addContainsPrefixRemovePrefix() { | ||
| StringSet stringSet = instance(); | ||
|
|
||
| stringSet.add("abc"); | ||
| stringSet.add("abd"); | ||
| stringSet.add("bcd"); | ||
|
|
||
| assertTrue(stringSet.contains("abc")); | ||
| assertTrue(stringSet.howManyStartsWithPrefix("a") == 2); | ||
| assertTrue(stringSet.remove("abc")); | ||
| assertTrue(stringSet.howManyStartsWithPrefix("a") == 1); | ||
| } | ||
|
|
||
| @Test | ||
| public void doubleAdd() { | ||
| StringSet stringSet = instance(); | ||
| stringSet.add("helloWorldAndVeryLongStringAfter"); | ||
| stringSet.add("helloWorldAndVeryLongStringAfter"); | ||
| assertTrue(stringSet.size() == 1); | ||
| assertTrue(stringSet.howManyStartsWithPrefix("helloWorld") == 1); | ||
| } | ||
|
|
||
| @Test | ||
| public void doubleDelete() { | ||
| StringSet stringSet = instance(); | ||
| stringSet.add("helloWorldAndVeryLongStringAfter"); | ||
|
|
||
| assertTrue(stringSet.remove("helloWorldAndVeryLongStringAfter")); | ||
| assertTrue(!stringSet.remove("helloWorldAndVeryLongStringAfter")); | ||
|
|
||
| assertTrue(stringSet.size() == 0); | ||
| assertTrue(stringSet.howManyStartsWithPrefix("helloWorld") == 0); | ||
| } | ||
|
|
||
| @Test | ||
| public void emptyStringsTest() { | ||
| StringSet stringSet = instance(); | ||
|
|
||
| stringSet.add("abc"); | ||
| assertTrue(stringSet.howManyStartsWithPrefix("") == 1); | ||
| assertTrue(stringSet.add("")); | ||
| assertTrue(stringSet.howManyStartsWithPrefix("") == 2); | ||
| assertTrue(!stringSet.add("")); | ||
| assertTrue(stringSet.howManyStartsWithPrefix("") == 2); | ||
| assertTrue(stringSet.size() == 2); | ||
| assertTrue(stringSet.remove("")); | ||
| assertTrue(stringSet.size() == 1); | ||
| assertTrue(stringSet.contains("abc")); | ||
| } | ||
|
|
||
|
|
||
|
|
||
| public static StringSet instance() { | ||
| try { | ||
| return (StringSet) Class.forName("ru.spbau.mit.StringSetImpl").newInstance(); | ||
| return (StringSet) Class.forName("ru.spbau.mit.StringSetImpl") | ||
| .newInstance(); | ||
| } catch (InstantiationException e) { | ||
| e.printStackTrace(); | ||
| } catch (IllegalAccessException e) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
==
root.howMany...?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Да, и size тут не нужен