diff --git a/hw1/.idea/misc.xml b/hw1/.idea/misc.xml
new file mode 100644
index 0000000..0548357
--- /dev/null
+++ b/hw1/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/hw1/.idea/modules.xml b/hw1/.idea/modules.xml
new file mode 100644
index 0000000..9b27cd1
--- /dev/null
+++ b/hw1/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/hw1/hw1.iml b/hw1/hw1.iml
new file mode 100644
index 0000000..bf5ed58
--- /dev/null
+++ b/hw1/hw1.iml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/hw1/ru/spbau/solikov/hw1/src/HashTable.java b/hw1/ru/spbau/solikov/hw1/src/HashTable.java
new file mode 100644
index 0000000..f71fafd
--- /dev/null
+++ b/hw1/ru/spbau/solikov/hw1/src/HashTable.java
@@ -0,0 +1,157 @@
+package ru.spbau.solikov.hw1.src;
+
+/**
+ * Implementation of hash table structure using separate chaining
+ */
+public class HashTable {
+
+ /**
+ * Number used in hash function
+ */
+ private static final int DEFAULT_HASH_PRIME_NUMBER = 31;
+
+ private List[] table;
+ private int capacity = 2;
+ private int size;
+
+ /**
+ * Creates a HashTable of default capacity
+ */
+ public HashTable() {
+ table = new List[2];
+ size = 0;
+ }
+
+ /**
+ * Returns number of keys
+ *
+ * @return size
+ */
+ public int size() {
+ return size;
+ }
+
+
+ /**
+ * Iterates on each list in HashTable and clears it, capacity is the same
+ */
+ public void clear() {
+ for (List list : table) {
+ if (list != null) {
+ list.clear();
+ }
+ }
+ size = 0;
+ }
+
+ /**
+ * Hash function for obtaining a code from key
+ *
+ * @param key
+ * @return hash code
+ */
+ private int getHash(String key) {
+ int hash = 0;
+ for (int i = 0; i < key.length(); i++) {
+ hash = (DEFAULT_HASH_PRIME_NUMBER * hash + key.charAt(i)) % capacity;
+ }
+ return hash;
+ }
+
+ /**
+ * Returns data stored by key or null if not found
+ *
+ * @param key
+ * @return data or null if not found
+ */
+ public String get(String key) {
+ int hash = getHash(key);
+ if (table[hash] == null){
+ return null;
+ }
+ return table[hash].find(key);
+ }
+
+ /**
+ * Increases the capacity of HashTable by 2 times
+ */
+ private void increase() {
+ List[] oldTable = table;
+ table = new List[2 * capacity];
+ capacity *= 2;
+
+ for (List list : oldTable) {
+ if (list != null) {
+ while (!list.isEmpty()) {
+ String key = list.getHeadsKey();
+ int hash = getHash(key);
+ if (table[hash] == null) {
+ table[hash] = new List();
+ }
+ table[hash].insert(key, list.getHeadsData());
+ list.delete(key);
+ }
+ }
+ }
+ }
+
+ /**
+ * Allows to add the pair of key and data into HashTable, if there's not enough space calls increase()
+ *
+ * @param key
+ * @param data
+ * @return data that was stored before by the same key or null if this space was empty
+ */
+ public String put(String key, String data) {
+ int hash = getHash(key);
+ if (table[hash] == null) {
+ table[hash] = new List();
+ }
+
+ List current = table[hash];
+ String deleted = current.delete(key);
+ current.insert(key, data);
+
+ if (deleted == null) {
+ size++;
+ }
+
+ if (size >= capacity) {
+ increase();
+ }
+
+ return deleted;
+ }
+
+ /**
+ * Allows to remove data stored by key
+ *
+ * @param key
+ * @return data stored by key
+ */
+ public String remove(String key) {
+ int hash = getHash(key);
+
+ if (table[hash] == null) {
+ return null;
+ }
+
+ String deleted = table[hash].delete(key);
+ if (deleted != null) {
+ size--;
+ return deleted;
+ }
+
+ return null;
+ }
+
+ /**
+ * Checks whether HashTable contains some data by passed key
+ *
+ * @param key
+ * @return data or null if the HashTable doesn't contain key
+ */
+ public boolean contains(String key) {
+ return get(key) != null;
+ }
+}
diff --git a/hw1/ru/spbau/solikov/hw1/src/List.java b/hw1/ru/spbau/solikov/hw1/src/List.java
new file mode 100644
index 0000000..04f8d48
--- /dev/null
+++ b/hw1/ru/spbau/solikov/hw1/src/List.java
@@ -0,0 +1,121 @@
+package ru.spbau.solikov.hw1.src;
+
+/**
+ * Implementation of single-linked list that stores Nodes of keys and data
+ */
+public class List {
+
+ /**
+ * Class that stores keys and data and has link for next Node
+ */
+ private class Node {
+
+ private Node next;
+
+ private String key;
+
+ private String data;
+
+ public Node(Node n, String k, String d) {
+ next = n;
+ key = k;
+ data = d;
+ }
+ }
+
+ private Node head;
+
+ private Node tail;
+
+ public Node getHead() {
+ return head;
+ }
+
+ /**
+ * Adds a pair of key and data in List
+ *
+ * @param key
+ * @param data
+ */
+ public void insert(String key, String data) {
+ if (head != null) {
+ tail.next = new Node(null, key, data);
+ tail = tail.next;
+ } else {
+ tail = head = new Node(null, key, data);
+ }
+ }
+
+ /**
+ * Checks if the list does not contain any elements
+ *
+ * @return boolean - true if the list is empty
+ */
+ public boolean isEmpty() {
+ return head == null;
+ }
+
+ /**
+ * Searches for data by key in List
+ *
+ * @param key
+ * @return data or null if not found
+ */
+ public String find(String key) {
+ Node current = head;
+ while (current != null) {
+ if (current.key.equals(key)) {
+ return current.data;
+ }
+ current = current.next;
+ }
+
+ return null;
+ }
+
+ public String getHeadsKey() {
+ return head.key;
+ }
+
+ public String getHeadsData() {
+ return head.data;
+ }
+
+ /**
+ * Deletes a data stored by key in List
+ *
+ * @param key
+ * @return data that was deleted
+ */
+ public String delete(String key) {
+ if (head == null) {
+ return null;
+ }
+
+ if (head.key.equals(key)) {
+ String deleted = head.data;
+ head = head.next;
+ return deleted;
+ }
+
+ Node current = head;
+ while (current.next != null) {
+ if (current.next.key.equals(key)) {
+ String deleted = current.next.data;
+ current.next = current.next.next;
+ return deleted;
+ }
+ current = current.next;
+ }
+
+ return null;
+ }
+
+ /**
+ * Clears the List
+ */
+ public void clear() {
+ head = null;
+ tail = null;
+ }
+}
diff --git a/hw1/ru/spbau/solikov/hw1/src/primitive/test/HashTableTest.java b/hw1/ru/spbau/solikov/hw1/src/primitive/test/HashTableTest.java
new file mode 100644
index 0000000..6a881ca
--- /dev/null
+++ b/hw1/ru/spbau/solikov/hw1/src/primitive/test/HashTableTest.java
@@ -0,0 +1,41 @@
+package ru.spbau.solikov.hw1.src.primitive.test;
+
+import ru.spbau.solikov.hw1.src.HashTable;
+
+/**
+ * Class for testing all the HashTable functions
+ */
+
+public class HashTableTest {
+ public static void main(String[] args) {
+ HashTable hashTable = new HashTable();
+
+ for (int i = 0; i < 100; i++){
+ hashTable.put(String.valueOf(i), String.valueOf(i * i));
+ }
+
+ System.out.println(hashTable.size() + " - size of hashtable (must be 100)");
+
+ System.out.println();
+
+ System.out.println(hashTable.get("10") + " - square of 10 (must be 100)");
+
+ System.out.println();
+
+ System.out.println(hashTable.put("10", "200") + " - changed square of 10 (must have been 100)");
+
+ System.out.println();
+
+ System.out.println(hashTable.contains("10") + " - contains '10' (must be true)");
+
+ System.out.println();
+
+ System.out.println(hashTable.remove("10") + " - removed '10'");
+
+ System.out.println();
+
+ hashTable.clear();
+
+ System.out.println(hashTable.size() + " - size of hashtable (must be 0)");
+ }
+}
diff --git a/hw1/ru/spbau/solikov/hw1/src/primitive/test/ListTest.java b/hw1/ru/spbau/solikov/hw1/src/primitive/test/ListTest.java
new file mode 100644
index 0000000..be54d90
--- /dev/null
+++ b/hw1/ru/spbau/solikov/hw1/src/primitive/test/ListTest.java
@@ -0,0 +1,29 @@
+package ru.spbau.solikov.hw1.src.primitive.test;
+
+import ru.spbau.solikov.hw1.src.List;
+
+/**
+ * Class for testing all the List functions
+ */
+
+public class ListTest {
+ public static void main(String[] args) {
+ List l = new List();
+
+ for (int i = 0; i < 10; i++) {
+ l.insert(String.valueOf(i), String.valueOf(i));
+ }
+
+ System.out.println();
+
+ System.out.println(l.find("5") + " - found key '5'.");
+ l.delete("5");
+ System.out.println(l.delete("5") + " - deleted key '5'.");
+
+ System.out.println();
+
+ l.clear();
+ System.out.print(l.getHead() == null);
+ System.out.println(" - cleared the list.");
+ }
+}
diff --git a/hw1/ru/spbau/solikov/hw1/test/HashTableTest.java b/hw1/ru/spbau/solikov/hw1/test/HashTableTest.java
new file mode 100644
index 0000000..958c53d
--- /dev/null
+++ b/hw1/ru/spbau/solikov/hw1/test/HashTableTest.java
@@ -0,0 +1,41 @@
+package ru.spbau.solikov.hw1.src.primitive.test;
+
+import ru.spbau.solikov.hw1.src.HashTable;
+
+/**
+ * Class for testing all the HashTable functions
+ */
+
+public class HashTableTest {
+ public static void main(String[] args) {
+ HashTable hashTable = new HashTable();
+
+ for (int i = 0; i < 100; i++){
+ hashTable.put(String.valueOf(i), String.valueOf(i * i));
+ }
+
+ System.out.println(hashTable.size() + " - size of hashtable (must be 100)");
+
+ System.out.println();
+
+ System.out.println(hashTable.get("10") + " - square of 10 (must be 100)");
+
+ System.out.println();
+
+ System.out.println(hashTable.put("10", "200") + " - changed square of 10 (must have been 100)");
+
+ System.out.println();
+
+ System.out.println(hashTable.contains("10") + " - contains '10' (must be true)");
+
+ System.out.println();
+
+ System.out.println(hashTable.remove("10") + " - removed '10'");
+
+ System.out.println();
+
+ hashTable.clear();
+
+ System.out.println(hashTable.size() + " - size of hashtable (must be 0)");
+ }
+}
\ No newline at end of file
diff --git a/hw1/ru/spbau/solikov/hw1/test/HashTableUnitTest.java b/hw1/ru/spbau/solikov/hw1/test/HashTableUnitTest.java
new file mode 100644
index 0000000..f7d5d17
--- /dev/null
+++ b/hw1/ru/spbau/solikov/hw1/test/HashTableUnitTest.java
@@ -0,0 +1,253 @@
+package ru.spbau.solikov.hw1.src.primitive.test;
+
+import org.junit.Before;
+import org.junit.Test;
+import ru.spbau.solikov.hw1.src.HashTable;
+
+import static org.junit.Assert.*;
+
+/**
+ * Test class for HashTable with separate chaining
+ */
+public class HashTableTest {
+
+ private HashTable table;
+
+ /**
+ * Constructs new hash table for every test
+ */
+ @Before
+ public void setUp() {
+ table = new HashTable();
+ }
+
+ /**
+ * Tests if the size of empty table is 0
+ */
+ @Test
+ public void testSizeOfEmptyHashTable() {
+ assertEquals(0, table.size());
+ }
+
+ /**
+ * Tests if 'put' puts the right key
+ */
+ @Test
+ public void testPut() {
+ table.put("27", "09");
+ assertEquals(true, table.contains("27"));
+ }
+
+ /**
+ * Tests if the size after many 'puts' is correct
+ */
+ @Test
+ public void testSizeAfterPut() {
+ for (int i = 0; i < 10; i++) {
+ table.put(String.valueOf(i), String.valueOf(i));
+ }
+ assertEquals(10, table.size());
+ }
+
+ /**
+ * Tests if the size after 'put' in the same key is correct
+ */
+ @Test
+ public void testSizeAfterPutExistingKey() {
+ table.put("123", "321");
+ table.put("123", "333");
+ assertEquals(1, table.size());
+ }
+
+ /**
+ * Tests if 'put' inserts new value instead of previous
+ */
+ @Test
+ public void testPutExistingKey() {
+ for (int i = 0; i < 10; i++) {
+ table.put(String.valueOf(i), String.valueOf(i));
+ }
+ table.put("4", "99");
+ assertEquals("99", table.get("4"));
+ }
+
+ /**
+ * Tests if 'size' on empty table is 0
+ */
+ @Test
+ public void testClearEmpty() {
+ table.clear();
+ assertEquals(0, table.size());
+ }
+
+ /**
+ * Tests if 'clear' works right on table with many keys
+ */
+ @Test
+ public void testClear() {
+ for (int i = 0; i < 10; i++) {
+ table.put(String.valueOf(i), String.valueOf(i));
+ }
+ table.clear();
+ assertEquals(0, table.size());
+ }
+
+ /**
+ * Tests if 'get' from empty table returns null
+ */
+ @Test
+ public void testGetFromEmpty() {
+ assertEquals(null, table.get("Deadline"));
+ }
+
+ /**
+ * Tests if 'get' from one-element table returns the right value
+ */
+ @Test
+ public void testGetElementFromOneElementTable() {
+ table.put("1", "2");
+ assertEquals("2", table.get("1"));
+ }
+
+ /**
+ * Tests if 'get' on many-element table returns the right value
+ */
+ @Test
+ public void testGetElementFromManyElementTable() {
+ for (int i = 0; i < 10; i++) {
+ table.put(String.valueOf(i), String.valueOf(i));
+ }
+ assertEquals("5", table.get("5"));
+ }
+
+ /**
+ * Tests if 'get' does not change the size of hash table
+ */
+ @Test
+ public void testGetDoesNotChangeSize() {
+ for (int i = 0; i < 10; i++) {
+ table.put(String.valueOf(i), String.valueOf(i));
+ }
+ table.get("5");
+ assertEquals(10, table.size());
+ }
+
+ /**
+ * Tests if 'remove' does nothing with table after removing from empty table
+ */
+ @Test
+ public void testSizeAfterRemovingFromEmptyTable() {
+ table.remove("123");
+ assertEquals(0, table.size());
+ }
+
+ /**
+ * Tests if 'remove' on empty table returns null
+ */
+ @Test
+ public void testRemoveFromEmptyTable() {
+ assertEquals(null, table.remove("123"));
+ }
+
+ /**
+ * Tests if 'remove' on one-element table returns the right value
+ */
+ @Test
+ public void testRemoveFromOneElementTable() {
+ table.put("123", "321");
+ assertEquals("321", table.get("123"));
+ }
+
+ /**
+ * Tests if the size of table becomes zero after removing from one-element table
+ */
+ @Test
+ public void testSizeAfterRemovingFromOneElementTable() {
+ table.put("123", "321");
+ table.remove("123");
+ assertEquals(0, table.size());
+ }
+
+ /**
+ * Tests if the size of hash table is not affected by removing element that does not exist
+ */
+ @Test
+ public void testSizeAfterRemovingNonexistingFromManyElementTable() {
+ for (int i = 0; i < 10; i++) {
+ table.put(String.valueOf(i), String.valueOf(i));
+ }
+ table.remove("100");
+ assertEquals(10, table.size());
+ }
+
+ /**
+ * Tests if size after removing existing element decreases
+ */
+ @Test
+ public void testSizeAfterRemoveFromManyElementTable() {
+ for (int i = 0; i < 10; i++) {
+ table.put(String.valueOf(i), String.valueOf(i));
+ }
+ table.remove("5");
+ assertEquals(9, table.size());
+ }
+
+ /**
+ * Tests if 'remove' from many-element table returns the right value
+ */
+ @Test
+ public void testRemoveFromManyElementTable() {
+ for (int i = 0; i < 10; i++) {
+ table.put(String.valueOf(i), String.valueOf(i));
+ }
+ assertEquals("4", table.remove("4"));
+ }
+
+ /**
+ * Tests if 'contains' returns false on empty table
+ */
+ @Test
+ public void testContainsFromEmptyTable() {
+ assertEquals(false, table.contains("some"));
+ }
+
+ /**
+ * Tests if 'contains' returns true on element that exists in one-element table
+ */
+ @Test
+ public void testContainsFromOneElementTable() {
+ table.put("Wednesday", "27.09");
+ assertEquals(true, table.contains("Wednesday"));
+ }
+
+ /**
+ * Tests if 'contains' returns false on element that does not exist in one-element table
+ */
+ @Test
+ public void testContainsNonexistingElementFromOneElementTable() {
+ table.put("Wednesday", "27.09");
+ assertEquals(false, table.contains("Sunday"));
+ }
+
+ /**
+ * Tests if 'contains' returns true on many-element table
+ */
+ @Test
+ public void testContainsManyElementTable() {
+ for (int i = 0; i < 10; i++) {
+ table.put(String.valueOf(i), String.valueOf(i));
+ }
+ assertEquals(true, table.contains("4"));
+ }
+
+ /**
+ * Tests if 'contains' returns false on elements that don't exist in many-element table
+ */
+ @Test
+ public void testContainsNonexistingElementFromManyElementTable() {
+ for (int i = 0; i < 10; i++) {
+ table.put(String.valueOf(i), String.valueOf(i));
+ }
+ assertEquals(false, table.contains("123"));
+ }
+}
\ No newline at end of file
diff --git a/hw1/ru/spbau/solikov/hw1/test/ListTest.java b/hw1/ru/spbau/solikov/hw1/test/ListTest.java
new file mode 100644
index 0000000..b3f6b75
--- /dev/null
+++ b/hw1/ru/spbau/solikov/hw1/test/ListTest.java
@@ -0,0 +1,29 @@
+package ru.spbau.solikov.hw1.src.primitive.test;
+
+import ru.spbau.solikov.hw1.src.List;
+
+/**
+ * Class for testing all the List functions
+ */
+
+public class ListTest {
+ public static void main(String[] args) {
+ List l = new List();
+
+ for (int i = 0; i < 10; i++) {
+ l.insert(String.valueOf(i), String.valueOf(i));
+ }
+
+ System.out.println();
+
+ System.out.println(l.find("5") + " - found key '5'.");
+ l.delete("5");
+ System.out.println(l.delete("5") + " - deleted key '5'.");
+
+ System.out.println();
+
+ l.clear();
+ System.out.print(l.getHead() == null);
+ System.out.println(" - cleared the list.");
+ }
+}
\ No newline at end of file
diff --git a/hw1/ru/spbau/solikov/hw1/test/ListUnitTest.java b/hw1/ru/spbau/solikov/hw1/test/ListUnitTest.java
new file mode 100644
index 0000000..db8c8f1
--- /dev/null
+++ b/hw1/ru/spbau/solikov/hw1/test/ListUnitTest.java
@@ -0,0 +1,127 @@
+package ru.spbau.solikov.hw1.src.primitive.test;
+
+import org.junit.Before;
+import org.junit.Test;
+import ru.spbau.solikov.hw1.src.List;
+
+import static org.junit.Assert.*;
+
+/**
+ * Test class for class List that implements single-linked list
+ */
+public class ListTest {
+
+ private List l;
+
+ /**
+ * Constructs new list for every test
+ */
+ @Before
+ public void setUp() {
+ l = new List();
+ }
+
+ /**
+ * Tests if 'isEmpty' on empty list returns true
+ */
+ @Test
+ public void testIsEmptyOfEmptyList() {
+ assertEquals(true, l.isEmpty());
+ }
+
+ /**
+ * Tests if 'insert' on empty list inserts the right data
+ */
+ @Test
+ public void testInsert() {
+ l.insert("SPbAU", "Java");
+ assertEquals("Java", l.getHeadsData());
+ }
+
+ /**
+ * Tests if many 'insert's insert the right data
+ */
+ @Test
+ public void testManyInserts() {
+ for (int i = 0; i < 10; i++) {
+ l.insert(String.valueOf(i), String.valueOf(i));
+ }
+
+ int number = 0;
+ while (!l.isEmpty()) {
+ assertEquals(Integer.toString(number), l.getHeadsData());
+ number++;
+ l.delete(l.getHeadsKey());
+ }
+ }
+
+ /**
+ * Tests if 'find' on empty list returns null
+ */
+ @Test
+ public void testFindNonexistingElement() {
+ assertEquals(null, l.find("Something"));
+ }
+
+ /**
+ * Tests if 'find' on one-element list returns right value
+ */
+ @Test
+ public void testFindExistingElement() {
+ l.insert("SPbAU", "Java");
+ assertEquals("Java", l.find("SPbAU"));
+ }
+
+ /**
+ * Tests if 'find' on many-element list returns right value
+ */
+ @Test
+ public void testFindExistingElementManyElements() {
+ for (int i = 0; i < 10; i++) {
+ l.insert(String.valueOf(i), String.valueOf(i));
+ }
+ l.insert("SPbAU", "Java");
+ assertEquals("Java", l.find("SPbAU"));
+ }
+
+ /**
+ * Tests if 'delete' on empty list does nothing
+ */
+ @Test
+ public void testDeleteElementFromEmptyList() {
+ l.delete("SomeKey");
+ assertEquals(true, l.isEmpty());
+ }
+
+ /**
+ * Tests if 'delete' nonexisting element on one-element list does nothing
+ */
+ @Test
+ public void testDeleteNonexistingElement() {
+ l.insert("1", "2");
+ l.delete("5");
+ assertNotEquals(true, l.isEmpty());
+ }
+
+ /**
+ * Tests if 'delete' from one-element list truly deletes element
+ */
+ @Test
+ public void testDeleteExistingElement() {
+ l.insert("SPbAU", "Java");
+ l.delete("SPbAU");
+ assertEquals(true, l.isEmpty());
+ }
+
+ /**
+ * Tests if 'clear' deletes all elements from many-element list
+ */
+ @Test
+ public void testClear() {
+ for (int i = 0; i < 10; i++) {
+ l.insert(String.valueOf(i), String.valueOf(i));
+ }
+ l.clear();
+ assertEquals(true, l.isEmpty());
+ }
+}
\ No newline at end of file