From ffc7278f565f076254bbf7bb1b0d7e3c1c655436 Mon Sep 17 00:00:00 2001 From: Georgy S Date: Sat, 15 Apr 2023 17:42:33 +0300 Subject: [PATCH 01/84] refactor: Separate tests for TreeStructs into different files. --- lib/src/test/kotlin/treelib/AVLStructTest.kt | 18 + lib/src/test/kotlin/treelib/BINStructTest.kt | 474 ++++++++++++++++ lib/src/test/kotlin/treelib/RBStructTree.kt | 18 + .../test/kotlin/treelib/TreeStructsTest.kt | 513 ------------------ 4 files changed, 510 insertions(+), 513 deletions(-) create mode 100644 lib/src/test/kotlin/treelib/AVLStructTest.kt create mode 100644 lib/src/test/kotlin/treelib/BINStructTest.kt create mode 100644 lib/src/test/kotlin/treelib/RBStructTree.kt delete mode 100644 lib/src/test/kotlin/treelib/TreeStructsTest.kt diff --git a/lib/src/test/kotlin/treelib/AVLStructTest.kt b/lib/src/test/kotlin/treelib/AVLStructTest.kt new file mode 100644 index 0000000..00215f2 --- /dev/null +++ b/lib/src/test/kotlin/treelib/AVLStructTest.kt @@ -0,0 +1,18 @@ +package treelib + +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.DisplayName +import treelib.avlTree.AVLNode +import treelib.avlTree.AVLStateContainer +import treelib.avlTree.AVLStruct + +@DisplayName("Test: AVL Struct") +class AVLStructTest { + val treeW = TreeStructWrapper, AVLStateContainer, AVLStruct>() + var classUnderTest = AVLStruct() + + @BeforeEach + fun reInitClassUnderTest() { + classUnderTest = AVLStruct() + } +} \ No newline at end of file diff --git a/lib/src/test/kotlin/treelib/BINStructTest.kt b/lib/src/test/kotlin/treelib/BINStructTest.kt new file mode 100644 index 0000000..194096e --- /dev/null +++ b/lib/src/test/kotlin/treelib/BINStructTest.kt @@ -0,0 +1,474 @@ +package treelib + +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import treelib.binTree.BINNode +import treelib.binTree.BINStateContainer +import treelib.binTree.BINStruct +import kotlin.test.assertEquals + +@DisplayName("Test: Binary Search Tree Struct") +class BINStructTest { + val treeW = TreeStructWrapper, BINStateContainer, BINStruct>() + var classUnderTest = BINStruct() + + @BeforeEach + fun reInitClassUnderTest() { + classUnderTest = BINStruct() + } + + @Test + fun `test delete root`() { + val num = mutableListOf(5, 3, 7, 1, 9, -1, 4, 2, 0, 6) + for (i in num) { + classUnderTest.insert(i) + } + classUnderTest.delete(5) + val root = treeW.getPrivateNode(classUnderTest)?.value + + assertEquals(expected = 6, actual = root) + } + + @Test + fun `test insert`() { + val num = mutableListOf(1, 2, 3, 4, 5, 8) + for (i in num) { + classUnderTest.insert(i) + } + + val additional_num = mutableListOf(1, 2, 3, 5, 7, 8, 11) + for (i in additional_num) { + classUnderTest.insert(i) + } + + val root = treeW.getPrivateNode(classUnderTest)?.value + val node_2 = treeW.getPrivateNode(classUnderTest)?.right?.value + val node_null = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_3 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value + val node_null1 = treeW.getPrivateNode(classUnderTest)?.right?.left?.value + val node_4 = treeW.getPrivateNode(classUnderTest)?.right?.right?.right?.value + + assertEquals(expected = root, actual = 1) + assertEquals(expected = node_null, actual = null) + assertEquals(expected = node_4, actual = 4) + assertEquals(expected = node_2, actual = 2) + assertEquals(expected = node_3, actual = 3) + assertEquals(expected = node_null1, actual = null) + } + + @Test + fun `test find ordinary`() { + val num = mutableListOf(2, 3, 1, 4, 5, 10) + + assertEquals(expected = classUnderTest.find(2), actual = null) + + for (i in num) { + classUnderTest.insert(i) + } + + assertEquals(expected = classUnderTest.find(2), actual = 2) + } + + @Test + fun `test find null`() { + val num = mutableListOf(1) + classUnderTest.insert(num[0]) + + assertEquals(classUnderTest.find(2), null) + + } + + @Test + fun `test find root`() { + val num = mutableListOf(1) + classUnderTest.insert(num[0]) + + assertEquals(classUnderTest.find(1), 1) + } + + @Test + fun `test insert and delete root`() { + val num = mutableListOf(1, 2) + for (i in num) { + classUnderTest.insert(i) + } + + classUnderTest.delete(1) + + val additional_num = mutableListOf(1, 2, 11) + for (i in additional_num) { + classUnderTest.insert(i) + } + + val root = treeW.getPrivateNode(classUnderTest)?.value + val node_1 = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_11 = treeW.getPrivateNode(classUnderTest)?.right?.value + + + assertEquals(expected = root, actual = 2) + assertEquals(expected = node_1, actual = 1) + assertEquals(expected = node_11, actual = 11) + } + + @Test + fun `test delete nonexistent value right`() { + val num = mutableListOf(5, 6) + for (value in num) { + classUnderTest.insert(value) + } + classUnderTest.delete(6) + + val root = treeW.getPrivateNode(classUnderTest)?.value + val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.value + + assertEquals(expected = null, actual = node_null_left) + assertEquals(expected = null, actual = node_null_right) + assertEquals(expected = 5, actual = root) + } + + @Test + fun `test delete nonexistent value left`() { + val num = mutableListOf(6, 5) + for (value in num) { + classUnderTest.insert(value) + } + classUnderTest.delete(5) + + val root = treeW.getPrivateNode(classUnderTest)?.value + val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.value + + assertEquals(expected = null, actual = node_null_left) + assertEquals(expected = null, actual = node_null_right) + assertEquals(expected = 6, actual = root) + } + + @Test + fun `test delete no child root`() { + val num = mutableListOf(3) + for (i in num) { + classUnderTest.insert(i) + } + classUnderTest.delete(3) + + val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.value + val root = treeW.getPrivateNode(classUnderTest)?.value + + assertEquals(expected = null, actual = node_null_left) + assertEquals(expected = null, actual = node_null_right) + assertEquals(expected = null, actual = root) + } + + @Test + fun `test delete no child right`() { + val num = mutableListOf(3, 10, 15) + for (i in num) { + classUnderTest.insert(i) + } + classUnderTest.delete(15) + + val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.value + val node_null_left = treeW.getPrivateNode(classUnderTest)?.right?.left?.value + val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.right?.value + val root = treeW.getPrivateNode(classUnderTest)?.value + + + assertEquals(expected = 10, actual = node_10) + assertEquals(expected = null, actual = node_null_left) + assertEquals(expected = null, actual = node_null_right) + assertEquals(expected = 3, actual = root) + } + + @Test + fun `test delete no child left`() { + val num = mutableListOf(15, 10, 3) + for (i in num) { + classUnderTest.insert(i) + } + classUnderTest.delete(3) + + val node_10 = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.left?.value + val node_null_right = treeW.getPrivateNode(classUnderTest)?.left?.right?.value + val root = treeW.getPrivateNode(classUnderTest)?.value + + + assertEquals(expected = 10, actual = node_10) + assertEquals(expected = null, actual = node_null_left) + assertEquals(expected = null, actual = node_null_right) + assertEquals(expected = 15, actual = root) + } + + @Test + fun `test delete one child left`() { + val num = mutableListOf(3, 2, 1, 5) + for (value in num) { + classUnderTest.insert(value) + } + classUnderTest.delete(2) + + val node_1 = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.left?.value + val node_null_right = treeW.getPrivateNode(classUnderTest)?.left?.right?.value + val root = treeW.getPrivateNode(classUnderTest)?.value + + assertEquals(expected = 1, actual = node_1) + assertEquals(expected = null, actual = node_null_left) + assertEquals(expected = null, actual = node_null_right) + assertEquals(expected = 3, actual = root) + } + + @Test + fun `test delete one child right`() { + val num = mutableListOf(3, 1, 5, 6) + for (value in num) { + classUnderTest.insert(value) + } + classUnderTest.delete(5) + + val node_6 = treeW.getPrivateNode(classUnderTest)?.right?.value + val node_null_left = treeW.getPrivateNode(classUnderTest)?.right?.left?.value + val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.right?.value + val root = treeW.getPrivateNode(classUnderTest)?.value + + assertEquals(expected = 6, actual = node_6) + assertEquals(expected = null, actual = node_null_left) + assertEquals(expected = null, actual = node_null_right) + assertEquals(expected = 3, actual = root) + } + + @Test + fun `test delete one child root`() { + val num = mutableListOf(3, 6) + for (value in num) { + classUnderTest.insert(value) + } + classUnderTest.delete(3) + + val node_6 = treeW.getPrivateNode(classUnderTest)?.value + val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.value + + assertEquals(expected = 6, actual = node_6) + assertEquals(expected = null, actual = node_null_left) + assertEquals(expected = null, actual = node_null_right) + } + + @Test + fun `test delete one child with family`() { + val num = mutableListOf(10, 7, 13, 6, 3, 1, 5, 2, 4, 15) + for (value in num) { + classUnderTest.insert(value) + } + classUnderTest.delete(7) + val node_6 = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_3 = treeW.getPrivateNode(classUnderTest)?.left?.left?.value + val node_null_right = treeW.getPrivateNode(classUnderTest)?.left?.right?.value + val node_1 = treeW.getPrivateNode(classUnderTest)?.left?.left?.left?.value + val node_2 = treeW.getPrivateNode(classUnderTest)?.left?.left?.left?.right?.value + val node_5 = treeW.getPrivateNode(classUnderTest)?.left?.left?.right?.value + val node_4 = treeW.getPrivateNode(classUnderTest)?.left?.left?.right?.left?.value + val root = treeW.getPrivateNode(classUnderTest)?.value + + assertEquals(expected = 6, actual = node_6) + assertEquals(expected = 3, actual = node_3) + assertEquals(expected = null, actual = node_null_right) + assertEquals(expected = 1, actual = node_1) + assertEquals(expected = 2, actual = node_2) + assertEquals(expected = 5, actual = node_5) + assertEquals(expected = 4, actual = node_4) + assertEquals(expected = 10, actual = root) + } + + @Test + fun `test delete two child only three element`() { + val num = mutableListOf(2, 1, 3) + for (i in num) { + classUnderTest.insert(i) + } + classUnderTest.delete(2) + + val root = treeW.getPrivateNode(classUnderTest)?.value + val node_1 = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_null_left1 = treeW.getPrivateNode(classUnderTest)?.left?.left?.value + val node_null_right1 = treeW.getPrivateNode(classUnderTest)?.left?.right?.value + val node_null_right_root = treeW.getPrivateNode(classUnderTest)?.right?.value + + assertEquals(expected = root, actual = 3) + assertEquals(expected = node_1, actual = 1) + assertEquals(expected = node_null_left1, actual = null) + assertEquals(expected = node_null_right1, actual = null) + assertEquals(expected = node_null_right_root, actual = null) + } + + @Test + fun `test delete two child without family`() { + val num = mutableListOf(10, 7, 5, 4, 6) + for (i in num) { + classUnderTest.insert(i) + } + classUnderTest.delete(7) + + val root = treeW.getPrivateNode(classUnderTest)?.value + val node_5 = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_4 = treeW.getPrivateNode(classUnderTest)?.left?.left?.value + val node_6 = treeW.getPrivateNode(classUnderTest)?.left?.right?.value + val node_null_left4 = treeW.getPrivateNode(classUnderTest)?.left?.left?.left?.value + val node_null_right4 = treeW.getPrivateNode(classUnderTest)?.left?.left?.right?.value + val node_null_left6 = treeW.getPrivateNode(classUnderTest)?.left?.right?.left?.value + val node_null_right6 = treeW.getPrivateNode(classUnderTest)?.left?.right?.left?.value + + assertEquals(expected = root, actual = 10) + assertEquals(expected = node_5, actual = 5) + assertEquals(expected = node_4, actual = 4) + assertEquals(expected = node_6, actual = 6) + assertEquals(expected = node_null_left4, actual = null) + assertEquals(expected = node_null_right4, actual = null) + assertEquals(expected = node_null_left6, actual = null) + assertEquals(expected = node_null_right6, actual = null) + } + + @Test + fun `test two child double delete and delete root`() { + val num = mutableListOf(6, 8, 10, 7) + for (i in num) { + classUnderTest.insert(i) + } + + classUnderTest.delete(6) + classUnderTest.delete(7) + + val root = treeW.getPrivateNode(classUnderTest)?.value + val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.value + val node_null_right10 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value + val node_null_left10 = treeW.getPrivateNode(classUnderTest)?.right?.left?.value + + assertEquals(expected = root, actual = 8) + assertEquals(expected = node_10, actual = 10) + assertEquals(expected = node_null_left10, actual = null) + assertEquals(expected = node_null_right10, actual = null) + assertEquals(expected = node_null_left, actual = null) + } + + @Test + fun `test two child delete min element in right tree`() { + val num = mutableListOf(6, 8, 10, 7, 12, 9) + for (i in num) { + classUnderTest.insert(i) + } + + classUnderTest.delete(8) + + val root = treeW.getPrivateNode(classUnderTest)?.value + val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_9 = treeW.getPrivateNode(classUnderTest)?.right?.value + val node_7 = treeW.getPrivateNode(classUnderTest)?.right?.left?.value + val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value + val node_12 = treeW.getPrivateNode(classUnderTest)?.right?.right?.right?.value + val node_null = treeW.getPrivateNode(classUnderTest)?.right?.right?.left?.value + + assertEquals(expected = root, actual = 6) + assertEquals(expected = node_9, actual = 9) + assertEquals(expected = node_null, actual = null) + assertEquals(expected = node_null_left, actual = null) + assertEquals(expected = node_7, actual = 7) + assertEquals(expected = node_10, actual = 10) + assertEquals(expected = node_12, actual = 12) + } + + @Test + fun `test two child delete min element in right tree for root`() { + val num = mutableListOf(8, 10, 7, 12, 9) + for (i in num) { + classUnderTest.insert(i) + } + + classUnderTest.delete(8) + + val root = treeW.getPrivateNode(classUnderTest)?.value + val node_7 = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.value + val node_12 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value + val node_null = treeW.getPrivateNode(classUnderTest)?.right?.left?.value + + assertEquals(expected = root, actual = 9) + assertEquals(expected = node_null, actual = null) + assertEquals(expected = node_7, actual = 7) + assertEquals(expected = node_10, actual = 10) + assertEquals(expected = node_12, actual = 12) + } + + @Test + fun `test two child delete min element in right tree for rightmost element`() { + val num = mutableListOf(8, 10, 7, 12, 13, 14) + for (i in num) { + classUnderTest.insert(i) + } + + classUnderTest.delete(8) + + val root = treeW.getPrivateNode(classUnderTest)?.value + val node_7 = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_12 = treeW.getPrivateNode(classUnderTest)?.right?.value + val node_13 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value + val node_14 = treeW.getPrivateNode(classUnderTest)?.right?.right?.right?.value + val node_null = treeW.getPrivateNode(classUnderTest)?.right?.left?.value + + assertEquals(expected = root, actual = 10) + assertEquals(expected = node_null, actual = null) + assertEquals(expected = node_7, actual = 7) + assertEquals(expected = node_13, actual = 13) + assertEquals(expected = node_14, actual = 14) + assertEquals(expected = node_12, actual = 12) + } + + @Test + fun `test two child delete min element in right tree but in Tree`() { + val num = mutableListOf(8, 12, 15, 13, 10, 11, 9) + for (i in num) { + classUnderTest.insert(i) + } + + classUnderTest.delete(12) + + val root = treeW.getPrivateNode(classUnderTest)?.value + val node_13 = treeW.getPrivateNode(classUnderTest)?.right?.value + val node_15 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value + val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.left?.value + val node_11 = treeW.getPrivateNode(classUnderTest)?.right?.left?.right?.value + val node_9 = treeW.getPrivateNode(classUnderTest)?.right?.left?.left?.value + val node_null = treeW.getPrivateNode(classUnderTest)?.right?.right?.left?.value + + assertEquals(expected = root, actual = 8) + assertEquals(expected = node_10, actual = 10) + assertEquals(expected = node_11, actual = 11) + assertEquals(expected = node_13, actual = 13) + assertEquals(expected = node_9, actual = 9) + assertEquals(expected = node_15, actual = 15) + assertEquals(expected = node_null, actual = null) + } + + @Test + fun `test two child delete min element in right tree for leftmost element`() { + val num = mutableListOf(8, 10, 7, 6) + for (i in num) { + classUnderTest.insert(i) + } + + classUnderTest.delete(8) + + val root = treeW.getPrivateNode(classUnderTest)?.value + val node_7 = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_6 = treeW.getPrivateNode(classUnderTest)?.left?.left?.value + val node_null = treeW.getPrivateNode(classUnderTest)?.right?.value + + assertEquals(expected = root, actual = 10) + assertEquals(expected = node_null, actual = null) + assertEquals(expected = node_7, actual = 7) + assertEquals(expected = node_6, actual = 6) + } +} \ No newline at end of file diff --git a/lib/src/test/kotlin/treelib/RBStructTree.kt b/lib/src/test/kotlin/treelib/RBStructTree.kt new file mode 100644 index 0000000..c1e040b --- /dev/null +++ b/lib/src/test/kotlin/treelib/RBStructTree.kt @@ -0,0 +1,18 @@ +package treelib + +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.DisplayName +import treelib.rbTree.RBNode +import treelib.rbTree.RBStateContainer +import treelib.rbTree.RBStruct + +@DisplayName("Test: Red-Black Tree Struct") +class RBStructTree { + val treeW = TreeStructWrapper, RBStateContainer, RBStruct>() + var classUnderTest = RBStruct() + + @BeforeEach + fun reInitClassUnderTest() { + classUnderTest = RBStruct() + } +} \ No newline at end of file diff --git a/lib/src/test/kotlin/treelib/TreeStructsTest.kt b/lib/src/test/kotlin/treelib/TreeStructsTest.kt deleted file mode 100644 index a79b9ef..0000000 --- a/lib/src/test/kotlin/treelib/TreeStructsTest.kt +++ /dev/null @@ -1,513 +0,0 @@ -package treelib - -import org.junit.jupiter.api.* -import kotlin.test.assertEquals - -/* BINStruct */ -import treelib.binTree.BINNode -import treelib.binTree.BINStruct - -/* AVLStruct */ -import treelib.avlTree.AVLNode -import treelib.avlTree.AVLStateContainer -import treelib.avlTree.AVLStruct -import treelib.binTree.BINStateContainer - -/* RBStruct */ -import treelib.rbTree.RBNode -import treelib.rbTree.RBStateContainer -import treelib.rbTree.RBStruct - -@DisplayName("Test group: Structs testing") -class TreeStructsTest { - //TESTS ONLY WITH Comparable = INT, otherwise - errors - @Nested - @DisplayName("Test: Binary Search Tree Struct") - inner class BINStructTest { - val treeW = TreeStructWrapper, BINStateContainer, BINStruct>() - var classUnderTest = BINStruct() - - @BeforeEach - fun reInitClassUnderTest() { - classUnderTest = BINStruct() - } - @Test - fun `test delete root`() { - val num = mutableListOf(5, 3, 7, 1, 9, -1, 4 ,2, 0, 6) - for (i in num) { - classUnderTest.insert(i) - } - classUnderTest.delete(5) - val root = treeW.getPrivateNode(classUnderTest)?.value - - assertEquals(expected = 6, actual = root) - } - - @Test - fun `test insert`() { - val num = mutableListOf(1, 2, 3, 4, 5, 8) - for (i in num) { - classUnderTest.insert(i) - } - - val additional_num = mutableListOf(1, 2, 3, 5, 7, 8, 11) - for (i in additional_num) { - classUnderTest.insert(i) - } - - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_2 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_null = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_3 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val node_null1 = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - val node_4 = treeW.getPrivateNode(classUnderTest)?.right?.right?.right?.value - - assertEquals(expected = root, actual = 1) - assertEquals(expected = node_null, actual = null) - assertEquals(expected = node_4, actual = 4) - assertEquals(expected = node_2, actual = 2) - assertEquals(expected = node_3, actual = 3) - assertEquals(expected = node_null1, actual = null) - } - - @Test - fun `test find ordinary`() { - val num = mutableListOf(2, 3, 1, 4, 5 ,10) - - assertEquals(expected = classUnderTest.find(2), actual = null) - - for (i in num) { - classUnderTest.insert(i) - } - - assertEquals(expected = classUnderTest.find(2), actual = 2) - } - - @Test - fun `test find null`() { - val num = mutableListOf(1) - classUnderTest.insert(num[0]) - - assertEquals(classUnderTest.find(2), null) - - } - - @Test - fun `test find root`() { - val num = mutableListOf(1) - classUnderTest.insert(num[0]) - - assertEquals(classUnderTest.find(1), 1) - } - - @Test - fun `test insert and delete root`() { - val num = mutableListOf(1, 2) - for (i in num) { - classUnderTest.insert(i) - } - - classUnderTest.delete(1) - - val additional_num = mutableListOf(1, 2, 11) - for (i in additional_num) { - classUnderTest.insert(i) - } - - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_1 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_11 = treeW.getPrivateNode(classUnderTest)?.right?.value - - - assertEquals(expected = root, actual = 2) - assertEquals(expected = node_1, actual = 1) - assertEquals(expected = node_11, actual = 11) - } - - @Test - fun `test delete nonexistent value right`() { - val num = mutableListOf(5, 6) - for (value in num) { - classUnderTest.insert(value) - } - classUnderTest.delete(6) - - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.value - - assertEquals(expected = null, actual = node_null_left) - assertEquals(expected = null, actual = node_null_right) - assertEquals(expected = 5, actual = root) - } - - @Test - fun `test delete nonexistent value left`() { - val num = mutableListOf(6, 5) - for (value in num) { - classUnderTest.insert(value) - } - classUnderTest.delete(5) - - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.value - - assertEquals(expected = null, actual = node_null_left) - assertEquals(expected = null, actual = node_null_right) - assertEquals(expected = 6, actual = root) - } - - @Test - fun `test delete no child root`(){ - val num = mutableListOf(3) - for (i in num) { - classUnderTest.insert(i) - } - classUnderTest.delete(3) - - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.value - val root = treeW.getPrivateNode(classUnderTest)?.value - - assertEquals(expected = null, actual = node_null_left) - assertEquals(expected = null, actual = node_null_right) - assertEquals(expected = null, actual = root) - } - - @Test - fun `test delete no child right`(){ - val num = mutableListOf(3, 10, 15) - for (i in num) { - classUnderTest.insert(i) - } - classUnderTest.delete(15) - - val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val root = treeW.getPrivateNode(classUnderTest)?.value - - - assertEquals(expected = 10, actual = node_10) - assertEquals(expected = null, actual = node_null_left) - assertEquals(expected = null, actual = node_null_right) - assertEquals(expected = 3, actual = root) - } - - @Test - fun `test delete no child left`(){ - val num = mutableListOf(15, 10, 3) - for (i in num) { - classUnderTest.insert(i) - } - classUnderTest.delete(3) - - val node_10 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.left?.right?.value - val root = treeW.getPrivateNode(classUnderTest)?.value - - - assertEquals(expected = 10, actual = node_10) - assertEquals(expected = null, actual = node_null_left) - assertEquals(expected = null, actual = node_null_right) - assertEquals(expected = 15, actual = root) - } - - @Test - fun `test delete one child left`(){ - val num = mutableListOf(3, 2, 1, 5) - for (value in num) { - classUnderTest.insert(value) - } - classUnderTest.delete(2) - - val node_1 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.left?.right?.value - val root = treeW.getPrivateNode(classUnderTest)?.value - - assertEquals(expected = 1 , actual = node_1) - assertEquals(expected = null , actual = node_null_left) - assertEquals(expected = null , actual = node_null_right) - assertEquals(expected = 3, actual = root) - } - - @Test - fun `test delete one child right`(){ - val num = mutableListOf(3, 1, 5, 6) - for (value in num) { - classUnderTest.insert(value) - } - classUnderTest.delete(5) - - val node_6 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val root = treeW.getPrivateNode(classUnderTest)?.value - - assertEquals(expected = 6 , actual = node_6) - assertEquals(expected = null , actual = node_null_left) - assertEquals(expected = null , actual = node_null_right) - assertEquals(expected = 3, actual = root) - } - - @Test - fun `test delete one child root`() { - val num = mutableListOf(3, 6) - for (value in num) { - classUnderTest.insert(value) - } - classUnderTest.delete(3) - - val node_6 = treeW.getPrivateNode(classUnderTest)?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.value - - assertEquals(expected = 6 , actual = node_6) - assertEquals(expected = null , actual = node_null_left) - assertEquals(expected = null , actual = node_null_right) - } - - @Test - fun `test delete one child with family`() { - val num = mutableListOf(10, 7, 13, 6, 3, 1, 5, 2, 4, 15) - for (value in num) { - classUnderTest.insert(value) - } - classUnderTest.delete(7) - val node_6 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_3 = treeW.getPrivateNode(classUnderTest)?.left?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.left?.right?.value - val node_1 = treeW.getPrivateNode(classUnderTest)?.left?.left?.left?.value - val node_2 = treeW.getPrivateNode(classUnderTest)?.left?.left?.left?.right?.value - val node_5 = treeW.getPrivateNode(classUnderTest)?.left?.left?.right?.value - val node_4 = treeW.getPrivateNode(classUnderTest)?.left?.left?.right?.left?.value - val root = treeW.getPrivateNode(classUnderTest)?.value - - assertEquals(expected = 6 , actual = node_6) - assertEquals(expected = 3 , actual = node_3) - assertEquals(expected = null , actual = node_null_right) - assertEquals(expected = 1 , actual = node_1) - assertEquals(expected = 2 , actual = node_2) - assertEquals(expected = 5 , actual = node_5) - assertEquals(expected = 4 , actual = node_4) - assertEquals(expected = 10, actual = root) - } - - @Test - fun `test delete two child only three element`() { - val num = mutableListOf(2, 1 ,3) - for (i in num) { - classUnderTest.insert(i) - } - classUnderTest.delete(2) - - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_1 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_left1 = treeW.getPrivateNode(classUnderTest)?.left?.left?.value - val node_null_right1 = treeW.getPrivateNode(classUnderTest)?.left?.right?.value - val node_null_right_root = treeW.getPrivateNode(classUnderTest)?.right?.value - - assertEquals(expected = root, actual = 3) - assertEquals(expected = node_1, actual = 1) - assertEquals(expected = node_null_left1, actual = null) - assertEquals(expected = node_null_right1, actual = null) - assertEquals(expected = node_null_right_root, actual = null) - } - - @Test - fun `test delete two child without family`() { - val num = mutableListOf(10, 7, 5, 4, 6) - for (i in num) { - classUnderTest.insert(i) - } - classUnderTest.delete(7) - - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_5 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_4 = treeW.getPrivateNode(classUnderTest)?.left?.left?.value - val node_6 = treeW.getPrivateNode(classUnderTest)?.left?.right?.value - val node_null_left4 = treeW.getPrivateNode(classUnderTest)?.left?.left?.left?.value - val node_null_right4 = treeW.getPrivateNode(classUnderTest)?.left?.left?.right?.value - val node_null_left6 = treeW.getPrivateNode(classUnderTest)?.left?.right?.left?.value - val node_null_right6 = treeW.getPrivateNode(classUnderTest)?.left?.right?.left?.value - - assertEquals(expected = root, actual = 10) - assertEquals(expected = node_5, actual = 5) - assertEquals(expected = node_4, actual = 4) - assertEquals(expected = node_6, actual = 6) - assertEquals(expected = node_null_left4, actual = null) - assertEquals(expected = node_null_right4, actual = null) - assertEquals(expected = node_null_left6, actual = null) - assertEquals(expected = node_null_right6, actual = null) - } - - @Test - fun `test two child double delete and delete root`() { - val num = mutableListOf(6, 8, 10, 7) - for (i in num) { - classUnderTest.insert(i) - } - - classUnderTest.delete(6) - classUnderTest.delete(7) - - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_null_right10 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val node_null_left10 = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - - assertEquals(expected = root, actual = 8) - assertEquals(expected = node_10, actual = 10) - assertEquals(expected = node_null_left10, actual = null) - assertEquals(expected = node_null_right10, actual = null) - assertEquals(expected = node_null_left, actual = null) - } - - @Test - fun `test two child delete min element in right tree`() { - val num = mutableListOf(6, 8, 10, 7, 12, 9) - for (i in num) { - classUnderTest.insert(i) - } - - classUnderTest.delete(8) - - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_9 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_7 = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val node_12 = treeW.getPrivateNode(classUnderTest)?.right?.right?.right?.value - val node_null = treeW.getPrivateNode(classUnderTest)?.right?.right?.left?.value - - assertEquals(expected = root, actual = 6) - assertEquals(expected = node_9, actual = 9) - assertEquals(expected = node_null, actual = null) - assertEquals(expected = node_null_left, actual = null) - assertEquals(expected = node_7, actual = 7) - assertEquals(expected = node_10, actual = 10) - assertEquals(expected = node_12, actual = 12) - } - - @Test - fun `test two child delete min element in right tree for root`() { - val num = mutableListOf(8, 10, 7, 12, 9) - for (i in num) { - classUnderTest.insert(i) - } - - classUnderTest.delete(8) - - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_7 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_12 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val node_null = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - - assertEquals(expected = root, actual = 9) - assertEquals(expected = node_null, actual = null) - assertEquals(expected = node_7, actual = 7) - assertEquals(expected = node_10, actual = 10) - assertEquals(expected = node_12, actual = 12) - } - - @Test - fun `test two child delete min element in right tree for rightmost element`() { - val num = mutableListOf(8, 10, 7, 12, 13, 14) - for (i in num) { - classUnderTest.insert(i) - } - - classUnderTest.delete(8) - - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_7 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_12 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_13 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val node_14 = treeW.getPrivateNode(classUnderTest)?.right?.right?.right?.value - val node_null = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - - assertEquals(expected = root, actual = 10) - assertEquals(expected = node_null, actual = null) - assertEquals(expected = node_7, actual = 7) - assertEquals(expected = node_13, actual = 13) - assertEquals(expected = node_14, actual = 14) - assertEquals(expected = node_12, actual = 12) - } - - @Test - fun `test two child delete min element in right tree but in Tree`() { - val num = mutableListOf(8, 12, 15, 13, 10 , 11, 9) - for (i in num) { - classUnderTest.insert(i) - } - - classUnderTest.delete(12) - - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_13 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_15 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - val node_11 = treeW.getPrivateNode(classUnderTest)?.right?.left?.right?.value - val node_9 = treeW.getPrivateNode(classUnderTest)?.right?.left?.left?.value - val node_null = treeW.getPrivateNode(classUnderTest)?.right?.right?.left?.value - - assertEquals(expected = root, actual = 8) - assertEquals(expected = node_10, actual = 10) - assertEquals(expected = node_11, actual = 11) - assertEquals(expected = node_13, actual = 13) - assertEquals(expected = node_9, actual = 9) - assertEquals(expected = node_15, actual = 15) - assertEquals(expected = node_null, actual = null) - } - - @Test - fun `test two child delete min element in right tree for leftmost element`() { - val num = mutableListOf(8, 10, 7, 6) - for (i in num) { - classUnderTest.insert(i) - } - - classUnderTest.delete(8) - - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_7 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_6 = treeW.getPrivateNode(classUnderTest)?.left?.left?.value - val node_null = treeW.getPrivateNode(classUnderTest)?.right?.value - - assertEquals(expected = root, actual = 10) - assertEquals(expected = node_null, actual = null) - assertEquals(expected = node_7, actual = 7) - assertEquals(expected = node_6, actual = 6) - } - - } - - @Nested - @DisplayName("Test: AVL Struct") - inner class AVLStructTest { - val treeW = TreeStructWrapper, AVLStateContainer, AVLStruct>() - var classUnderTest = AVLStruct() - - @BeforeEach - fun reInitClassUnderTest() { - classUnderTest = AVLStruct() - } - } - - @Nested - @DisplayName("Test: Red-Black Tree Struct") - inner class RBStructTree { - val treeW = TreeStructWrapper, RBStateContainer,RBStruct>() - var classUnderTest = RBStruct() - - @BeforeEach - fun reInitClassUnderTest() { - classUnderTest = RBStruct() - } - } -} From 6377db78126e76ec49e9aee36d7bddd1e8f8238a Mon Sep 17 00:00:00 2001 From: Georgy S Date: Sat, 15 Apr 2023 23:28:10 +0300 Subject: [PATCH 02/84] fix: Fix bugs in RBStruct; write base tests for RBStruct. --- .../kotlin/treelib/abstractTree/TreeStruct.kt | 6 +- .../main/kotlin/treelib/rbTree/RBStruct.kt | 15 ++- lib/src/test/kotlin/treelib/RBStructTest.kt | 103 ++++++++++++++++++ lib/src/test/kotlin/treelib/RBStructTree.kt | 18 --- 4 files changed, 120 insertions(+), 22 deletions(-) create mode 100644 lib/src/test/kotlin/treelib/RBStructTest.kt delete mode 100644 lib/src/test/kotlin/treelib/RBStructTree.kt diff --git a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt index 2f21c10..422177e 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt @@ -220,7 +220,11 @@ abstract class TreeStruct, NodeType : Node> : BalancedTreeStruct, RBStateContainer, RBBalancer>() { @@ -17,12 +20,12 @@ class RBStruct> : override fun generateStateInsert( insertNode: RBNode?, contentNode: RBNode?, - ): RBStateContainer = RBStateContainer(contentNode) + ): RBStateContainer = RBStateContainer(insertNode) override fun generateStateFind( findNode: RBNode?, contentNode: RBNode?, - ): RBStateContainer = RBStateContainer(contentNode) + ): RBStateContainer = RBStateContainer(findNode) override fun connectUnlinkedSubTreeWithParent( node: RBNode, @@ -45,6 +48,7 @@ class RBStruct> : } } else root?.let { root = childForLink + if (childForLink != null) childForLink.parent = null } } @@ -53,7 +57,12 @@ class RBStruct> : override fun createNode(item: Pack): RBNode = RBNode(item) override fun linkNewNode(node: RBNode, parent: RBNode?): RBNode { - if (parent == null) root = node + if (parent == null) { + root = node + root?.let { + it.color = Markers.BLACK + } ?: throw MultithreadingException(ImpossibleCaseException()) + } else { if (node.value > parent.value) parent.right = node else parent.left = node diff --git a/lib/src/test/kotlin/treelib/RBStructTest.kt b/lib/src/test/kotlin/treelib/RBStructTest.kt new file mode 100644 index 0000000..807a1d6 --- /dev/null +++ b/lib/src/test/kotlin/treelib/RBStructTest.kt @@ -0,0 +1,103 @@ +package treelib + +import org.junit.jupiter.api.* +import treelib.rbTree.RBNode +import treelib.rbTree.RBStateContainer +import treelib.rbTree.RBStruct +import treelib.singleObjects.Markers +import kotlin.test.assertEquals + +@DisplayName("Test: Red-Black Tree Struct") +class RBStructTest { + val treeW = TreeStructWrapper, RBStateContainer, RBStruct>() + var classUnderTest = RBStruct() + + @BeforeEach + fun reInitClassUnderTest() { + classUnderTest = RBStruct() + } + + @Test + fun `base test on creation root`() { + classUnderTest.insert(6) + val root = treeW.getPrivateNode(classUnderTest) + assertAll( + { assertEquals(root?.value, 6) }, + { assertEquals(root?.color, Markers.BLACK) }, + ) + } + + @Test + fun `base test on creation root with left`() { + classUnderTest.insert(6) + classUnderTest.insert(3) + val root = treeW.getPrivateNode(classUnderTest) + assertAll( + { assertEquals(root?.left?.value, 3) }, + { assertEquals(root?.left?.color, Markers.RED) }, + ) + } + + @Test + fun `base test on creation root with right`() { + classUnderTest.insert(6) + classUnderTest.insert(8) + val root = treeW.getPrivateNode(classUnderTest) + assertAll( + { assertEquals(root?.right?.value, 8) }, + { assertEquals(root?.right?.color, Markers.RED) }, + ) + } + + @Test + fun `base test on creation children`() { + classUnderTest.insert(6) + classUnderTest.insert(8) + classUnderTest.insert(3) + val root = treeW.getPrivateNode(classUnderTest) + assertAll( + { assertEquals(root?.right?.value, 8) }, + { assertEquals(root?.left?.value, 3) }, + { assertEquals(root?.right?.color, Markers.RED) }, + { assertEquals(root?.left?.color, Markers.RED) }, + ) + } + + @Test + fun `base test delete root (left & right children)`() { + classUnderTest.insert(6) + classUnderTest.insert(8) + classUnderTest.insert(3) + classUnderTest.delete(6) + val root = treeW.getPrivateNode(classUnderTest) + assertAll( + { assertEquals(root?.value, 8) }, + { assertEquals(root?.color, Markers.BLACK) }, + ) + } + + @Test + fun `base test delete root (right child)`() { + classUnderTest.insert(6) + classUnderTest.insert(8) + classUnderTest.delete(6) + val root = treeW.getPrivateNode(classUnderTest) + assertAll( + { assertEquals(8, root?.value) }, + { assertEquals(Markers.BLACK, root?.color) }, + ) + } + + @Test + fun `base test delete root (left child)`() { + classUnderTest.insert(6) + classUnderTest.insert(3) + classUnderTest.delete(6) + val root = treeW.getPrivateNode(classUnderTest) + assertAll( + { assertEquals(3, root?.value) }, + { assertEquals(Markers.BLACK, root?.color) }, + ) + } + +} \ No newline at end of file diff --git a/lib/src/test/kotlin/treelib/RBStructTree.kt b/lib/src/test/kotlin/treelib/RBStructTree.kt deleted file mode 100644 index c1e040b..0000000 --- a/lib/src/test/kotlin/treelib/RBStructTree.kt +++ /dev/null @@ -1,18 +0,0 @@ -package treelib - -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.DisplayName -import treelib.rbTree.RBNode -import treelib.rbTree.RBStateContainer -import treelib.rbTree.RBStruct - -@DisplayName("Test: Red-Black Tree Struct") -class RBStructTree { - val treeW = TreeStructWrapper, RBStateContainer, RBStruct>() - var classUnderTest = RBStruct() - - @BeforeEach - fun reInitClassUnderTest() { - classUnderTest = RBStruct() - } -} \ No newline at end of file From c58589caffa3f266caca5cc54aa3069f39bc4542 Mon Sep 17 00:00:00 2001 From: Georgy S Date: Sun, 16 Apr 2023 14:50:38 +0300 Subject: [PATCH 03/84] feat: Add RBAnalyzer class for testing invariant of a RBStruct. --- .../kotlin/treelib/abstractTree/TreeStruct.kt | 6 +- lib/src/test/kotlin/treelib/AVLStructTest.kt | 1 + lib/src/test/kotlin/treelib/BINStructTest.kt | 1 + lib/src/test/kotlin/treelib/RBStructTest.kt | 11 ++- lib/src/test/kotlin/utils/Analyzer.kt | 10 +++ lib/src/test/kotlin/utils/RBAnalyzer.kt | 85 +++++++++++++++++++ .../{treelib => utils}/TreeStructWrapper.kt | 2 +- 7 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 lib/src/test/kotlin/utils/Analyzer.kt create mode 100644 lib/src/test/kotlin/utils/RBAnalyzer.kt rename lib/src/test/kotlin/{treelib => utils}/TreeStructWrapper.kt (98%) diff --git a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt index 422177e..898a40e 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt @@ -6,7 +6,11 @@ import treelib.singleObjects.exceptions.MultithreadingException import treelib.singleObjects.exceptions.NonExistentValueException -abstract class TreeStruct, NodeType : Node, State : StateContainer> { +abstract class TreeStruct< + Pack : Comparable, + NodeType : Node, + State : StateContainer + > { protected abstract var root: NodeType? diff --git a/lib/src/test/kotlin/treelib/AVLStructTest.kt b/lib/src/test/kotlin/treelib/AVLStructTest.kt index 00215f2..23237a8 100644 --- a/lib/src/test/kotlin/treelib/AVLStructTest.kt +++ b/lib/src/test/kotlin/treelib/AVLStructTest.kt @@ -5,6 +5,7 @@ import org.junit.jupiter.api.DisplayName import treelib.avlTree.AVLNode import treelib.avlTree.AVLStateContainer import treelib.avlTree.AVLStruct +import utils.TreeStructWrapper @DisplayName("Test: AVL Struct") class AVLStructTest { diff --git a/lib/src/test/kotlin/treelib/BINStructTest.kt b/lib/src/test/kotlin/treelib/BINStructTest.kt index 194096e..38b5a71 100644 --- a/lib/src/test/kotlin/treelib/BINStructTest.kt +++ b/lib/src/test/kotlin/treelib/BINStructTest.kt @@ -6,6 +6,7 @@ import org.junit.jupiter.api.Test import treelib.binTree.BINNode import treelib.binTree.BINStateContainer import treelib.binTree.BINStruct +import utils.TreeStructWrapper import kotlin.test.assertEquals @DisplayName("Test: Binary Search Tree Struct") diff --git a/lib/src/test/kotlin/treelib/RBStructTest.kt b/lib/src/test/kotlin/treelib/RBStructTest.kt index 807a1d6..da9e9c5 100644 --- a/lib/src/test/kotlin/treelib/RBStructTest.kt +++ b/lib/src/test/kotlin/treelib/RBStructTest.kt @@ -5,12 +5,18 @@ import treelib.rbTree.RBNode import treelib.rbTree.RBStateContainer import treelib.rbTree.RBStruct import treelib.singleObjects.Markers +import utils.RBAnalyzer +import utils.TreeStructWrapper import kotlin.test.assertEquals @DisplayName("Test: Red-Black Tree Struct") class RBStructTest { - val treeW = TreeStructWrapper, RBStateContainer, RBStruct>() - var classUnderTest = RBStruct() + private val treeW = TreeStructWrapper, RBStateContainer, RBStruct>() + private var classUnderTest = RBStruct() + + private fun testAssert(msg: String): Nothing = fail(msg) + + private val analyzer = RBAnalyzer(::testAssert) @BeforeEach fun reInitClassUnderTest() { @@ -99,5 +105,4 @@ class RBStructTest { { assertEquals(Markers.BLACK, root?.color) }, ) } - } \ No newline at end of file diff --git a/lib/src/test/kotlin/utils/Analyzer.kt b/lib/src/test/kotlin/utils/Analyzer.kt new file mode 100644 index 0000000..5a342f9 --- /dev/null +++ b/lib/src/test/kotlin/utils/Analyzer.kt @@ -0,0 +1,10 @@ +package utils + +import treelib.abstractTree.Node + +interface Analyzer< + Pack : Comparable, + NodeType : Node, + > { + fun checkTree(root: NodeType) +} \ No newline at end of file diff --git a/lib/src/test/kotlin/utils/RBAnalyzer.kt b/lib/src/test/kotlin/utils/RBAnalyzer.kt new file mode 100644 index 0000000..1932026 --- /dev/null +++ b/lib/src/test/kotlin/utils/RBAnalyzer.kt @@ -0,0 +1,85 @@ +package utils + +import treelib.rbTree.RBNode +import treelib.singleObjects.Markers +import treelib.singleObjects.exceptions.BugInImplementException + +class RBAnalyzer>( + val assertMethod: (input: String) -> Unit = { + throw BugInImplementException(it) + } +) : Analyzer> { + /** Magic number for error := -9999999 -> just an impossible value **/ + private val errorMagicNumber = -9999999 + + override fun checkTree(root: RBNode) { + if (root.color != Markers.BLACK) assertMethod("The root isn't black!!!") + checkInvariant(root) + } + + private fun checkInvariant(node: RBNode): Int { + var leftBlackCount = 0 + var rightBlackCount = 0 + + if ((node.right == null) && (node.left == null)) { + if (node.color == Markers.RED) return 0 + else return 1 + } + node.right?.let { + when { + it.value == node.value -> { + assertMethod("parent.value == RightChild.value => [${node.value} == ${it.value}]") + return@checkInvariant errorMagicNumber + } + + it.value < node.value -> { + assertMethod("parent.value > RightChild.value => [${node.value} > ${it.value}]") + return@checkInvariant errorMagicNumber + } + + (it.color == Markers.RED) && (node.color == Markers.RED) -> { + assertMethod("parent.color == RED == RightChild.color => [parent - ${node.value} RightChild - ${it.value}]") + return@checkInvariant errorMagicNumber + } + + else -> {} + } + } + + node.left?.let { + when { + it.value == node.value -> { + assertMethod("parent.value == LeftChild.value => [${node.value} == ${it.value}]") + return@checkInvariant errorMagicNumber + } + + it.value > node.value -> { + assertMethod("parent.value < LeftChild.value => [${node.value} < ${it.value}]") + return@checkInvariant errorMagicNumber + } + + (it.color == Markers.RED) && (node.color == Markers.RED) -> { + assertMethod("parent.color == RED == LeftChild.color => [parent - ${node.value} LeftChild - ${it.value}]") + return@checkInvariant errorMagicNumber + } + + else -> {} + } + } + + leftBlackCount = node.left?.let { return@let checkInvariant(it) } ?: 0 + rightBlackCount = node.right?.let { return@let checkInvariant(it) } ?: 0 + + if (leftBlackCount < 0 || rightBlackCount < 0) return errorMagicNumber + + if (leftBlackCount != rightBlackCount) { + assertMethod( + "Number of black nodes does not match in children: parent.value - ${node.value} =>[left - $leftBlackCount] != [right - $rightBlackCount]" + ) + return errorMagicNumber + } + + if(node.color == Markers.BLACK) return leftBlackCount + 1 + else return rightBlackCount + } +} \ No newline at end of file diff --git a/lib/src/test/kotlin/treelib/TreeStructWrapper.kt b/lib/src/test/kotlin/utils/TreeStructWrapper.kt similarity index 98% rename from lib/src/test/kotlin/treelib/TreeStructWrapper.kt rename to lib/src/test/kotlin/utils/TreeStructWrapper.kt index 88870ec..1bdb93e 100644 --- a/lib/src/test/kotlin/treelib/TreeStructWrapper.kt +++ b/lib/src/test/kotlin/utils/TreeStructWrapper.kt @@ -1,4 +1,4 @@ -package treelib +package utils import treelib.abstractTree.Node import treelib.abstractTree.StateContainer From bee3da40b439ba0728ad76378a075a186c044024 Mon Sep 17 00:00:00 2001 From: Georgy S Date: Sun, 16 Apr 2023 15:36:48 +0300 Subject: [PATCH 04/84] refactor: Rename variables in test Classes. --- lib/src/test/kotlin/treelib/AVLStructTest.kt | 4 +- lib/src/test/kotlin/treelib/RBStructTest.kt | 54 ++++++++++---------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/lib/src/test/kotlin/treelib/AVLStructTest.kt b/lib/src/test/kotlin/treelib/AVLStructTest.kt index 23237a8..25ce4cb 100644 --- a/lib/src/test/kotlin/treelib/AVLStructTest.kt +++ b/lib/src/test/kotlin/treelib/AVLStructTest.kt @@ -10,10 +10,10 @@ import utils.TreeStructWrapper @DisplayName("Test: AVL Struct") class AVLStructTest { val treeW = TreeStructWrapper, AVLStateContainer, AVLStruct>() - var classUnderTest = AVLStruct() + var treeStruct = AVLStruct() @BeforeEach fun reInitClassUnderTest() { - classUnderTest = AVLStruct() + treeStruct = AVLStruct() } } \ No newline at end of file diff --git a/lib/src/test/kotlin/treelib/RBStructTest.kt b/lib/src/test/kotlin/treelib/RBStructTest.kt index da9e9c5..5995dd4 100644 --- a/lib/src/test/kotlin/treelib/RBStructTest.kt +++ b/lib/src/test/kotlin/treelib/RBStructTest.kt @@ -12,7 +12,7 @@ import kotlin.test.assertEquals @DisplayName("Test: Red-Black Tree Struct") class RBStructTest { private val treeW = TreeStructWrapper, RBStateContainer, RBStruct>() - private var classUnderTest = RBStruct() + private var treeStruct = RBStruct() private fun testAssert(msg: String): Nothing = fail(msg) @@ -20,13 +20,13 @@ class RBStructTest { @BeforeEach fun reInitClassUnderTest() { - classUnderTest = RBStruct() + treeStruct = RBStruct() } @Test fun `base test on creation root`() { - classUnderTest.insert(6) - val root = treeW.getPrivateNode(classUnderTest) + treeStruct.insert(6) + val root = treeW.getPrivateNode(treeStruct) assertAll( { assertEquals(root?.value, 6) }, { assertEquals(root?.color, Markers.BLACK) }, @@ -35,9 +35,9 @@ class RBStructTest { @Test fun `base test on creation root with left`() { - classUnderTest.insert(6) - classUnderTest.insert(3) - val root = treeW.getPrivateNode(classUnderTest) + treeStruct.insert(6) + treeStruct.insert(3) + val root = treeW.getPrivateNode(treeStruct) assertAll( { assertEquals(root?.left?.value, 3) }, { assertEquals(root?.left?.color, Markers.RED) }, @@ -46,9 +46,9 @@ class RBStructTest { @Test fun `base test on creation root with right`() { - classUnderTest.insert(6) - classUnderTest.insert(8) - val root = treeW.getPrivateNode(classUnderTest) + treeStruct.insert(6) + treeStruct.insert(8) + val root = treeW.getPrivateNode(treeStruct) assertAll( { assertEquals(root?.right?.value, 8) }, { assertEquals(root?.right?.color, Markers.RED) }, @@ -57,10 +57,10 @@ class RBStructTest { @Test fun `base test on creation children`() { - classUnderTest.insert(6) - classUnderTest.insert(8) - classUnderTest.insert(3) - val root = treeW.getPrivateNode(classUnderTest) + treeStruct.insert(6) + treeStruct.insert(8) + treeStruct.insert(3) + val root = treeW.getPrivateNode(treeStruct) assertAll( { assertEquals(root?.right?.value, 8) }, { assertEquals(root?.left?.value, 3) }, @@ -71,11 +71,11 @@ class RBStructTest { @Test fun `base test delete root (left & right children)`() { - classUnderTest.insert(6) - classUnderTest.insert(8) - classUnderTest.insert(3) - classUnderTest.delete(6) - val root = treeW.getPrivateNode(classUnderTest) + treeStruct.insert(6) + treeStruct.insert(8) + treeStruct.insert(3) + treeStruct.delete(6) + val root = treeW.getPrivateNode(treeStruct) assertAll( { assertEquals(root?.value, 8) }, { assertEquals(root?.color, Markers.BLACK) }, @@ -84,10 +84,10 @@ class RBStructTest { @Test fun `base test delete root (right child)`() { - classUnderTest.insert(6) - classUnderTest.insert(8) - classUnderTest.delete(6) - val root = treeW.getPrivateNode(classUnderTest) + treeStruct.insert(6) + treeStruct.insert(8) + treeStruct.delete(6) + val root = treeW.getPrivateNode(treeStruct) assertAll( { assertEquals(8, root?.value) }, { assertEquals(Markers.BLACK, root?.color) }, @@ -96,10 +96,10 @@ class RBStructTest { @Test fun `base test delete root (left child)`() { - classUnderTest.insert(6) - classUnderTest.insert(3) - classUnderTest.delete(6) - val root = treeW.getPrivateNode(classUnderTest) + treeStruct.insert(6) + treeStruct.insert(3) + treeStruct.delete(6) + val root = treeW.getPrivateNode(treeStruct) assertAll( { assertEquals(3, root?.value) }, { assertEquals(Markers.BLACK, root?.color) }, From 9b834d6803882caedccb2a057c28b376d5898a29 Mon Sep 17 00:00:00 2001 From: Georgy S Date: Sun, 16 Apr 2023 15:37:20 +0300 Subject: [PATCH 05/84] feat: Add BINAnalyzer class for testing invariant of the BINStruct. --- lib/src/test/kotlin/treelib/BINStructTest.kt | 307 ++++++++++--------- lib/src/test/kotlin/utils/BINAnalyzer.kt | 52 ++++ 2 files changed, 215 insertions(+), 144 deletions(-) create mode 100644 lib/src/test/kotlin/utils/BINAnalyzer.kt diff --git a/lib/src/test/kotlin/treelib/BINStructTest.kt b/lib/src/test/kotlin/treelib/BINStructTest.kt index 38b5a71..952a6fa 100644 --- a/lib/src/test/kotlin/treelib/BINStructTest.kt +++ b/lib/src/test/kotlin/treelib/BINStructTest.kt @@ -3,30 +3,36 @@ package treelib import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test +import org.junit.jupiter.api.fail import treelib.binTree.BINNode import treelib.binTree.BINStateContainer import treelib.binTree.BINStruct +import utils.BINAnalyzer import utils.TreeStructWrapper import kotlin.test.assertEquals @DisplayName("Test: Binary Search Tree Struct") class BINStructTest { val treeW = TreeStructWrapper, BINStateContainer, BINStruct>() - var classUnderTest = BINStruct() + var treeStruct = BINStruct() + + private fun testAssert(msg: String): Nothing = fail(msg) + + private val analyzer = BINAnalyzer(::testAssert) @BeforeEach fun reInitClassUnderTest() { - classUnderTest = BINStruct() + treeStruct = BINStruct() } @Test fun `test delete root`() { val num = mutableListOf(5, 3, 7, 1, 9, -1, 4, 2, 0, 6) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(5) - val root = treeW.getPrivateNode(classUnderTest)?.value + treeStruct.delete(5) + val root = treeW.getPrivateNode(treeStruct)?.value assertEquals(expected = 6, actual = root) } @@ -35,20 +41,20 @@ class BINStructTest { fun `test insert`() { val num = mutableListOf(1, 2, 3, 4, 5, 8) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } val additional_num = mutableListOf(1, 2, 3, 5, 7, 8, 11) for (i in additional_num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_2 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_null = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_3 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val node_null1 = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - val node_4 = treeW.getPrivateNode(classUnderTest)?.right?.right?.right?.value + val root = treeW.getPrivateNode(treeStruct)?.value + val node_2 = treeW.getPrivateNode(treeStruct)?.right?.value + val node_null = treeW.getPrivateNode(treeStruct)?.left?.value + val node_3 = treeW.getPrivateNode(treeStruct)?.right?.right?.value + val node_null1 = treeW.getPrivateNode(treeStruct)?.right?.left?.value + val node_4 = treeW.getPrivateNode(treeStruct)?.right?.right?.right?.value assertEquals(expected = root, actual = 1) assertEquals(expected = node_null, actual = null) @@ -62,49 +68,49 @@ class BINStructTest { fun `test find ordinary`() { val num = mutableListOf(2, 3, 1, 4, 5, 10) - assertEquals(expected = classUnderTest.find(2), actual = null) + assertEquals(expected = treeStruct.find(2), actual = null) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - assertEquals(expected = classUnderTest.find(2), actual = 2) + assertEquals(expected = treeStruct.find(2), actual = 2) } @Test fun `test find null`() { val num = mutableListOf(1) - classUnderTest.insert(num[0]) + treeStruct.insert(num[0]) - assertEquals(classUnderTest.find(2), null) + assertEquals(treeStruct.find(2), null) } @Test fun `test find root`() { val num = mutableListOf(1) - classUnderTest.insert(num[0]) + treeStruct.insert(num[0]) - assertEquals(classUnderTest.find(1), 1) + assertEquals(treeStruct.find(1), 1) } @Test fun `test insert and delete root`() { val num = mutableListOf(1, 2) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(1) + treeStruct.delete(1) val additional_num = mutableListOf(1, 2, 11) for (i in additional_num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_1 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_11 = treeW.getPrivateNode(classUnderTest)?.right?.value + val root = treeW.getPrivateNode(treeStruct)?.value + val node_1 = treeW.getPrivateNode(treeStruct)?.left?.value + val node_11 = treeW.getPrivateNode(treeStruct)?.right?.value assertEquals(expected = root, actual = 2) @@ -116,13 +122,13 @@ class BINStructTest { fun `test delete nonexistent value right`() { val num = mutableListOf(5, 6) for (value in num) { - classUnderTest.insert(value) + treeStruct.insert(value) } - classUnderTest.delete(6) + treeStruct.delete(6) - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.value + val root = treeW.getPrivateNode(treeStruct)?.value + val node_null_left = treeW.getPrivateNode(treeStruct)?.left?.value + val node_null_right = treeW.getPrivateNode(treeStruct)?.right?.value assertEquals(expected = null, actual = node_null_left) assertEquals(expected = null, actual = node_null_right) @@ -133,13 +139,13 @@ class BINStructTest { fun `test delete nonexistent value left`() { val num = mutableListOf(6, 5) for (value in num) { - classUnderTest.insert(value) + treeStruct.insert(value) } - classUnderTest.delete(5) + treeStruct.delete(5) - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.value + val root = treeW.getPrivateNode(treeStruct)?.value + val node_null_left = treeW.getPrivateNode(treeStruct)?.left?.value + val node_null_right = treeW.getPrivateNode(treeStruct)?.right?.value assertEquals(expected = null, actual = node_null_left) assertEquals(expected = null, actual = node_null_right) @@ -150,13 +156,13 @@ class BINStructTest { fun `test delete no child root`() { val num = mutableListOf(3) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(3) + treeStruct.delete(3) - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.value - val root = treeW.getPrivateNode(classUnderTest)?.value + val node_null_left = treeW.getPrivateNode(treeStruct)?.left?.value + val node_null_right = treeW.getPrivateNode(treeStruct)?.right?.value + val root = treeW.getPrivateNode(treeStruct)?.value assertEquals(expected = null, actual = node_null_left) assertEquals(expected = null, actual = node_null_right) @@ -167,14 +173,14 @@ class BINStructTest { fun `test delete no child right`() { val num = mutableListOf(3, 10, 15) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(15) + treeStruct.delete(15) - val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val root = treeW.getPrivateNode(classUnderTest)?.value + val node_10 = treeW.getPrivateNode(treeStruct)?.right?.value + val node_null_left = treeW.getPrivateNode(treeStruct)?.right?.left?.value + val node_null_right = treeW.getPrivateNode(treeStruct)?.right?.right?.value + val root = treeW.getPrivateNode(treeStruct)?.value assertEquals(expected = 10, actual = node_10) @@ -187,14 +193,14 @@ class BINStructTest { fun `test delete no child left`() { val num = mutableListOf(15, 10, 3) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(3) + treeStruct.delete(3) - val node_10 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.left?.right?.value - val root = treeW.getPrivateNode(classUnderTest)?.value + val node_10 = treeW.getPrivateNode(treeStruct)?.left?.value + val node_null_left = treeW.getPrivateNode(treeStruct)?.left?.left?.value + val node_null_right = treeW.getPrivateNode(treeStruct)?.left?.right?.value + val root = treeW.getPrivateNode(treeStruct)?.value assertEquals(expected = 10, actual = node_10) @@ -207,14 +213,14 @@ class BINStructTest { fun `test delete one child left`() { val num = mutableListOf(3, 2, 1, 5) for (value in num) { - classUnderTest.insert(value) + treeStruct.insert(value) } - classUnderTest.delete(2) + treeStruct.delete(2) - val node_1 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.left?.right?.value - val root = treeW.getPrivateNode(classUnderTest)?.value + val node_1 = treeW.getPrivateNode(treeStruct)?.left?.value + val node_null_left = treeW.getPrivateNode(treeStruct)?.left?.left?.value + val node_null_right = treeW.getPrivateNode(treeStruct)?.left?.right?.value + val root = treeW.getPrivateNode(treeStruct)?.value assertEquals(expected = 1, actual = node_1) assertEquals(expected = null, actual = node_null_left) @@ -226,14 +232,14 @@ class BINStructTest { fun `test delete one child right`() { val num = mutableListOf(3, 1, 5, 6) for (value in num) { - classUnderTest.insert(value) + treeStruct.insert(value) } - classUnderTest.delete(5) + treeStruct.delete(5) - val node_6 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val root = treeW.getPrivateNode(classUnderTest)?.value + val node_6 = treeW.getPrivateNode(treeStruct)?.right?.value + val node_null_left = treeW.getPrivateNode(treeStruct)?.right?.left?.value + val node_null_right = treeW.getPrivateNode(treeStruct)?.right?.right?.value + val root = treeW.getPrivateNode(treeStruct)?.value assertEquals(expected = 6, actual = node_6) assertEquals(expected = null, actual = node_null_left) @@ -245,13 +251,13 @@ class BINStructTest { fun `test delete one child root`() { val num = mutableListOf(3, 6) for (value in num) { - classUnderTest.insert(value) + treeStruct.insert(value) } - classUnderTest.delete(3) + treeStruct.delete(3) - val node_6 = treeW.getPrivateNode(classUnderTest)?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.value + val node_6 = treeW.getPrivateNode(treeStruct)?.value + val node_null_left = treeW.getPrivateNode(treeStruct)?.left?.value + val node_null_right = treeW.getPrivateNode(treeStruct)?.right?.value assertEquals(expected = 6, actual = node_6) assertEquals(expected = null, actual = node_null_left) @@ -262,17 +268,17 @@ class BINStructTest { fun `test delete one child with family`() { val num = mutableListOf(10, 7, 13, 6, 3, 1, 5, 2, 4, 15) for (value in num) { - classUnderTest.insert(value) + treeStruct.insert(value) } - classUnderTest.delete(7) - val node_6 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_3 = treeW.getPrivateNode(classUnderTest)?.left?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.left?.right?.value - val node_1 = treeW.getPrivateNode(classUnderTest)?.left?.left?.left?.value - val node_2 = treeW.getPrivateNode(classUnderTest)?.left?.left?.left?.right?.value - val node_5 = treeW.getPrivateNode(classUnderTest)?.left?.left?.right?.value - val node_4 = treeW.getPrivateNode(classUnderTest)?.left?.left?.right?.left?.value - val root = treeW.getPrivateNode(classUnderTest)?.value + treeStruct.delete(7) + val node_6 = treeW.getPrivateNode(treeStruct)?.left?.value + val node_3 = treeW.getPrivateNode(treeStruct)?.left?.left?.value + val node_null_right = treeW.getPrivateNode(treeStruct)?.left?.right?.value + val node_1 = treeW.getPrivateNode(treeStruct)?.left?.left?.left?.value + val node_2 = treeW.getPrivateNode(treeStruct)?.left?.left?.left?.right?.value + val node_5 = treeW.getPrivateNode(treeStruct)?.left?.left?.right?.value + val node_4 = treeW.getPrivateNode(treeStruct)?.left?.left?.right?.left?.value + val root = treeW.getPrivateNode(treeStruct)?.value assertEquals(expected = 6, actual = node_6) assertEquals(expected = 3, actual = node_3) @@ -288,15 +294,15 @@ class BINStructTest { fun `test delete two child only three element`() { val num = mutableListOf(2, 1, 3) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(2) + treeStruct.delete(2) - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_1 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_left1 = treeW.getPrivateNode(classUnderTest)?.left?.left?.value - val node_null_right1 = treeW.getPrivateNode(classUnderTest)?.left?.right?.value - val node_null_right_root = treeW.getPrivateNode(classUnderTest)?.right?.value + val root = treeW.getPrivateNode(treeStruct)?.value + val node_1 = treeW.getPrivateNode(treeStruct)?.left?.value + val node_null_left1 = treeW.getPrivateNode(treeStruct)?.left?.left?.value + val node_null_right1 = treeW.getPrivateNode(treeStruct)?.left?.right?.value + val node_null_right_root = treeW.getPrivateNode(treeStruct)?.right?.value assertEquals(expected = root, actual = 3) assertEquals(expected = node_1, actual = 1) @@ -309,18 +315,18 @@ class BINStructTest { fun `test delete two child without family`() { val num = mutableListOf(10, 7, 5, 4, 6) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(7) + treeStruct.delete(7) - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_5 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_4 = treeW.getPrivateNode(classUnderTest)?.left?.left?.value - val node_6 = treeW.getPrivateNode(classUnderTest)?.left?.right?.value - val node_null_left4 = treeW.getPrivateNode(classUnderTest)?.left?.left?.left?.value - val node_null_right4 = treeW.getPrivateNode(classUnderTest)?.left?.left?.right?.value - val node_null_left6 = treeW.getPrivateNode(classUnderTest)?.left?.right?.left?.value - val node_null_right6 = treeW.getPrivateNode(classUnderTest)?.left?.right?.left?.value + val root = treeW.getPrivateNode(treeStruct)?.value + val node_5 = treeW.getPrivateNode(treeStruct)?.left?.value + val node_4 = treeW.getPrivateNode(treeStruct)?.left?.left?.value + val node_6 = treeW.getPrivateNode(treeStruct)?.left?.right?.value + val node_null_left4 = treeW.getPrivateNode(treeStruct)?.left?.left?.left?.value + val node_null_right4 = treeW.getPrivateNode(treeStruct)?.left?.left?.right?.value + val node_null_left6 = treeW.getPrivateNode(treeStruct)?.left?.right?.left?.value + val node_null_right6 = treeW.getPrivateNode(treeStruct)?.left?.right?.left?.value assertEquals(expected = root, actual = 10) assertEquals(expected = node_5, actual = 5) @@ -336,17 +342,17 @@ class BINStructTest { fun `test two child double delete and delete root`() { val num = mutableListOf(6, 8, 10, 7) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(6) - classUnderTest.delete(7) + treeStruct.delete(6) + treeStruct.delete(7) - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_null_right10 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val node_null_left10 = treeW.getPrivateNode(classUnderTest)?.right?.left?.value + val root = treeW.getPrivateNode(treeStruct)?.value + val node_null_left = treeW.getPrivateNode(treeStruct)?.left?.value + val node_10 = treeW.getPrivateNode(treeStruct)?.right?.value + val node_null_right10 = treeW.getPrivateNode(treeStruct)?.right?.right?.value + val node_null_left10 = treeW.getPrivateNode(treeStruct)?.right?.left?.value assertEquals(expected = root, actual = 8) assertEquals(expected = node_10, actual = 10) @@ -359,18 +365,18 @@ class BINStructTest { fun `test two child delete min element in right tree`() { val num = mutableListOf(6, 8, 10, 7, 12, 9) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(8) + treeStruct.delete(8) - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_9 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_7 = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val node_12 = treeW.getPrivateNode(classUnderTest)?.right?.right?.right?.value - val node_null = treeW.getPrivateNode(classUnderTest)?.right?.right?.left?.value + val root = treeW.getPrivateNode(treeStruct)?.value + val node_null_left = treeW.getPrivateNode(treeStruct)?.left?.value + val node_9 = treeW.getPrivateNode(treeStruct)?.right?.value + val node_7 = treeW.getPrivateNode(treeStruct)?.right?.left?.value + val node_10 = treeW.getPrivateNode(treeStruct)?.right?.right?.value + val node_12 = treeW.getPrivateNode(treeStruct)?.right?.right?.right?.value + val node_null = treeW.getPrivateNode(treeStruct)?.right?.right?.left?.value assertEquals(expected = root, actual = 6) assertEquals(expected = node_9, actual = 9) @@ -385,16 +391,16 @@ class BINStructTest { fun `test two child delete min element in right tree for root`() { val num = mutableListOf(8, 10, 7, 12, 9) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(8) + treeStruct.delete(8) - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_7 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_12 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val node_null = treeW.getPrivateNode(classUnderTest)?.right?.left?.value + val root = treeW.getPrivateNode(treeStruct)?.value + val node_7 = treeW.getPrivateNode(treeStruct)?.left?.value + val node_10 = treeW.getPrivateNode(treeStruct)?.right?.value + val node_12 = treeW.getPrivateNode(treeStruct)?.right?.right?.value + val node_null = treeW.getPrivateNode(treeStruct)?.right?.left?.value assertEquals(expected = root, actual = 9) assertEquals(expected = node_null, actual = null) @@ -407,17 +413,17 @@ class BINStructTest { fun `test two child delete min element in right tree for rightmost element`() { val num = mutableListOf(8, 10, 7, 12, 13, 14) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(8) + treeStruct.delete(8) - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_7 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_12 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_13 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val node_14 = treeW.getPrivateNode(classUnderTest)?.right?.right?.right?.value - val node_null = treeW.getPrivateNode(classUnderTest)?.right?.left?.value + val root = treeW.getPrivateNode(treeStruct)?.value + val node_7 = treeW.getPrivateNode(treeStruct)?.left?.value + val node_12 = treeW.getPrivateNode(treeStruct)?.right?.value + val node_13 = treeW.getPrivateNode(treeStruct)?.right?.right?.value + val node_14 = treeW.getPrivateNode(treeStruct)?.right?.right?.right?.value + val node_null = treeW.getPrivateNode(treeStruct)?.right?.left?.value assertEquals(expected = root, actual = 10) assertEquals(expected = node_null, actual = null) @@ -431,18 +437,18 @@ class BINStructTest { fun `test two child delete min element in right tree but in Tree`() { val num = mutableListOf(8, 12, 15, 13, 10, 11, 9) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(12) + treeStruct.delete(12) - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_13 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_15 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - val node_11 = treeW.getPrivateNode(classUnderTest)?.right?.left?.right?.value - val node_9 = treeW.getPrivateNode(classUnderTest)?.right?.left?.left?.value - val node_null = treeW.getPrivateNode(classUnderTest)?.right?.right?.left?.value + val root = treeW.getPrivateNode(treeStruct)?.value + val node_13 = treeW.getPrivateNode(treeStruct)?.right?.value + val node_15 = treeW.getPrivateNode(treeStruct)?.right?.right?.value + val node_10 = treeW.getPrivateNode(treeStruct)?.right?.left?.value + val node_11 = treeW.getPrivateNode(treeStruct)?.right?.left?.right?.value + val node_9 = treeW.getPrivateNode(treeStruct)?.right?.left?.left?.value + val node_null = treeW.getPrivateNode(treeStruct)?.right?.right?.left?.value assertEquals(expected = root, actual = 8) assertEquals(expected = node_10, actual = 10) @@ -457,19 +463,32 @@ class BINStructTest { fun `test two child delete min element in right tree for leftmost element`() { val num = mutableListOf(8, 10, 7, 6) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(8) + treeStruct.delete(8) - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_7 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_6 = treeW.getPrivateNode(classUnderTest)?.left?.left?.value - val node_null = treeW.getPrivateNode(classUnderTest)?.right?.value + val root = treeW.getPrivateNode(treeStruct)?.value + val node_7 = treeW.getPrivateNode(treeStruct)?.left?.value + val node_6 = treeW.getPrivateNode(treeStruct)?.left?.left?.value + val node_null = treeW.getPrivateNode(treeStruct)?.right?.value assertEquals(expected = root, actual = 10) assertEquals(expected = node_null, actual = null) assertEquals(expected = node_7, actual = 7) assertEquals(expected = node_6, actual = 6) } + + @Test + fun `test analyzer`(){ + val num = mutableListOf(6, 8, 10, 7, 12, 9) + for (i in num) { + treeStruct.insert(i) + } + + treeStruct.delete(8) + + val root = treeW.getPrivateNode(treeStruct) + root?.let { analyzer.checkTree(root) } ?: Exception("CHzh") + } } \ No newline at end of file diff --git a/lib/src/test/kotlin/utils/BINAnalyzer.kt b/lib/src/test/kotlin/utils/BINAnalyzer.kt new file mode 100644 index 0000000..0584b70 --- /dev/null +++ b/lib/src/test/kotlin/utils/BINAnalyzer.kt @@ -0,0 +1,52 @@ +package utils + +import treelib.binTree.BINNode +import treelib.singleObjects.exceptions.BugInImplementException + +class BINAnalyzer>( + val assertMethod: (input: String) -> Unit = { + throw BugInImplementException(it) + } +) : Analyzer> { + + override fun checkTree(root: BINNode) { + checkInvariant(root) + } + + private tailrec fun checkInvariant(node: BINNode) { + if ((node.left == null) && (node.right == null)) return + + node.right?.let { + when { + it.value == node.value -> { + assertMethod("parent.value == RightChild.value => [${node.value} == ${it.value}]") + return@checkInvariant + } + + it.value < node.value -> { + assertMethod("parent.value > RightChild.value => [${node.value} > ${it.value}]") + return@checkInvariant + } + + else -> {} + } + } + + node.left?.let { + when { + it.value == node.value -> { + assertMethod("parent.value == LeftChild.value => [${node.value} == ${it.value}]") + return@checkInvariant + } + + it.value > node.value -> { + assertMethod("parent.value < LeftChild.value => [${node.value} < ${it.value}]") + return@checkInvariant + } + + else -> {} + } + } + } + +} \ No newline at end of file From 191bd5d695d445307ee788d5fb71bc81676ab66a Mon Sep 17 00:00:00 2001 From: Georgy S Date: Sun, 16 Apr 2023 19:07:21 +0300 Subject: [PATCH 06/84] fix: Rewrite interface Analyzer. --- lib/src/test/kotlin/utils/Analyzer.kt | 11 +++++++++-- lib/src/test/kotlin/utils/BINAnalyzer.kt | 14 +++++++------- lib/src/test/kotlin/utils/RBAnalyzer.kt | 20 ++++++++++---------- 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/lib/src/test/kotlin/utils/Analyzer.kt b/lib/src/test/kotlin/utils/Analyzer.kt index 5a342f9..6131d02 100644 --- a/lib/src/test/kotlin/utils/Analyzer.kt +++ b/lib/src/test/kotlin/utils/Analyzer.kt @@ -2,9 +2,16 @@ package utils import treelib.abstractTree.Node -interface Analyzer< +abstract class Analyzer< Pack : Comparable, NodeType : Node, > { - fun checkTree(root: NodeType) + + var message: String = "" + + protected abstract val assertMethod: (input: String) -> Unit + + protected fun wrappedAssertMethod(input: String) = assertMethod("$message$input") + + abstract fun checkTree(root: NodeType) } \ No newline at end of file diff --git a/lib/src/test/kotlin/utils/BINAnalyzer.kt b/lib/src/test/kotlin/utils/BINAnalyzer.kt index 0584b70..43dc5f5 100644 --- a/lib/src/test/kotlin/utils/BINAnalyzer.kt +++ b/lib/src/test/kotlin/utils/BINAnalyzer.kt @@ -4,27 +4,27 @@ import treelib.binTree.BINNode import treelib.singleObjects.exceptions.BugInImplementException class BINAnalyzer>( - val assertMethod: (input: String) -> Unit = { + override val assertMethod: (input: String) -> Unit = { throw BugInImplementException(it) } -) : Analyzer> { +) : Analyzer>() { override fun checkTree(root: BINNode) { checkInvariant(root) } - private tailrec fun checkInvariant(node: BINNode) { + private fun checkInvariant(node: BINNode) { if ((node.left == null) && (node.right == null)) return node.right?.let { when { it.value == node.value -> { - assertMethod("parent.value == RightChild.value => [${node.value} == ${it.value}]") + wrappedAssertMethod("parent.value == RightChild.value => [${node.value} == ${it.value}]") return@checkInvariant } it.value < node.value -> { - assertMethod("parent.value > RightChild.value => [${node.value} > ${it.value}]") + wrappedAssertMethod("parent.value > RightChild.value => [${node.value} > ${it.value}]") return@checkInvariant } @@ -35,12 +35,12 @@ class BINAnalyzer>( node.left?.let { when { it.value == node.value -> { - assertMethod("parent.value == LeftChild.value => [${node.value} == ${it.value}]") + wrappedAssertMethod("parent.value == LeftChild.value => [${node.value} == ${it.value}]") return@checkInvariant } it.value > node.value -> { - assertMethod("parent.value < LeftChild.value => [${node.value} < ${it.value}]") + wrappedAssertMethod("parent.value < LeftChild.value => [${node.value} < ${it.value}]") return@checkInvariant } diff --git a/lib/src/test/kotlin/utils/RBAnalyzer.kt b/lib/src/test/kotlin/utils/RBAnalyzer.kt index 1932026..1b04aff 100644 --- a/lib/src/test/kotlin/utils/RBAnalyzer.kt +++ b/lib/src/test/kotlin/utils/RBAnalyzer.kt @@ -5,15 +5,15 @@ import treelib.singleObjects.Markers import treelib.singleObjects.exceptions.BugInImplementException class RBAnalyzer>( - val assertMethod: (input: String) -> Unit = { + override val assertMethod: (input: String) -> Unit = { throw BugInImplementException(it) } -) : Analyzer> { +) : Analyzer>() { /** Magic number for error := -9999999 -> just an impossible value **/ private val errorMagicNumber = -9999999 override fun checkTree(root: RBNode) { - if (root.color != Markers.BLACK) assertMethod("The root isn't black!!!") + if (root.color != Markers.BLACK) wrappedAssertMethod("The root isn't black!!!") checkInvariant(root) } @@ -28,17 +28,17 @@ class RBAnalyzer>( node.right?.let { when { it.value == node.value -> { - assertMethod("parent.value == RightChild.value => [${node.value} == ${it.value}]") + wrappedAssertMethod("parent.value == RightChild.value => [${node.value} == ${it.value}]") return@checkInvariant errorMagicNumber } it.value < node.value -> { - assertMethod("parent.value > RightChild.value => [${node.value} > ${it.value}]") + wrappedAssertMethod("parent.value > RightChild.value => [${node.value} > ${it.value}]") return@checkInvariant errorMagicNumber } (it.color == Markers.RED) && (node.color == Markers.RED) -> { - assertMethod("parent.color == RED == RightChild.color => [parent - ${node.value} RightChild - ${it.value}]") + wrappedAssertMethod("parent.color == RED == RightChild.color => [parent - ${node.value} RightChild - ${it.value}]") return@checkInvariant errorMagicNumber } @@ -49,17 +49,17 @@ class RBAnalyzer>( node.left?.let { when { it.value == node.value -> { - assertMethod("parent.value == LeftChild.value => [${node.value} == ${it.value}]") + wrappedAssertMethod("parent.value == LeftChild.value => [${node.value} == ${it.value}]") return@checkInvariant errorMagicNumber } it.value > node.value -> { - assertMethod("parent.value < LeftChild.value => [${node.value} < ${it.value}]") + wrappedAssertMethod("parent.value < LeftChild.value => [${node.value} < ${it.value}]") return@checkInvariant errorMagicNumber } (it.color == Markers.RED) && (node.color == Markers.RED) -> { - assertMethod("parent.color == RED == LeftChild.color => [parent - ${node.value} LeftChild - ${it.value}]") + wrappedAssertMethod("parent.color == RED == LeftChild.color => [parent - ${node.value} LeftChild - ${it.value}]") return@checkInvariant errorMagicNumber } @@ -73,7 +73,7 @@ class RBAnalyzer>( if (leftBlackCount < 0 || rightBlackCount < 0) return errorMagicNumber if (leftBlackCount != rightBlackCount) { - assertMethod( + wrappedAssertMethod( "Number of black nodes does not match in children: parent.value - ${node.value} =>[left - $leftBlackCount] != [right - $rightBlackCount]" ) return errorMagicNumber From c9b46aaf2e355cbd79fb48137e7f69f6880923bf Mon Sep 17 00:00:00 2001 From: Aleksandr Date: Sun, 16 Apr 2023 22:26:04 +0300 Subject: [PATCH 07/84] feat: added tests for the invariant --- .../kotlin/treelib/abstractTree/TreeStruct.kt | 2 +- lib/src/test/kotlin/treelib/AVLStructTest.kt | 70 ++++++++++++++++++- 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt index 898a40e..ebdb05c 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt @@ -136,7 +136,7 @@ abstract class TreeStruct< if (root == null) return generateStateFind(null) while (true) { - if (obj == currentNode?.value) return generateStateFind(currentNode) + if (obj == currentNode?.value) return generateStateFind(currentNode, currentNode) else { currentNode?.let { if (obj > it.value) currentNode = it.right diff --git a/lib/src/test/kotlin/treelib/AVLStructTest.kt b/lib/src/test/kotlin/treelib/AVLStructTest.kt index 25ce4cb..347892c 100644 --- a/lib/src/test/kotlin/treelib/AVLStructTest.kt +++ b/lib/src/test/kotlin/treelib/AVLStructTest.kt @@ -2,18 +2,84 @@ package treelib import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.fail import treelib.avlTree.AVLNode import treelib.avlTree.AVLStateContainer import treelib.avlTree.AVLStruct +import utils.AVLAnalyzer import utils.TreeStructWrapper @DisplayName("Test: AVL Struct") class AVLStructTest { - val treeW = TreeStructWrapper, AVLStateContainer, AVLStruct>() - var treeStruct = AVLStruct() + private val treeW = TreeStructWrapper, AVLStateContainer, AVLStruct>() + private val treeH = AVLAnalyzer(::testAssert) + private var treeStruct = AVLStruct() + private fun testAssert(msg: String): Nothing = fail(msg) @BeforeEach fun reInitClassUnderTest() { treeStruct = AVLStruct() } + + @Test + fun `test one root`() { + val num = mutableListOf(1) + for (i in num) { + treeStruct.insert(i) + } + treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + } + + @Test + fun `test height 3`() { + val num = mutableListOf(3, 2, 1, 4) + for (i in num) { + treeStruct.insert(i) + } + treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + } + + @Test + fun `test height 3 with delete root`() { + val num = mutableListOf(3, 2, 1, 4) + for (i in num) { + treeStruct.insert(i) + } + treeStruct.delete(2) + treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + } + + @Test + fun `test 100000 arguments`() { + for (i in 1..100000) { + treeStruct.insert(i) + } + treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + } + + @Test + fun `test 100000 arguments and delete`() { + for (i in 1..100000) { + treeStruct.insert(i) + } + treeStruct.delete(5000) + treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + } + + @Test + fun `test two arguments`() { + treeStruct.insert(2) + treeStruct.insert(3) + treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + } + + @Test + fun `test many arguments`() { + val num = mutableListOf(3, 2, 1, 4, 2343, 123213, 3213, 657, 534, 12432, 5676756, 321, 5436546, 5435) + for (i in num) { + treeStruct.insert(i) + } + treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + } } \ No newline at end of file From 117e68d522e6aaf713d57ccd4d62e8cd07b544e9 Mon Sep 17 00:00:00 2001 From: Aleksandr Date: Sun, 16 Apr 2023 22:26:39 +0300 Subject: [PATCH 08/84] feat: Added invariant analyzer. --- lib/src/test/kotlin/utils/AVLAnalyzer.kt | 42 ++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 lib/src/test/kotlin/utils/AVLAnalyzer.kt diff --git a/lib/src/test/kotlin/utils/AVLAnalyzer.kt b/lib/src/test/kotlin/utils/AVLAnalyzer.kt new file mode 100644 index 0000000..b8a9ac4 --- /dev/null +++ b/lib/src/test/kotlin/utils/AVLAnalyzer.kt @@ -0,0 +1,42 @@ +package utils + +import treelib.avlTree.AVLNode +import kotlin.math.abs +import kotlin.math.max + + + +class AVLAnalyzer>(override val assertMethod: (input: String) -> Unit) : Analyzer>() { + private var heightL = 0 + private var heightR = 0 + private var heightMax = 0 + private var mainRight: AVLNode? = null + + override fun checkTree(root: AVLNode) { + mainRight = root.right + descent(root, 0) + heightR = heightMax + if (abs(heightR - heightL) > 1) { + wrappedAssertMethod("the invariant is not observed") + } + } + + private fun descent(node: AVLNode, height: Int) { + heightMax = max(heightMax, height) + val left = node.left + val right = node.right + + if (left != null) { + descent(left, height + 1) + } + + if (right == mainRight && heightR == 0) { + heightL = heightMax + heightMax = 0 + } + + if (right != null) { + descent(right, height + 1) + } + } +} From b8cc4828e308554ca72f6ed7a1a7de944c64f894 Mon Sep 17 00:00:00 2001 From: Georgy S Date: Mon, 17 Apr 2023 14:07:00 +0300 Subject: [PATCH 09/84] feat: Add fuzzers with partial functionality. --- .../kotlin/utils/fuzzers/AVLStructFuzzer.kt | 7 + .../kotlin/utils/fuzzers/BINStructFuzzer.kt | 16 +++ .../kotlin/utils/fuzzers/RBStructFuzzer.kt | 16 +++ .../kotlin/utils/fuzzers/TreeStructFuzzer.kt | 128 ++++++++++++++++++ 4 files changed, 167 insertions(+) create mode 100644 lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt create mode 100644 lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt create mode 100644 lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt create mode 100644 lib/src/test/kotlin/utils/fuzzers/TreeStructFuzzer.kt diff --git a/lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt b/lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt new file mode 100644 index 0000000..01d49c5 --- /dev/null +++ b/lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt @@ -0,0 +1,7 @@ +package utils.fuzzers + +import treelib.avlTree.AVLNode + +class AVLStructFuzzer>(){ +// TODO +} \ No newline at end of file diff --git a/lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt b/lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt new file mode 100644 index 0000000..5ce3959 --- /dev/null +++ b/lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt @@ -0,0 +1,16 @@ +package utils.fuzzers + +import treelib.binTree.BINNode +import treelib.binTree.BINStateContainer +import treelib.binTree.BINStruct +import utils.BINAnalyzer + +class BINStructFuzzer>( + override val baseInput: Array, + override val assertMethod: (input: String) -> Unit +): TreeStructFuzzer, BINAnalyzer, BINStateContainer, BINStruct>() { + + override fun createTreeStruct(): BINStruct = BINStruct() + + override fun createAnalyzer(): BINAnalyzer = BINAnalyzer(assertMethod) +} \ No newline at end of file diff --git a/lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt b/lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt new file mode 100644 index 0000000..6b59799 --- /dev/null +++ b/lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt @@ -0,0 +1,16 @@ +package utils.fuzzers + +import treelib.rbTree.RBNode +import treelib.rbTree.RBStateContainer +import treelib.rbTree.RBStruct +import utils.RBAnalyzer + +class RBStructFuzzer>( + override val baseInput: Array, + override val assertMethod: (input: String) -> Unit +): TreeStructFuzzer, RBAnalyzer, RBStateContainer, RBStruct>() { + + override fun createTreeStruct(): RBStruct = RBStruct() + + override fun createAnalyzer(): RBAnalyzer = RBAnalyzer(assertMethod) +} \ No newline at end of file diff --git a/lib/src/test/kotlin/utils/fuzzers/TreeStructFuzzer.kt b/lib/src/test/kotlin/utils/fuzzers/TreeStructFuzzer.kt new file mode 100644 index 0000000..a5390b9 --- /dev/null +++ b/lib/src/test/kotlin/utils/fuzzers/TreeStructFuzzer.kt @@ -0,0 +1,128 @@ +package utils.fuzzers + +import treelib.abstractTree.Node +import treelib.abstractTree.StateContainer +import treelib.abstractTree.TreeStruct +import kotlin.random.Random +import utils.Analyzer +import treelib.singleObjects.exceptions.* +import kotlin.random.nextInt +import utils.TreeStructWrapper +import java.io.File +import java.time.Instant + +abstract class TreeStructFuzzer< + Pack : Comparable, + NodeType : Node, + AnalyzerType : Analyzer, + State : StateContainer, + TreeStructType : TreeStruct, + > { + abstract val baseInput: Array + + protected abstract val assertMethod: (input: String) -> Unit + + private var saveFlag: Boolean = false + + private var dirPath: String? = null + + protected val treeWrapper = TreeStructWrapper() + + protected abstract fun createTreeStruct(): TreeStructType + + protected abstract fun createAnalyzer(): AnalyzerType + + /** + * testNumbers - How many times fuzzer would be run + * inputSize - How many elements from baseInput would be used + * **/ + fun fuzzInvariantInsert(testNumbers: Int, inputSize: Int? = null) { + val dataSize: Int = checkCorrectInput(testNumbers, inputSize) + + for (iterations in 0 until testNumbers) { + val treeStruct = createTreeStruct() + println(dataSize) + val testSetIndexes = getInputSetIndexes(dataSize) + val testID = "${Instant.now().toEpochMilli() + iterations}-insert" + val analyzer = createAnalyzer() + + analyzer.message = "$testID: " + + if (saveFlag) saveCurrentTestSet(testID, testSetIndexes) + + try { + for (index in testSetIndexes) { + treeStruct.insert(baseInput[index]) + } + } catch (ex: Exception) { + exceptionsCatch(ex) + } + + val root = treeWrapper.getPrivateNode(treeStruct, "root") + // todo: probably won't work with junit.fail() + root?.let { analyzer.checkTree(it) } ?: assertMethod("The root was not created in the test $testID") + } + } + + fun fuzzInvariantDelete(testNumbers: Int, inputSize: Int? = null) { + val dataSize: Int = checkCorrectInput(testNumbers, inputSize) + TODO("DON'T IMPLEMENTED YET") + } + + fun fuzzInvariant(testNumbers: Int, inputSize: Int? = null) { + val dataSize: Int = checkCorrectInput(testNumbers, inputSize) + TODO("DON'T IMPLEMENTED YET") + } + + private fun checkCorrectInput(testNumbers: Int, inputSize: Int?): Int { + val dataSize: Int + + if (inputSize == null) dataSize = baseInput.size + else dataSize = inputSize + + if (dataSize > baseInput.size) throw BugInImplementException("inputSize > size of the baseInput") + return dataSize + } + + private fun getInputSetIndexes(inputSize: Int): List { + return generateSequence { Random.nextInt(baseInput.indices) }.distinct().take(inputSize).toList() + } + + private fun exceptionsCatch(ex: Exception) { + when (ex) { + is BugInImplementException, + is IllegalBaseNodeException, + is IllegalNodeStateException, + is ImpossibleCaseException, + is MultithreadingException, + is NonExistentValueException, + -> {/*TODO: Implement */ + } + + else -> throw ex + } + } + + fun saveNextTestSets(dirName: String) { + dirPath = dirName + val file = File("./$dirPath") + file.mkdir() + if (file.isDirectory) saveFlag = true + } + + fun dontSaveNextTestSets() { + saveFlag = false + } + + private fun saveCurrentTestSet(testId: String, testSet: List) { + val file = File("./$dirPath/$testId.txt") + file.createNewFile() +// println("./$dirPath/$testId.txt") + for (index in testSet) { +// print("${baseInput[index]} ") + file.appendText("${baseInput[index]} \n") + } +// println() + } + +} \ No newline at end of file From d1cba855e5185c4da0d2094e8de0c543e184ebdd Mon Sep 17 00:00:00 2001 From: Georgy S Date: Mon, 17 Apr 2023 14:13:04 +0300 Subject: [PATCH 10/84] fix: Fix bug in AVLStruct.find method. --- .../kotlin/treelib/abstractTree/TreeStruct.kt | 6 +++--- lib/src/test/kotlin/treelib/RBStructTest.kt | 21 +++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt index ebdb05c..d2fe865 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt @@ -133,7 +133,7 @@ abstract class TreeStruct< protected fun findItem(obj: Pack): State { var currentNode = root - if (root == null) return generateStateFind(null) + if (root == null) return generateStateFind(null, null) while (true) { if (obj == currentNode?.value) return generateStateFind(currentNode, currentNode) @@ -141,7 +141,7 @@ abstract class TreeStruct< currentNode?.let { if (obj > it.value) currentNode = it.right else currentNode = it.left - } ?: return generateStateFind(null) + } ?: return generateStateFind(null, null) } } } @@ -166,7 +166,7 @@ abstract class TreeStruct< } updateNode.value = item - return generateStateInsert(null) + return generateStateInsert(null, null) } protected abstract fun generateStateDelete( diff --git a/lib/src/test/kotlin/treelib/RBStructTest.kt b/lib/src/test/kotlin/treelib/RBStructTest.kt index 5995dd4..606ca40 100644 --- a/lib/src/test/kotlin/treelib/RBStructTest.kt +++ b/lib/src/test/kotlin/treelib/RBStructTest.kt @@ -7,6 +7,7 @@ import treelib.rbTree.RBStruct import treelib.singleObjects.Markers import utils.RBAnalyzer import utils.TreeStructWrapper +import utils.fuzzers.RBStructFuzzer import kotlin.test.assertEquals @DisplayName("Test: Red-Black Tree Struct") @@ -30,6 +31,7 @@ class RBStructTest { assertAll( { assertEquals(root?.value, 6) }, { assertEquals(root?.color, Markers.BLACK) }, + { analyzer.checkTree(root!!) } ) } @@ -41,6 +43,7 @@ class RBStructTest { assertAll( { assertEquals(root?.left?.value, 3) }, { assertEquals(root?.left?.color, Markers.RED) }, + { analyzer.checkTree(root!!) } ) } @@ -52,6 +55,7 @@ class RBStructTest { assertAll( { assertEquals(root?.right?.value, 8) }, { assertEquals(root?.right?.color, Markers.RED) }, + { analyzer.checkTree(root!!) } ) } @@ -66,6 +70,7 @@ class RBStructTest { { assertEquals(root?.left?.value, 3) }, { assertEquals(root?.right?.color, Markers.RED) }, { assertEquals(root?.left?.color, Markers.RED) }, + { analyzer.checkTree(root!!) } ) } @@ -79,6 +84,7 @@ class RBStructTest { assertAll( { assertEquals(root?.value, 8) }, { assertEquals(root?.color, Markers.BLACK) }, + { analyzer.checkTree(root!!) } ) } @@ -91,6 +97,7 @@ class RBStructTest { assertAll( { assertEquals(8, root?.value) }, { assertEquals(Markers.BLACK, root?.color) }, + { analyzer.checkTree(root!!) } ) } @@ -103,6 +110,20 @@ class RBStructTest { assertAll( { assertEquals(3, root?.value) }, { assertEquals(Markers.BLACK, root?.color) }, + { analyzer.checkTree(root!!) } ) } + + @Test + fun `fazzer test`() { + val fazzer = RBStructFuzzer(arrayOf(1, 2, 3, 4, 5, 6, 7,8,9,20,100,123,234,556,345677,88765,43,364,23456,2754), ::testAssert) + fazzer.saveNextTestSets("TEST_TEST") + + assertAll( + { + fazzer.fuzzInvariantInsert(15, 10) + } + ) + } + } \ No newline at end of file From 660c98c15c0ae297d81fe86b66f0281b4be2b97b Mon Sep 17 00:00:00 2001 From: Artem Date: Sat, 15 Apr 2023 15:27:37 +0300 Subject: [PATCH 11/84] fix: Partially change exceptions --- .../kotlin/treelib/avlTree/AVLBalancer.kt | 25 ++++----- .../main/kotlin/treelib/rbTree/RBBalancer.kt | 55 +++++++++---------- 2 files changed, 37 insertions(+), 43 deletions(-) diff --git a/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt b/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt index 703ea69..5f80a87 100644 --- a/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt +++ b/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt @@ -1,11 +1,8 @@ package treelib.avlTree import treelib.abstractTree.balanced.BalancerNoParent -import treelib.singleObjects.exceptions.IllegalBaseNodeException -import treelib.singleObjects.exceptions.IllegalNodeStateException -class AVLBalancer>(private var root: AVLNode?) : - BalancerNoParent, AVLStateContainer>() { +class AVLBalancer>(private var root: AVLNode?): BalancerNoParent, AVLStateContainer>() { private fun updateBalance(node: AVLNode?): Int { return (getHeight(node?.left) - getHeight(node?.right)).toInt() } @@ -16,19 +13,18 @@ class AVLBalancer>(private var root: AVLNode?) : private fun updateHeight(currentNode: AVLNode?) { if (currentNode != null) - currentNode.height = maxOf(getHeight(currentNode.left), getHeight(currentNode.right)) + 1u + currentNode.height = maxOf(getHeight(currentNode.left), getHeight(currentNode.right))+1u } - override fun balance(state: AVLStateContainer): AVLNode { - val node = state.contentNode - root = state.root - return balance(root, node?.value ?: throw IllegalBaseNodeException()) + override fun balance(stateContainer: AVLStateContainer): AVLNode { + val node = stateContainer.contentNode ?: throw IllegalStateException("") // IllegalBaseNodeException("A non-existent node (null) was passed to the method") + root = stateContainer.root + return balance(root, node.value) } - - // В баланс передаем родителя ноды, которую будем удалять + /*** In the method we pass the parent of the removed/inserted node ***/ private fun balance(currentNode: AVLNode?, value: Pack): AVLNode { if (currentNode == null) { - throw IllegalBaseNodeException() + throw NullPointerException() } when { currentNode.value < value -> currentNode.right = balance(currentNode.right, value) @@ -38,7 +34,7 @@ class AVLBalancer>(private var root: AVLNode?) : val balance = updateBalance(currentNode) if (balance == -2) { if (updateBalance(currentNode.right) == 1) { - currentNode.right = currentNode.right?.let { rightRotate(it) } ?: throw IllegalNodeStateException() + currentNode.right = currentNode.right?.let { rightRotate(it) } ?: throw NullPointerException() // IllegalNodeStateException() updateHeight(currentNode.right?.right) } val balancedNode = leftRotate(currentNode) @@ -48,7 +44,7 @@ class AVLBalancer>(private var root: AVLNode?) : } if (balance == 2) { if (updateBalance(currentNode.left) == -1) { - currentNode.left = currentNode.left?.let { leftRotate(it) } ?: throw IllegalNodeStateException() + currentNode.left = currentNode.left?.let { leftRotate(it) } ?: throw NullPointerException() // IllegalNodeStateException("There is no node required by the condition of the algorithm") updateHeight(currentNode.left?.left) } val balanceNode = rightRotate(currentNode) @@ -58,4 +54,5 @@ class AVLBalancer>(private var root: AVLNode?) : } return currentNode } + } diff --git a/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt b/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt index fe73c5b..67e5427 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt @@ -2,9 +2,6 @@ package treelib.rbTree import treelib.abstractTree.balanced.BalancerParent import treelib.singleObjects.Markers -import treelib.singleObjects.exceptions.IllegalBaseNodeException -import treelib.singleObjects.exceptions.IllegalNodeStateException -import treelib.singleObjects.exceptions.ImpossibleCaseException class RBBalancer>(private var root: RBNode?): BalancerParent, RBStateContainer>() { @@ -30,7 +27,7 @@ class RBBalancer>(private var root: RBNode?): Balan private fun getRoot(node: RBNode): RBNode { var currentNode = node while (currentNode.parent != null) - currentNode = currentNode.parent ?: throw IllegalNodeStateException() + currentNode = currentNode.parent ?: throw NullPointerException() root = currentNode root?.color = Markers.BLACK return currentNode @@ -38,12 +35,13 @@ class RBBalancer>(private var root: RBNode?): Balan private fun nodeIsLeaf(node: RBNode?): Boolean { if (node == null) - throw IllegalBaseNodeException() + throw NullPointerException() return node.right == null && node.left == null } - override fun balance(state: RBStateContainer): RBNode { - val node = state.contentNode ?: throw IllegalBaseNodeException() + override fun balance(stateContainer: RBStateContainer): RBNode { + val node = stateContainer.contentNode ?: + throw IllegalStateException() //IllegalBaseNodeException("A non-existent node (null) was passed to the method") val uncle = getUncle(node) when { /** node insertion case **/ @@ -58,14 +56,14 @@ class RBBalancer>(private var root: RBNode?): Balan return getRoot(currentNode) } - var parent = currentNode.parent ?: throw IllegalNodeStateException() + var parent = currentNode.parent ?: throw IllegalStateException() // в данном случае родитель не может быть null when (parent) { parent.parent?.left -> { if (currentNode == parent.right) { leftRotate(parent) currentNode = parent } - parent = currentNode.parent?.parent ?: throw IllegalNodeStateException() + parent = currentNode.parent?.parent ?: throw IllegalStateException() // IllegalNodeStateException() currentNode = rightRotate(parent) currentNode.color = Markers.BLACK currentNode.right?.color = Markers.RED @@ -76,17 +74,17 @@ class RBBalancer>(private var root: RBNode?): Balan rightRotate(parent) currentNode = parent } - parent = currentNode.parent?.parent ?: throw IllegalNodeStateException() + parent = currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() currentNode = leftRotate(parent) currentNode.color = Markers.BLACK currentNode.right?.color = Markers.RED currentNode.left?.color = Markers.RED } - else -> throw IllegalNodeStateException() + else -> throw IllegalStateException() // невозможное условие выполнения } if (currentNode.parent == null) root = currentNode - return root ?: throw IllegalNodeStateException() + return root ?: throw NullPointerException() } /** node removal cases **/ node.color == Markers.RED && (node.right != null || node.left != null) -> @@ -116,12 +114,11 @@ class RBBalancer>(private var root: RBNode?): Balan firstCase(node, null) } - - else -> throw IllegalNodeStateException() + else -> throw IllegalStateException() } } } - throw ImpossibleCaseException() + throw IllegalStateException() } private fun afterInsert(node: RBNode): RBNode { @@ -130,7 +127,7 @@ class RBBalancer>(private var root: RBNode?): Balan val uncle = getUncle(currentNode) if (uncle?.color == Markers.RED) { currentNode.parent?.color = Markers.BLACK - currentNode = currentNode.parent?.parent ?: throw IllegalNodeStateException() + currentNode = currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() currentNode.color = Markers.RED uncle.color = Markers.BLACK } @@ -145,7 +142,7 @@ class RBBalancer>(private var root: RBNode?): Balan /** black node removal case **/ private fun firstCase(parent: RBNode?, node: RBNode?): RBNode { return when { - parent == null && node == null -> throw IllegalBaseNodeException() + parent == null && node == null -> throw NullPointerException() parent != null -> { when (parent.color) { Markers.RED -> secondCase(parent, node) @@ -154,13 +151,13 @@ class RBBalancer>(private var root: RBNode?): Balan getRoot(parent) } - else -> getRoot(node ?: throw IllegalBaseNodeException()) + else -> getRoot(node ?: throw NullPointerException() /* IllegalNodeStateException() */) } } /** parent is red **/ private fun secondCase(parent: RBNode, node: RBNode?) { - var brother = getBrother(parent, node) ?: throw IllegalBaseNodeException() + var brother = getBrother(parent, node) ?: throw NullPointerException() // IllegalNodeStateException() if (brother.color == Markers.RED) throw NullPointerException() @@ -187,7 +184,7 @@ class RBBalancer>(private var root: RBNode?): Balan brother.color = Markers.RED } else { - throw NullPointerException() + throw IllegalStateException() } } parent.right -> @@ -206,17 +203,17 @@ class RBBalancer>(private var root: RBNode?): Balan brother.right?.color = Markers.BLACK } else { - throw NullPointerException() + throw IllegalStateException() } } - else -> throw NullPointerException() + else -> throw IllegalStateException() } } /** parent is black **/ private fun thirdCase(parent: RBNode, node: RBNode?) { - val brother = getBrother(parent, node) ?: throw NullPointerException() + val brother = getBrother(parent, node) ?: throw NullPointerException() // IllegalNodeStateException() when (brother.color) { Markers.RED -> thirdCaseSubFirst(brother, parent) Markers.BLACK -> thirdCaseSubSecond(brother, parent) @@ -228,7 +225,7 @@ class RBBalancer>(private var root: RBNode?): Balan when (brother) { brother.parent?.left -> { - var rightBrotherSon = brother.right ?: throw NullPointerException() + var rightBrotherSon = brother.right ?: throw NullPointerException() // IllegalNodeStateException() if (rightBrotherSon.right?.color != Markers.RED && rightBrotherSon.left?.color != Markers.RED) { rightBrotherSon.color = Markers.RED @@ -244,7 +241,7 @@ class RBBalancer>(private var root: RBNode?): Balan rightBrotherSon.color = Markers.RED leftRotate(rightBrotherSon) - rightBrotherSon = rightBrotherSon.parent ?: throw NullPointerException() + rightBrotherSon = rightBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() rightBrotherSon.color = Markers.BLACK } @@ -260,14 +257,14 @@ class RBBalancer>(private var root: RBNode?): Balan if (leftBrotherSon.right?.color != Markers.RED && leftBrotherSon.left?.color != Markers.RED) { leftBrotherSon.color = Markers.RED brother.color = Markers.BLACK - leftRotate(brother.parent ?: throw NullPointerException()) + leftRotate(brother.parent ?: throw NullPointerException()) // IllegalNodeStateException() return } if (leftBrotherSon.left?.color == Markers.RED) { rightRotate(leftBrotherSon) leftBrotherSon.color = Markers.RED - leftBrotherSon = leftBrotherSon.parent ?: throw NullPointerException() + leftBrotherSon = leftBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() leftBrotherSon.color = Markers.BLACK } @@ -277,7 +274,7 @@ class RBBalancer>(private var root: RBNode?): Balan leftRotate(parent) } } - else -> throw NullPointerException() + else -> throw IllegalStateException() } } @@ -315,7 +312,7 @@ class RBBalancer>(private var root: RBNode?): Balan } } - else -> throw NullPointerException() + else -> throw IllegalStateException() } } From 3270e8db74b38d72d77a4daf1121e38f76839e59 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 17 Apr 2023 14:37:18 +0300 Subject: [PATCH 12/84] feat: Implement neo4j database sketch --- lib/build.gradle.kts | 10 +- lib/src/main/kotlin/CONTAINER.conf | 3 + lib/src/main/kotlin/DataBase.kt | 172 ++++++++++++++++++++++++ lib/src/main/kotlin/testNeo4j.sh | 15 +++ lib/src/main/kotlin/treelib/DBNodeRB.kt | 14 ++ settings.gradle.kts | 2 +- 6 files changed, 213 insertions(+), 3 deletions(-) create mode 100644 lib/src/main/kotlin/CONTAINER.conf create mode 100644 lib/src/main/kotlin/DataBase.kt create mode 100644 lib/src/main/kotlin/testNeo4j.sh create mode 100644 lib/src/main/kotlin/treelib/DBNodeRB.kt diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 09124dc..0f9f88e 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -19,11 +19,17 @@ repositories { } dependencies { + api("org.apache.commons:commons-math3:3.6.1") + implementation("com.google.guava:guava:31.1-jre") + + val neo4jCore = "4.0.5" + implementation("org.neo4j", "neo4j-ogm-core", neo4jCore) + implementation("org.neo4j", "neo4j-ogm-bolt-driver", neo4jCore) + testImplementation("io.mockk:mockk:1.13.4") testImplementation("org.jetbrains.kotlin:kotlin-test-junit5:1.8.10") testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.2") - api("org.apache.commons:commons-math3:3.6.1") - implementation("com.google.guava:guava:31.1-jre") + implementation(kotlin("stdlib-jdk8")) } tasks.test { diff --git a/lib/src/main/kotlin/CONTAINER.conf b/lib/src/main/kotlin/CONTAINER.conf new file mode 100644 index 0000000..9b9fb0a --- /dev/null +++ b/lib/src/main/kotlin/CONTAINER.conf @@ -0,0 +1,3 @@ +CONTAINER_NAME=neo4j-db +PASSWORD="test-neo4j" +VOLUMEDIR="/volume" \ No newline at end of file diff --git a/lib/src/main/kotlin/DataBase.kt b/lib/src/main/kotlin/DataBase.kt new file mode 100644 index 0000000..ddc72a3 --- /dev/null +++ b/lib/src/main/kotlin/DataBase.kt @@ -0,0 +1,172 @@ + +import org.neo4j.driver.AuthTokens +import org.neo4j.driver.Driver +import org.neo4j.driver.GraphDatabase +import org.neo4j.driver.exceptions.SessionExpiredException +import treelib.DBNodeRB +import treelib.singleObjects.Markers +import java.io.Closeable +import java.io.IOException +import java.util.* + +class Neo4jRepository: Closeable { + + private var driver: Driver? = null + + fun open(uri: String, username: String, password: String) { + try { + driver = GraphDatabase.driver(uri, AuthTokens.basic(username, password)) + } catch(ex: IllegalArgumentException) { + throw IOException() + } catch(ex: SessionExpiredException) { + throw IOException() + } + + } + + // я наверное смогу получить рут, используя фильтр что-то вроде: на данный узел не указывает ни один другой узел с отношением [left_child] / [right_child] + + fun , V> saveChanges(preOrder: Array>, inOrder: Array>) { + + /*** сюда по ощущениям лучше всего добавлять именно то поддерево исходного дерева, которое было изменено ***/ + val session = driver?.session() ?: throw IOException() + + var inOrderIndex = 0 + var preOrderIndex = 0 + val set = HashSet>() + val stack = LinkedList>() + + while (preOrderIndex in preOrder.indices) { + do { + val currentNode = preOrder[preOrderIndex] + if (preOrderIndex == 0) { + session.executeWrite { tx -> + tx.run( + "MERGE(:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY})", + mutableMapOf( + "nodeValue" to currentNode.value, + "nodeKey" to currentNode.key, + "nodeColor" to currentNode.color.toString(), + "nodeX" to currentNode.x, + "nodeY" to currentNode.y + ) + ) + } + } + if (!stack.isEmpty()) { + if ( set.contains( stack.peek() ) ) { + set.remove(stack.peek()) + val parentNode = stack.pop() + session.executeWrite {tx -> + tx.run("MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + + "MERGE (parent)-[:RIGHT_SON]->(son)", + mutableMapOf( + "parentNodeValue" to parentNode.value, + "parentNodeKey" to parentNode.key, + "parentNodeColor" to parentNode.color.toString(), + "parentNodeX" to parentNode.x, + "parentNodeY" to parentNode.y, + "nodeValue" to currentNode.value, + "nodeKey" to currentNode.key, + "nodeColor" to currentNode.color.toString(), + "nodeX" to currentNode.x, + "nodeY" to currentNode.y + ) + ) + } + } + else { + val parentNode = stack.peek() + session.executeWrite {tx -> + tx.run("MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + + "MERGE (parent)-[:LEFT_SON]->(son)", + mutableMapOf( + "parentNodeValue" to parentNode.value, + "parentNodeKey" to parentNode.key, + "parentNodeColor" to parentNode.color.toString(), + "parentNodeX" to parentNode.x, + "parentNodeY" to parentNode.y, + "nodeValue" to currentNode.value, + "nodeKey" to currentNode.key, + "nodeColor" to currentNode.color.toString(), + "nodeX" to currentNode.x, + "nodeY" to currentNode.y + ) + ) + } + } + } + stack.push(currentNode) + } while (preOrder[preOrderIndex++] != inOrder[inOrderIndex] && preOrderIndex < preOrder.size) + + var currentNode: DBNodeRB? = null + + while(!stack.isEmpty() && inOrderIndex < inOrder.size && stack.peek().key == inOrder[inOrderIndex].key) { + currentNode = stack.pop() + ++inOrderIndex + } + + if (currentNode != null) { + set.add(currentNode) + stack.push(currentNode) + } + + } + + session.close() + } + + // Это скорее всего будем запускать при открытии приложения, нужно будет сразу восстановить дерево + + fun exportRBtree() { + + val session = driver?.session() ?: throw IOException() + var preOrder: List>> = listOf() + var inOrder: List>> = listOf() + + session.executeRead {tx -> + preOrder = tx.run("MATCH (node: Node) " + + "RETURN node.value, node.key, node.color, node.x, node.y ").list() + .map{ DBNodeRB( + value = it.values().get(0).toString(), + key = it.values().get(1).toString(), + color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, + x = it.values().get(3).toString().toDouble(), + y = it.values().get(4).toString().toDouble()) + } + + inOrder = tx.run("MATCH (node: Node) " + + "RETURN node.value, node.key, node.color, node.x, node.y " + + "ORDER BY node.key").list() + .map{ DBNodeRB( + value = it.values().get(0).toString(), + key = it.values().get(1).toString(), + color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, + x = it.values().get(3).toString().toDouble(), + y = it.values().get(4).toString().toDouble()) + } + } + + session.close() + + } + + override fun close() { + driver?.close() + } +} + +// neo4j-admin, backup, restore +/* +у меня есть вершины и ребра между ними, надо уметь сохранять дерево в базе, но как? +вопрос: когда заносить изменения в бд и как это реализовывать? +надо еще подумать над оптимизацией, те чтобы не пересобирать дерево в бд каждый раз, когда мы добавили за сессию всего один узел + +root = tx.run("MATCH (parent: Node)-->(son: Node) " + + "WHERE NOT ()-->(parent) " + + "RETURN parent.value, parent.key, parent.color, parent.x, parent.y").list().map {it.values()}.get(0) + */ diff --git a/lib/src/main/kotlin/testNeo4j.sh b/lib/src/main/kotlin/testNeo4j.sh new file mode 100644 index 0000000..97ad8db --- /dev/null +++ b/lib/src/main/kotlin/testNeo4j.sh @@ -0,0 +1,15 @@ + +BASEDIR=$(realpath "$(dirname "$0")") + +. "${BASEDIR}/CONTAINER.conf" + +docker run \ + --rm \ + --name "CONTAINER_NAME" \ + --volume=$HOME/neo4j/data:/data \ + --volume=$HOME/neo4j/logs:/logs \ + --publish=7474:7474 --publish=7687:7687 \ + --env NEO4J_AUTH=neo4j/"$PASSWORD" \ + neo4j:latest \ + +#docker stop neo4j:latest diff --git a/lib/src/main/kotlin/treelib/DBNodeRB.kt b/lib/src/main/kotlin/treelib/DBNodeRB.kt new file mode 100644 index 0000000..d048930 --- /dev/null +++ b/lib/src/main/kotlin/treelib/DBNodeRB.kt @@ -0,0 +1,14 @@ +package treelib + +import treelib.singleObjects.Markers + + +class DBNodeRB, V>(val value: V, + val key: K, + val color: Markers = Markers.RED, + val x: Double = 0.0, + val y: Double = 0.0) { + + + +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 21643d4..26b0762 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -7,5 +7,5 @@ * in the user manual at https://docs.gradle.org/8.0/userguide/multi_project_builds.html */ -rootProject.name = "TreeLib" +rootProject.name = "treelib" include("lib") From b7ed0c41654991f3a6e2ec99f22b422cbe7987e9 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 17 Apr 2023 19:32:32 +0300 Subject: [PATCH 13/84] feat: Implement initialize tree from DB --- lib/src/main/kotlin/Controller.kt | 50 +++++++++++++++++ lib/src/main/kotlin/DataBase.kt | 55 +++++++++---------- lib/src/main/kotlin/treelib/DBNodeRB.kt | 9 +-- lib/src/main/kotlin/treelib/Main.kt | 39 +++++++++++++ .../main/kotlin/treelib/abstractTree/Tree.kt | 12 ++-- .../kotlin/treelib/abstractTree/TreeStruct.kt | 21 +++---- 6 files changed, 135 insertions(+), 51 deletions(-) create mode 100644 lib/src/main/kotlin/Controller.kt create mode 100644 lib/src/main/kotlin/treelib/Main.kt diff --git a/lib/src/main/kotlin/Controller.kt b/lib/src/main/kotlin/Controller.kt new file mode 100644 index 0000000..cc4e699 --- /dev/null +++ b/lib/src/main/kotlin/Controller.kt @@ -0,0 +1,50 @@ +import treelib.DBNodeRB +import treelib.rbTree.RBStruct +import treelib.rbTree.RBTree +import treelib.singleObjects.Container + +class Controller { + + fun initTree() { + val neo4jDB = Neo4jRepository() + neo4jDB.open("bolt://localhost:7687", "neo4j", "test-neo4j") + /*** orders.first = preOrder, orders.second = inOrder ***/ + val orders: Pair>>>, List>>>> = + neo4jDB.exportRBtree() + + val RBtree = RBStruct>>() + RBtree.restoreTreeFromDatabase(orders.first, orders.second) + } + + fun saveTree() { + val tree = RBTree() + tree.putItem(Pair(25, 1)) + tree.putItem(Pair(15, 1)) + tree.putItem(Pair(50, 1)) + tree.putItem(Pair(10, 1)) + tree.putItem(Pair(22, 1)) + tree.putItem(Pair(35, 1)) + tree.putItem(Pair(70, 1)) + tree.putItem(Pair(4, 1)) + tree.putItem(Pair(12, 1)) + tree.putItem(Pair(18, 1)) + tree.putItem(Pair(24, 1)) + tree.putItem(Pair(31, 1)) + tree.putItem(Pair(44, 1)) + tree.putItem(Pair(66, 1)) + tree.putItem(Pair(90, 1)) + + val neo4jDB = Neo4jRepository() + neo4jDB.open("bolt://localhost:7687", "neo4j", "test-neo4j") + + val preOrder = tree.preOrder().map { DBNodeRB(it.value, it.color) } + val inOrder = tree.inOrder().map { DBNodeRB(it.value, it.color) } + + neo4jDB.saveChanges(preOrder.toTypedArray(), inOrder.toTypedArray()) + + neo4jDB.close() + + + } + +} \ No newline at end of file diff --git a/lib/src/main/kotlin/DataBase.kt b/lib/src/main/kotlin/DataBase.kt index ddc72a3..3e94aac 100644 --- a/lib/src/main/kotlin/DataBase.kt +++ b/lib/src/main/kotlin/DataBase.kt @@ -4,6 +4,7 @@ import org.neo4j.driver.Driver import org.neo4j.driver.GraphDatabase import org.neo4j.driver.exceptions.SessionExpiredException import treelib.DBNodeRB +import treelib.singleObjects.Container import treelib.singleObjects.Markers import java.io.Closeable import java.io.IOException @@ -21,31 +22,29 @@ class Neo4jRepository: Closeable { } catch(ex: SessionExpiredException) { throw IOException() } - } - // я наверное смогу получить рут, используя фильтр что-то вроде: на данный узел не указывает ни один другой узел с отношением [left_child] / [right_child] - - fun , V> saveChanges(preOrder: Array>, inOrder: Array>) { + fun > saveChanges(preOrder: Array>, inOrder: Array>) { /*** сюда по ощущениям лучше всего добавлять именно то поддерево исходного дерева, которое было изменено ***/ val session = driver?.session() ?: throw IOException() var inOrderIndex = 0 var preOrderIndex = 0 - val set = HashSet>() - val stack = LinkedList>() + val set = HashSet>() + val stack = LinkedList>() while (preOrderIndex in preOrder.indices) { do { val currentNode = preOrder[preOrderIndex] + currentNode.value as Container<*, *> if (preOrderIndex == 0) { session.executeWrite { tx -> tx.run( "MERGE(:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY})", mutableMapOf( - "nodeValue" to currentNode.value, - "nodeKey" to currentNode.key, + "nodeValue" to currentNode.value.pair.second, + "nodeKey" to currentNode.value.pair.first, "nodeColor" to currentNode.color.toString(), "nodeX" to currentNode.x, "nodeY" to currentNode.y @@ -57,19 +56,20 @@ class Neo4jRepository: Closeable { if ( set.contains( stack.peek() ) ) { set.remove(stack.peek()) val parentNode = stack.pop() + parentNode.value as Container<*, *> session.executeWrite {tx -> tx.run("MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + "MERGE (parent)-[:RIGHT_SON]->(son)", mutableMapOf( - "parentNodeValue" to parentNode.value, - "parentNodeKey" to parentNode.key, + "parentNodeValue" to parentNode.value.pair.second, + "parentNodeKey" to parentNode.value.pair.first, "parentNodeColor" to parentNode.color.toString(), "parentNodeX" to parentNode.x, "parentNodeY" to parentNode.y, - "nodeValue" to currentNode.value, - "nodeKey" to currentNode.key, + "nodeValue" to currentNode.value.pair.second, + "nodeKey" to currentNode.value.pair.first, "nodeColor" to currentNode.color.toString(), "nodeX" to currentNode.x, "nodeY" to currentNode.y @@ -79,19 +79,20 @@ class Neo4jRepository: Closeable { } else { val parentNode = stack.peek() + parentNode.value as Container<*, *> session.executeWrite {tx -> tx.run("MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + "MERGE (parent)-[:LEFT_SON]->(son)", mutableMapOf( - "parentNodeValue" to parentNode.value, - "parentNodeKey" to parentNode.key, + "parentNodeValue" to parentNode.value.pair.second, + "parentNodeKey" to parentNode.value.pair.first, "parentNodeColor" to parentNode.color.toString(), "parentNodeX" to parentNode.x, "parentNodeY" to parentNode.y, - "nodeValue" to currentNode.value, - "nodeKey" to currentNode.key, + "nodeValue" to currentNode.value.pair.second, + "nodeKey" to currentNode.value.pair.first, "nodeColor" to currentNode.color.toString(), "nodeX" to currentNode.x, "nodeY" to currentNode.y @@ -103,9 +104,9 @@ class Neo4jRepository: Closeable { stack.push(currentNode) } while (preOrder[preOrderIndex++] != inOrder[inOrderIndex] && preOrderIndex < preOrder.size) - var currentNode: DBNodeRB? = null + var currentNode: DBNodeRB? = null - while(!stack.isEmpty() && inOrderIndex < inOrder.size && stack.peek().key == inOrder[inOrderIndex].key) { + while(!stack.isEmpty() && inOrderIndex < inOrder.size && stack.peek().value == inOrder[inOrderIndex].value) { currentNode = stack.pop() ++inOrderIndex } @@ -120,20 +121,17 @@ class Neo4jRepository: Closeable { session.close() } - // Это скорее всего будем запускать при открытии приложения, нужно будет сразу восстановить дерево - - fun exportRBtree() { + fun exportRBtree(): Pair>>>, List>>>>{ val session = driver?.session() ?: throw IOException() - var preOrder: List>> = listOf() - var inOrder: List>> = listOf() + var preOrder: List>>> = listOf() + var inOrder: List>>> = listOf() session.executeRead {tx -> preOrder = tx.run("MATCH (node: Node) " + "RETURN node.value, node.key, node.color, node.x, node.y ").list() .map{ DBNodeRB( - value = it.values().get(0).toString(), - key = it.values().get(1).toString(), + value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, x = it.values().get(3).toString().toDouble(), y = it.values().get(4).toString().toDouble()) @@ -143,16 +141,17 @@ class Neo4jRepository: Closeable { "RETURN node.value, node.key, node.color, node.x, node.y " + "ORDER BY node.key").list() .map{ DBNodeRB( - value = it.values().get(0).toString(), - key = it.values().get(1).toString(), + value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, x = it.values().get(3).toString().toDouble(), y = it.values().get(4).toString().toDouble()) } } - + session.close() + return Pair(preOrder, inOrder) + } override fun close() { diff --git a/lib/src/main/kotlin/treelib/DBNodeRB.kt b/lib/src/main/kotlin/treelib/DBNodeRB.kt index d048930..b28228f 100644 --- a/lib/src/main/kotlin/treelib/DBNodeRB.kt +++ b/lib/src/main/kotlin/treelib/DBNodeRB.kt @@ -3,12 +3,7 @@ package treelib import treelib.singleObjects.Markers -class DBNodeRB, V>(val value: V, - val key: K, +class DBNodeRB>(val value: Pack, val color: Markers = Markers.RED, val x: Double = 0.0, - val y: Double = 0.0) { - - - -} + val y: Double = 0.0) diff --git a/lib/src/main/kotlin/treelib/Main.kt b/lib/src/main/kotlin/treelib/Main.kt new file mode 100644 index 0000000..0aeb3e0 --- /dev/null +++ b/lib/src/main/kotlin/treelib/Main.kt @@ -0,0 +1,39 @@ +package treelib + +import Controller + + +fun main() { + // 25, 15, 10, 4, 12, 22, 18, 24, 50, 35, 31, 44, 70, 66, 90 + // 4, 10, 12, 15, 18, 22, 24, 25, 31, 35, 44, 50, 66, 70, 90 + + /* + + val neo4jRep = Neo4jRepository() + val a1 = DBNodeRB(Container(Pair(1, 25))) + val a2 = DBNodeRB(Container(Pair(1, 15))) + val a3 = DBNodeRB(Container(Pair(1, 10))) + val a4 = DBNodeRB(Container(Pair(1, 4))) + val a5 = DBNodeRB(Container(Pair(1, 12))) + val a6 = DBNodeRB(Container(Pair(1, 22))) + val a7 = DBNodeRB(Container(Pair(1, 18))) + val a8 = DBNodeRB(Container(Pair(1, 24))) + val a9 = DBNodeRB(Container(Pair(1, 50))) + val a10 = DBNodeRB(Container(Pair(1, 35))) + val a11 = DBNodeRB(Container(Pair(1, 31))) + val a12 = DBNodeRB(Container(Pair(1, 44))) + val a13 = DBNodeRB(Container(Pair(1, 70))) + val a14 = DBNodeRB(Container(Pair(1, 66))) + val a15 = DBNodeRB(Container(Pair(1, 90))) + val preArr = arrayOf(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) + val inArr = arrayOf(a4, a3, a5, a2, a7, a6, a8, a1, a11, a10, a12, a9, a14, a13, a15) + neo4jRep.open("bolt://localhost:7687", "neo4j", "test-neo4j") + neo4jRep.saveChanges(preArr, inArr) + */ + val controller = Controller() + controller.saveTree() + + //neo4jRep.exportRBtree() + + //neo4jRep.close() +} \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/abstractTree/Tree.kt b/lib/src/main/kotlin/treelib/abstractTree/Tree.kt index b64cca1..1607caa 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/Tree.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/Tree.kt @@ -33,15 +33,15 @@ abstract class Tree< treeStruct.delete(wrapForFind(key)) } - private fun createPoorList(info: List>): List> { - val returnInfo = mutableListOf>() - for (element in info) returnInfo.add(element.pair) + private fun createPoorList(info: List): List { + val returnInfo = mutableListOf() + for (element in info) returnInfo.add(element) return returnInfo } - fun inOrder(): List> = createPoorList(treeStruct.inOrder()) + fun inOrder(): List = createPoorList(treeStruct.inOrder()) - fun preOrder(): List> = createPoorList(treeStruct.preOrder()) + fun preOrder(): List = createPoorList(treeStruct.preOrder()) - fun postOrder(): List> = createPoorList(treeStruct.postOrder()) + fun postOrder(): List = createPoorList(treeStruct.postOrder()) } diff --git a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt index d2fe865..2f536d8 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt @@ -162,7 +162,8 @@ abstract class TreeStruct< linkNewNode(currentNode, parentNode) - return generateStateInsert(currentNode, parentNode) + if (parentNode != null) return generateStateInsert(currentNode, parentNode) + else return generateStateInsert(currentNode, currentNode) } updateNode.value = item @@ -258,8 +259,8 @@ abstract class TreeStruct< fun find(obj: Pack): Pack? = findItem(obj).contentNode?.value - fun inOrder(): List { - val arrayNodes = mutableListOf() + fun inOrder(): List { + val arrayNodes = mutableListOf() var flagVisited = 0 var current = root val parents = ArrayDeque() @@ -276,7 +277,7 @@ abstract class TreeStruct< } } current?.let { - arrayNodes.add(it.value) + arrayNodes.add(it) if (it.right != null) { flagVisited = 0 current = it.right @@ -291,9 +292,9 @@ abstract class TreeStruct< return arrayNodes } - fun postOrder(): List { + fun postOrder(): List { val parents = ArrayDeque() - val arrayNodes = mutableListOf() + val arrayNodes = mutableListOf() var flagVisited = 0 var current = root @@ -314,7 +315,7 @@ abstract class TreeStruct< current = it.right flagVisited = 0 } else { - arrayNodes.add(it.value) + arrayNodes.add(it) if (parents.isEmpty()) return@postOrder arrayNodes val parent = parents.removeLast() @@ -328,8 +329,8 @@ abstract class TreeStruct< return arrayNodes } - fun preOrder(): List { - val arrayNodes = mutableListOf() + fun preOrder(): List { + val arrayNodes = mutableListOf() var current: NodeType val queue = ArrayDeque() @@ -337,7 +338,7 @@ abstract class TreeStruct< queue.add(root) while (queue.isNotEmpty()) { current = queue.removeLast() - arrayNodes.add(current.value) + arrayNodes.add(current) if (current.right != null) current.right?.let { queue.add(it) From 366949e530cc6a9c522b28cb9eb3fb8f958a8450 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 17 Apr 2023 20:21:27 +0300 Subject: [PATCH 14/84] fix: Fix adding to database (neo4j) --- lib/src/main/kotlin/DataBase.kt | 82 ++++++++++-------- lib/src/main/kotlin/treelib/DBNodeRB.kt | 10 ++- .../kotlin/treelib/avlTree/AVLBalancer.kt | 15 ++-- .../main/kotlin/treelib/rbTree/RBBalancer.kt | 85 ++++++++++--------- .../main/kotlin/treelib/rbTree/RBStruct.kt | 63 ++++++++++++-- 5 files changed, 161 insertions(+), 94 deletions(-) diff --git a/lib/src/main/kotlin/DataBase.kt b/lib/src/main/kotlin/DataBase.kt index 3e94aac..e7ca4c6 100644 --- a/lib/src/main/kotlin/DataBase.kt +++ b/lib/src/main/kotlin/DataBase.kt @@ -1,4 +1,3 @@ - import org.neo4j.driver.AuthTokens import org.neo4j.driver.Driver import org.neo4j.driver.GraphDatabase @@ -10,21 +9,21 @@ import java.io.Closeable import java.io.IOException import java.util.* -class Neo4jRepository: Closeable { +class Neo4jRepository : Closeable { private var driver: Driver? = null fun open(uri: String, username: String, password: String) { try { driver = GraphDatabase.driver(uri, AuthTokens.basic(username, password)) - } catch(ex: IllegalArgumentException) { - throw IOException() - } catch(ex: SessionExpiredException) { + } catch (ex: IllegalArgumentException) { + throw IOException() + } catch (ex: SessionExpiredException) { throw IOException() } } - fun > saveChanges(preOrder: Array>, inOrder: Array>) { + fun > saveChanges(preOrder: Array>, inOrder: Array>) { /*** сюда по ощущениям лучше всего добавлять именно то поддерево исходного дерева, которое было изменено ***/ val session = driver?.session() ?: throw IOException() @@ -53,15 +52,16 @@ class Neo4jRepository: Closeable { } } if (!stack.isEmpty()) { - if ( set.contains( stack.peek() ) ) { + if (set.contains(stack.peek())) { set.remove(stack.peek()) val parentNode = stack.pop() parentNode.value as Container<*, *> - session.executeWrite {tx -> - tx.run("MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + - "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + - "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + - "MERGE (parent)-[:RIGHT_SON]->(son)", + session.executeWrite { tx -> + tx.run( + "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + + "MERGE (parent)-[:RIGHT_SON]->(son)", mutableMapOf( "parentNodeValue" to parentNode.value.pair.second, "parentNodeKey" to parentNode.value.pair.first, @@ -76,15 +76,15 @@ class Neo4jRepository: Closeable { ) ) } - } - else { + } else { val parentNode = stack.peek() parentNode.value as Container<*, *> - session.executeWrite {tx -> - tx.run("MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + - "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + - "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + - "MERGE (parent)-[:LEFT_SON]->(son)", + session.executeWrite { tx -> + tx.run( + "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + + "MERGE (parent)-[:LEFT_SON]->(son)", mutableMapOf( "parentNodeValue" to parentNode.value.pair.second, "parentNodeKey" to parentNode.value.pair.first, @@ -106,7 +106,7 @@ class Neo4jRepository: Closeable { var currentNode: DBNodeRB? = null - while(!stack.isEmpty() && inOrderIndex < inOrder.size && stack.peek().value == inOrder[inOrderIndex].value) { + while (!stack.isEmpty() && inOrderIndex < inOrder.size && stack.peek().value == inOrder[inOrderIndex].value) { currentNode = stack.pop() ++inOrderIndex } @@ -121,30 +121,38 @@ class Neo4jRepository: Closeable { session.close() } - fun exportRBtree(): Pair>>>, List>>>>{ + fun exportRBtree(): Pair>>>, List>>>> { val session = driver?.session() ?: throw IOException() var preOrder: List>>> = listOf() var inOrder: List>>> = listOf() - session.executeRead {tx -> - preOrder = tx.run("MATCH (node: Node) " + - "RETURN node.value, node.key, node.color, node.x, node.y ").list() - .map{ DBNodeRB( - value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), - color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, - x = it.values().get(3).toString().toDouble(), - y = it.values().get(4).toString().toDouble()) + session.executeRead { tx -> + preOrder = tx.run( + "MATCH (node: Node) " + + "RETURN node.value, node.key, node.color, node.x, node.y " + ).list() + .map { + DBNodeRB( + value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), + color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, + x = it.values().get(3).toString().toDouble(), + y = it.values().get(4).toString().toDouble() + ) } - inOrder = tx.run("MATCH (node: Node) " + - "RETURN node.value, node.key, node.color, node.x, node.y " + - "ORDER BY node.key").list() - .map{ DBNodeRB( - value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), - color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, - x = it.values().get(3).toString().toDouble(), - y = it.values().get(4).toString().toDouble()) + inOrder = tx.run( + "MATCH (node: Node) " + + "RETURN node.value, node.key, node.color, node.x, node.y " + + "ORDER BY node.key" + ).list() + .map { + DBNodeRB( + value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), + color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, + x = it.values().get(3).toString().toDouble(), + y = it.values().get(4).toString().toDouble() + ) } } diff --git a/lib/src/main/kotlin/treelib/DBNodeRB.kt b/lib/src/main/kotlin/treelib/DBNodeRB.kt index b28228f..cf067e1 100644 --- a/lib/src/main/kotlin/treelib/DBNodeRB.kt +++ b/lib/src/main/kotlin/treelib/DBNodeRB.kt @@ -3,7 +3,9 @@ package treelib import treelib.singleObjects.Markers -class DBNodeRB>(val value: Pack, - val color: Markers = Markers.RED, - val x: Double = 0.0, - val y: Double = 0.0) +class DBNodeRB>( + val value: Pack, + val color: Markers = Markers.RED, + val x: Double = 0.0, + val y: Double = 0.0 +) diff --git a/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt b/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt index 5f80a87..1a3afb9 100644 --- a/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt +++ b/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt @@ -2,7 +2,8 @@ package treelib.avlTree import treelib.abstractTree.balanced.BalancerNoParent -class AVLBalancer>(private var root: AVLNode?): BalancerNoParent, AVLStateContainer>() { +class AVLBalancer>(private var root: AVLNode?) : + BalancerNoParent, AVLStateContainer>() { private fun updateBalance(node: AVLNode?): Int { return (getHeight(node?.left) - getHeight(node?.right)).toInt() } @@ -13,14 +14,16 @@ class AVLBalancer>(private var root: AVLNode?): Bal private fun updateHeight(currentNode: AVLNode?) { if (currentNode != null) - currentNode.height = maxOf(getHeight(currentNode.left), getHeight(currentNode.right))+1u + currentNode.height = maxOf(getHeight(currentNode.left), getHeight(currentNode.right)) + 1u } override fun balance(stateContainer: AVLStateContainer): AVLNode { - val node = stateContainer.contentNode ?: throw IllegalStateException("") // IllegalBaseNodeException("A non-existent node (null) was passed to the method") + val node = stateContainer.contentNode + ?: throw IllegalStateException("") // IllegalBaseNodeException("A non-existent node (null) was passed to the method") root = stateContainer.root return balance(root, node.value) } + /*** In the method we pass the parent of the removed/inserted node ***/ private fun balance(currentNode: AVLNode?, value: Pack): AVLNode { if (currentNode == null) { @@ -34,7 +37,8 @@ class AVLBalancer>(private var root: AVLNode?): Bal val balance = updateBalance(currentNode) if (balance == -2) { if (updateBalance(currentNode.right) == 1) { - currentNode.right = currentNode.right?.let { rightRotate(it) } ?: throw NullPointerException() // IllegalNodeStateException() + currentNode.right = currentNode.right?.let { rightRotate(it) } + ?: throw NullPointerException() // IllegalNodeStateException() updateHeight(currentNode.right?.right) } val balancedNode = leftRotate(currentNode) @@ -44,7 +48,8 @@ class AVLBalancer>(private var root: AVLNode?): Bal } if (balance == 2) { if (updateBalance(currentNode.left) == -1) { - currentNode.left = currentNode.left?.let { leftRotate(it) } ?: throw NullPointerException() // IllegalNodeStateException("There is no node required by the condition of the algorithm") + currentNode.left = currentNode.left?.let { leftRotate(it) } + ?: throw NullPointerException() // IllegalNodeStateException("There is no node required by the condition of the algorithm") updateHeight(currentNode.left?.left) } val balanceNode = rightRotate(currentNode) diff --git a/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt b/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt index 67e5427..211e007 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt @@ -3,7 +3,8 @@ package treelib.rbTree import treelib.abstractTree.balanced.BalancerParent import treelib.singleObjects.Markers -class RBBalancer>(private var root: RBNode?): BalancerParent, RBStateContainer>() { +class RBBalancer>(private var root: RBNode?) : + BalancerParent, RBStateContainer>() { init { root?.color = Markers.BLACK @@ -39,14 +40,13 @@ class RBBalancer>(private var root: RBNode?): Balan return node.right == null && node.left == null } - override fun balance(stateContainer: RBStateContainer): RBNode { - val node = stateContainer.contentNode ?: - throw IllegalStateException() //IllegalBaseNodeException("A non-existent node (null) was passed to the method") + override fun balance(stateContainer: RBStateContainer): RBNode { + val node = stateContainer.contentNode + ?: throw IllegalStateException() //IllegalBaseNodeException("A non-existent node (null) was passed to the method") val uncle = getUncle(node) when { /** node insertion case **/ - node.color == Markers.RED && node.right == null && node.left == null-> - { + node.color == Markers.RED && node.right == null && node.left == null -> { var currentNode = node if (currentNode.parent?.color == Markers.RED && uncle?.color == Markers.RED) { @@ -56,30 +56,35 @@ class RBBalancer>(private var root: RBNode?): Balan return getRoot(currentNode) } - var parent = currentNode.parent ?: throw IllegalStateException() // в данном случае родитель не может быть null + var parent = + currentNode.parent ?: throw IllegalStateException() // в данном случае родитель не может быть null when (parent) { parent.parent?.left -> { if (currentNode == parent.right) { leftRotate(parent) currentNode = parent } - parent = currentNode.parent?.parent ?: throw IllegalStateException() // IllegalNodeStateException() + parent = + currentNode.parent?.parent ?: throw IllegalStateException() // IllegalNodeStateException() currentNode = rightRotate(parent) currentNode.color = Markers.BLACK currentNode.right?.color = Markers.RED currentNode.left?.color = Markers.RED } + parent.parent?.right -> { if (currentNode == parent.left) { rightRotate(parent) currentNode = parent } - parent = currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() + parent = + currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() currentNode = leftRotate(parent) currentNode.color = Markers.BLACK currentNode.right?.color = Markers.RED currentNode.left?.color = Markers.RED } + else -> throw IllegalStateException() // невозможное условие выполнения } if (currentNode.parent == null) @@ -87,21 +92,21 @@ class RBBalancer>(private var root: RBNode?): Balan return root ?: throw NullPointerException() } /** node removal cases **/ - node.color == Markers.RED && (node.right != null || node.left != null) -> - { + node.color == Markers.RED && (node.right != null || node.left != null) -> { when { /** black leaf removal case **/ node.right?.color == Markers.BLACK -> { return firstCase(node, node.left) } + node.left?.color == Markers.BLACK -> { return firstCase(node, node.right) } } } - node.color == Markers.BLACK -> - { + + node.color == Markers.BLACK -> { return when { /** red leaf removal case **/ (node.left == null && node.right == null) || @@ -110,10 +115,11 @@ class RBBalancer>(private var root: RBNode?): Balan getRoot(node) } /** black leaf removal case **/ - node.left == null || node.right == null-> { + node.left == null || node.right == null -> { firstCase(node, null) } + else -> throw IllegalStateException() } } @@ -130,8 +136,7 @@ class RBBalancer>(private var root: RBNode?): Balan currentNode = currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() currentNode.color = Markers.RED uncle.color = Markers.BLACK - } - else if(uncle != null){ + } else if (uncle != null) { return currentNode } } @@ -168,45 +173,41 @@ class RBBalancer>(private var root: RBNode?): Balan } when (node) { - parent.left -> - { + parent.left -> { if (brother.right?.color == Markers.RED) { leftRotate(parent) brother.left?.color = Markers.RED brother.right?.color = Markers.RED brother.color = Markers.BLACK - } - else if (brother.left?.color == Markers.RED) { + } else if (brother.left?.color == Markers.RED) { brother = rightRotate(brother) leftRotate(parent) brother.left?.color = Markers.BLACK brother.left?.color = Markers.BLACK brother.color = Markers.RED - } - else { + } else { throw IllegalStateException() } } - parent.right -> - { + + parent.right -> { if (brother.left?.color == Markers.RED) { rightRotate(parent) brother.color = Markers.BLACK brother.left?.color = Markers.RED brother.right?.color = Markers.RED - } - else if (brother.right?.color == Markers.RED) { + } else if (brother.right?.color == Markers.RED) { brother = leftRotate(brother) rightRotate(parent) brother.color = Markers.RED brother.left?.color = Markers.BLACK brother.right?.color = Markers.BLACK - } - else { + } else { throw IllegalStateException() } } + else -> throw IllegalStateException() } } @@ -223,8 +224,7 @@ class RBBalancer>(private var root: RBNode?): Balan /** black parent and red brother **/ private fun thirdCaseSubFirst(brother: RBNode, parent: RBNode) { when (brother) { - brother.parent?.left -> - { + brother.parent?.left -> { var rightBrotherSon = brother.right ?: throw NullPointerException() // IllegalNodeStateException() if (rightBrotherSon.right?.color != Markers.RED && rightBrotherSon.left?.color != Markers.RED) { @@ -241,7 +241,8 @@ class RBBalancer>(private var root: RBNode?): Balan rightBrotherSon.color = Markers.RED leftRotate(rightBrotherSon) - rightBrotherSon = rightBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() + rightBrotherSon = + rightBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() rightBrotherSon.color = Markers.BLACK } @@ -251,8 +252,8 @@ class RBBalancer>(private var root: RBNode?): Balan rightRotate(parent) } } - brother.parent?.right -> - { + + brother.parent?.right -> { var leftBrotherSon = brother.left ?: throw NullPointerException() if (leftBrotherSon.right?.color != Markers.RED && leftBrotherSon.left?.color != Markers.RED) { leftBrotherSon.color = Markers.RED @@ -264,7 +265,8 @@ class RBBalancer>(private var root: RBNode?): Balan if (leftBrotherSon.left?.color == Markers.RED) { rightRotate(leftBrotherSon) leftBrotherSon.color = Markers.RED - leftBrotherSon = leftBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() + leftBrotherSon = + leftBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() leftBrotherSon.color = Markers.BLACK } @@ -274,6 +276,7 @@ class RBBalancer>(private var root: RBNode?): Balan leftRotate(parent) } } + else -> throw IllegalStateException() } } @@ -289,29 +292,27 @@ class RBBalancer>(private var root: RBNode?): Balan return } when { - brother.left?.color == Markers.RED -> - { + brother.left?.color == Markers.RED -> { brother.left?.color = Markers.BLACK if (brother == parent.left) { rightRotate(parent) - } - else { + } else { rightRotate(brother) leftRotate(parent) } } - brother.right?.color == Markers.RED -> - { + + brother.right?.color == Markers.RED -> { brother.right?.color = Markers.BLACK if (brother == parent.right) { leftRotate(parent) - } - else { + } else { leftRotate(brother) rightRotate(parent) } } + else -> throw IllegalStateException() } } diff --git a/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt b/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt index 67ffc27..ee6a216 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt @@ -1,9 +1,11 @@ package treelib.rbTree +import treelib.DBNodeRB import treelib.abstractTree.balanced.BalancedTreeStruct import treelib.singleObjects.Markers import treelib.singleObjects.exceptions.ImpossibleCaseException import treelib.singleObjects.exceptions.MultithreadingException +import java.util.* class RBStruct> : BalancedTreeStruct, RBStateContainer, RBBalancer>() { @@ -15,17 +17,17 @@ class RBStruct> : override fun generateStateDelete( deletedNode: RBNode?, contentNode: RBNode?, - ): RBStateContainer = RBStateContainer(contentNode) + ): RBStateContainer = RBStateContainer(contentNode) override fun generateStateInsert( insertNode: RBNode?, contentNode: RBNode?, - ): RBStateContainer = RBStateContainer(insertNode) + ): RBStateContainer = RBStateContainer(insertNode) override fun generateStateFind( findNode: RBNode?, contentNode: RBNode?, - ): RBStateContainer = RBStateContainer(findNode) + ): RBStateContainer = RBStateContainer(findNode) override fun connectUnlinkedSubTreeWithParent( node: RBNode, @@ -39,11 +41,12 @@ class RBStruct> : (node.value < parent.value) -> { parent.left = childForLink } + (node.value > parent.value) -> { parent.right = childForLink } } - if (childForLink != null){ + if (childForLink != null) { childForLink.parent = parent } } else root?.let { @@ -62,12 +65,60 @@ class RBStruct> : root?.let { it.color = Markers.BLACK } ?: throw MultithreadingException(ImpossibleCaseException()) - } - else { + } else { if (node.value > parent.value) parent.right = node else parent.left = node node.parent = parent } return node } + + fun restoreTreeFromDatabase(preOrder: List>, inOrder: List>) { + var inOrderIndex = 0 + var preOrderIndex = 0 + val set = HashSet>() + val stack = LinkedList>() + + while (preOrderIndex in preOrder.indices) { + var currentNode: RBNode? + var drawNode: DBNodeRB + + do { + drawNode = preOrder[preOrderIndex] + currentNode = createRBNode(drawNode) + if (root == null) { + root = currentNode + } + if (!stack.isEmpty()) { + if (set.contains(stack.peek())) { + set.remove(stack.peek()) + stack.pop().right = currentNode + } else { + stack.peek().left = currentNode + // связь с ролитилем + } + } + stack.push(currentNode) + } while (preOrder[preOrderIndex++] != inOrder[inOrderIndex] && preOrderIndex < preOrder.size) + + currentNode = null + while (stack.isEmpty() && inOrderIndex < inOrder.size && + stack.peek().value == inOrder[inOrderIndex].value + ) { + currentNode = stack.pop() + ++inOrderIndex + } + + if (currentNode != null) { + set.add(currentNode) + stack.push(currentNode) + } + } + + } + + private fun createRBNode(drawNode: DBNodeRB): RBNode { + val node = RBNode(value = drawNode.value, color = drawNode.color) + return node + } } From bac244a5eb8711ff910b7adbd6f317cd5ea5b34e Mon Sep 17 00:00:00 2001 From: Georgy S Date: Mon, 17 Apr 2023 20:53:59 +0300 Subject: [PATCH 15/84] fix: Fix bug in TreeStruct.insert() method (test: after insert of two containers). --- lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt index d2fe865..5b96f98 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt @@ -141,7 +141,8 @@ abstract class TreeStruct< currentNode?.let { if (obj > it.value) currentNode = it.right else currentNode = it.left - } ?: return generateStateFind(null, null) + } + if (currentNode == null) return generateStateFind(null, null) } } } @@ -162,7 +163,8 @@ abstract class TreeStruct< linkNewNode(currentNode, parentNode) - return generateStateInsert(currentNode, parentNode) + if (parentNode == null) return generateStateInsert(currentNode, currentNode) + else return generateStateInsert(currentNode, parentNode) } updateNode.value = item From a2fe60fdb9815e134c729cd48694733f140ebc53 Mon Sep 17 00:00:00 2001 From: Georgy S Date: Mon, 17 Apr 2023 20:56:33 +0300 Subject: [PATCH 16/84] feat: Implement partial functionality of AVLStructFuzzer. --- lib/src/test/kotlin/utils/AVLAnalyzer.kt | 2 -- .../test/kotlin/utils/fuzzers/AVLStructFuzzer.kt | 13 +++++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/src/test/kotlin/utils/AVLAnalyzer.kt b/lib/src/test/kotlin/utils/AVLAnalyzer.kt index b8a9ac4..15e7825 100644 --- a/lib/src/test/kotlin/utils/AVLAnalyzer.kt +++ b/lib/src/test/kotlin/utils/AVLAnalyzer.kt @@ -4,8 +4,6 @@ import treelib.avlTree.AVLNode import kotlin.math.abs import kotlin.math.max - - class AVLAnalyzer>(override val assertMethod: (input: String) -> Unit) : Analyzer>() { private var heightL = 0 private var heightR = 0 diff --git a/lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt b/lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt index 01d49c5..7cbed69 100644 --- a/lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt +++ b/lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt @@ -1,7 +1,16 @@ package utils.fuzzers import treelib.avlTree.AVLNode +import treelib.avlTree.AVLStateContainer +import treelib.avlTree.AVLStruct +import utils.AVLAnalyzer -class AVLStructFuzzer>(){ -// TODO +class AVLStructFuzzer>( + override val baseInput: Array, + override val assertMethod: (input: String) -> Unit +) : TreeStructFuzzer, AVLAnalyzer, AVLStateContainer, AVLStruct>() { + + override fun createTreeStruct(): AVLStruct = AVLStruct() + + override fun createAnalyzer(): AVLAnalyzer = AVLAnalyzer(assertMethod) } \ No newline at end of file From d33f15b54226ba98c124dff5d907e6d549f4fe66 Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 18 Apr 2023 21:33:22 +0300 Subject: [PATCH 17/84] fix: Fix database interaction --- lib/src/main/kotlin/Controller.kt | 35 +--- lib/src/main/kotlin/DataBase.kt | 186 ++++++++++-------- lib/src/main/kotlin/initNeo4j.sh | 0 lib/src/main/kotlin/loadNeo4j.sh | 8 + lib/src/main/kotlin/testNeo4j.sh | 13 +- lib/src/main/kotlin/treelib/Main.kt | 29 ++- .../main/kotlin/treelib/abstractTree/Tree.kt | 37 ++-- .../kotlin/treelib/abstractTree/TreeStruct.kt | 26 ++- .../kotlin/treelib/abstractTree/Vertex.kt | 5 + .../balanced/BalancedTreeStruct.kt | 4 +- .../main/kotlin/treelib/avlTree/AVLStruct.kt | 6 +- .../main/kotlin/treelib/avlTree/AVLTree.kt | 10 +- .../main/kotlin/treelib/avlTree/AVLVertex.kt | 8 + .../main/kotlin/treelib/binTree/BINStruct.kt | 6 +- .../main/kotlin/treelib/binTree/BINTree.kt | 10 +- .../main/kotlin/treelib/binTree/BINVertex.kt | 5 + .../kotlin/treelib/rbTree/DrawRBVertex.kt | 10 + .../main/kotlin/treelib/rbTree/RBBalancer.kt | 24 +-- .../main/kotlin/treelib/rbTree/RBStruct.kt | 13 +- lib/src/main/kotlin/treelib/rbTree/RBTree.kt | 10 +- .../main/kotlin/treelib/rbTree/RBVertex.kt | 9 + 21 files changed, 286 insertions(+), 168 deletions(-) create mode 100644 lib/src/main/kotlin/initNeo4j.sh create mode 100644 lib/src/main/kotlin/loadNeo4j.sh create mode 100644 lib/src/main/kotlin/treelib/abstractTree/Vertex.kt create mode 100644 lib/src/main/kotlin/treelib/avlTree/AVLVertex.kt create mode 100644 lib/src/main/kotlin/treelib/binTree/BINVertex.kt create mode 100644 lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt create mode 100644 lib/src/main/kotlin/treelib/rbTree/RBVertex.kt diff --git a/lib/src/main/kotlin/Controller.kt b/lib/src/main/kotlin/Controller.kt index cc4e699..a59a3b0 100644 --- a/lib/src/main/kotlin/Controller.kt +++ b/lib/src/main/kotlin/Controller.kt @@ -1,6 +1,6 @@ -import treelib.DBNodeRB + +import treelib.rbTree.DrawRBVertex import treelib.rbTree.RBStruct -import treelib.rbTree.RBTree import treelib.singleObjects.Container class Controller { @@ -8,43 +8,28 @@ class Controller { fun initTree() { val neo4jDB = Neo4jRepository() neo4jDB.open("bolt://localhost:7687", "neo4j", "test-neo4j") + /*** orders.first = preOrder, orders.second = inOrder ***/ - val orders: Pair>>>, List>>>> = + val orders: Pair>>>, List>>>> = neo4jDB.exportRBtree() val RBtree = RBStruct>>() RBtree.restoreTreeFromDatabase(orders.first, orders.second) + neo4jDB.close() } - fun saveTree() { - val tree = RBTree() - tree.putItem(Pair(25, 1)) - tree.putItem(Pair(15, 1)) - tree.putItem(Pair(50, 1)) - tree.putItem(Pair(10, 1)) - tree.putItem(Pair(22, 1)) - tree.putItem(Pair(35, 1)) - tree.putItem(Pair(70, 1)) - tree.putItem(Pair(4, 1)) - tree.putItem(Pair(12, 1)) - tree.putItem(Pair(18, 1)) - tree.putItem(Pair(24, 1)) - tree.putItem(Pair(31, 1)) - tree.putItem(Pair(44, 1)) - tree.putItem(Pair(66, 1)) - tree.putItem(Pair(90, 1)) - + fun > saveTree(tree: RBStruct) { val neo4jDB = Neo4jRepository() neo4jDB.open("bolt://localhost:7687", "neo4j", "test-neo4j") - val preOrder = tree.preOrder().map { DBNodeRB(it.value, it.color) } - val inOrder = tree.inOrder().map { DBNodeRB(it.value, it.color) } + // вот тут плохо, потому что тут надо получать не base nodes, а для рисовалки - neo4jDB.saveChanges(preOrder.toTypedArray(), inOrder.toTypedArray()) + val preOrder = tree.preOrder().map { DrawRBVertex(it.value, it.color) } + val inOrder = tree.inOrder().map { DrawRBVertex(it.value, it.color) } + neo4jDB.saveChanges(preOrder.toTypedArray(), inOrder.toTypedArray()) neo4jDB.close() - } } \ No newline at end of file diff --git a/lib/src/main/kotlin/DataBase.kt b/lib/src/main/kotlin/DataBase.kt index e7ca4c6..809eb64 100644 --- a/lib/src/main/kotlin/DataBase.kt +++ b/lib/src/main/kotlin/DataBase.kt @@ -1,8 +1,9 @@ import org.neo4j.driver.AuthTokens import org.neo4j.driver.Driver import org.neo4j.driver.GraphDatabase +import org.neo4j.driver.TransactionContext import org.neo4j.driver.exceptions.SessionExpiredException -import treelib.DBNodeRB +import treelib.rbTree.DrawRBVertex import treelib.singleObjects.Container import treelib.singleObjects.Markers import java.io.Closeable @@ -23,88 +24,50 @@ class Neo4jRepository : Closeable { } } - fun > saveChanges(preOrder: Array>, inOrder: Array>) { + fun > saveChanges(preOrder: Array>, inOrder: Array>) { /*** сюда по ощущениям лучше всего добавлять именно то поддерево исходного дерева, которое было изменено ***/ val session = driver?.session() ?: throw IOException() var inOrderIndex = 0 var preOrderIndex = 0 - val set = HashSet>() - val stack = LinkedList>() + val set = HashSet>() + val stack = LinkedList>() + var id = 0 while (preOrderIndex in preOrder.indices) { do { val currentNode = preOrder[preOrderIndex] - currentNode.value as Container<*, *> + //currentNode.value as Container<*, *> if (preOrderIndex == 0) { session.executeWrite { tx -> - tx.run( - "MERGE(:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY})", - mutableMapOf( - "nodeValue" to currentNode.value.pair.second, - "nodeKey" to currentNode.value.pair.first, - "nodeColor" to currentNode.color.toString(), - "nodeX" to currentNode.x, - "nodeY" to currentNode.y - ) - ) + cleanDB(tx) + createRoot(tx, currentNode, id) } + ++id } if (!stack.isEmpty()) { if (set.contains(stack.peek())) { set.remove(stack.peek()) val parentNode = stack.pop() - parentNode.value as Container<*, *> + //parentNode.value as Container<*, *> session.executeWrite { tx -> - tx.run( - "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + - "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + - "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + - "MERGE (parent)-[:RIGHT_SON]->(son)", - mutableMapOf( - "parentNodeValue" to parentNode.value.pair.second, - "parentNodeKey" to parentNode.value.pair.first, - "parentNodeColor" to parentNode.color.toString(), - "parentNodeX" to parentNode.x, - "parentNodeY" to parentNode.y, - "nodeValue" to currentNode.value.pair.second, - "nodeKey" to currentNode.value.pair.first, - "nodeColor" to currentNode.color.toString(), - "nodeX" to currentNode.x, - "nodeY" to currentNode.y - ) - ) + createRightSon(tx, parentNode, currentNode, id) } + ++id } else { val parentNode = stack.peek() parentNode.value as Container<*, *> session.executeWrite { tx -> - tx.run( - "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + - "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + - "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + - "MERGE (parent)-[:LEFT_SON]->(son)", - mutableMapOf( - "parentNodeValue" to parentNode.value.pair.second, - "parentNodeKey" to parentNode.value.pair.first, - "parentNodeColor" to parentNode.color.toString(), - "parentNodeX" to parentNode.x, - "parentNodeY" to parentNode.y, - "nodeValue" to currentNode.value.pair.second, - "nodeKey" to currentNode.value.pair.first, - "nodeColor" to currentNode.color.toString(), - "nodeX" to currentNode.x, - "nodeY" to currentNode.y - ) - ) + createLeftSon(tx, parentNode, currentNode, id) } + ++id } } stack.push(currentNode) - } while (preOrder[preOrderIndex++] != inOrder[inOrderIndex] && preOrderIndex < preOrder.size) + } while (preOrder[preOrderIndex++].value != inOrder[inOrderIndex].value && preOrderIndex < preOrder.size) - var currentNode: DBNodeRB? = null + var currentNode: DrawRBVertex? = null while (!stack.isEmpty() && inOrderIndex < inOrder.size && stack.peek().value == inOrder[inOrderIndex].value) { currentNode = stack.pop() @@ -121,23 +84,26 @@ class Neo4jRepository : Closeable { session.close() } - fun exportRBtree(): Pair>>>, List>>>> { + fun exportRBtree(): Pair>>>, List>>>> { + + /*** Вот тут короче надо обращаться к neo4j с темЮ чтобы она инициализировала себя как-то ***/ val session = driver?.session() ?: throw IOException() - var preOrder: List>>> = listOf() - var inOrder: List>>> = listOf() + var preOrder: List>>> = listOf() + var inOrder: List>>> = listOf() session.executeRead { tx -> preOrder = tx.run( "MATCH (node: Node) " + - "RETURN node.value, node.key, node.color, node.x, node.y " + "RETURN node.value, node.key, node.color, node.x, node.y " + + "ORDER BY node.id" ).list() .map { - DBNodeRB( - value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), - color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, - x = it.values().get(3).toString().toDouble(), - y = it.values().get(4).toString().toDouble() + DrawRBVertex( + value = Container(Pair(it.values()[1].toString(), it.values()[0].toString())), + color = if (it.values()[2].toString() == """RED""") Markers.RED else Markers.BLACK, + x = it.values()[3].toString().toDouble(), + y = it.values()[4].toString().toDouble() ) } @@ -147,11 +113,11 @@ class Neo4jRepository : Closeable { "ORDER BY node.key" ).list() .map { - DBNodeRB( - value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), - color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, - x = it.values().get(3).toString().toDouble(), - y = it.values().get(4).toString().toDouble() + DrawRBVertex( + value = Container(Pair(it.values()[1].toString(), it.values()[0].toString())), + color = if (it.values()[2].toString() == """RED""") Markers.RED else Markers.BLACK, + x = it.values()[3].toString().toDouble(), + y = it.values()[4].toString().toDouble() ) } } @@ -162,18 +128,80 @@ class Neo4jRepository : Closeable { } + private fun cleanDB(tx: TransactionContext) { + tx.run("MATCH (n: Node) DETACH DELETE n") + } + + private fun > createRoot(tx: TransactionContext, rootNode: DrawRBVertex, id: Int) { + rootNode.value as Container<*, *> + tx.run( + "MERGE(:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY, id: \$nodeID})", + mutableMapOf( + "nodeValue" to rootNode.value.pair.second, + "nodeKey" to rootNode.value.pair.first, + "nodeColor" to rootNode.color.toString(), + "nodeX" to rootNode.x, + "nodeY" to rootNode.y, + "nodeID" to id + ) + ) + } + + private fun > createRightSon( + tx: TransactionContext, parentNode: DrawRBVertex, + currentNode: DrawRBVertex, id: Int + ) { + parentNode.value as Container<*, *> + currentNode.value as Container<*, *> + tx.run( + "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY, id: \$nodeID}) " + + "MERGE (parent)-[:RIGHT_SON]->(son)", + mutableMapOf( + "parentNodeValue" to parentNode.value.pair.second, + "parentNodeKey" to parentNode.value.pair.first, + "parentNodeColor" to parentNode.color.toString(), + "parentNodeX" to parentNode.x, + "parentNodeY" to parentNode.y, + "nodeValue" to currentNode.value.pair.second, + "nodeKey" to currentNode.value.pair.first, + "nodeColor" to currentNode.color.toString(), + "nodeX" to currentNode.x, + "nodeY" to currentNode.y, + "nodeID" to id, + ) + ) + } + + private fun > createLeftSon( + tx: TransactionContext, parentNode: DrawRBVertex, + currentNode: DrawRBVertex, id: Int + ) { + parentNode.value as Container<*, *> + currentNode.value as Container<*, *> + tx.run( + "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY, id: \$nodeID}) " + + "MERGE (parent)-[:LEFT_SON]->(son)", + mutableMapOf( + "parentNodeValue" to parentNode.value.pair.second, + "parentNodeKey" to parentNode.value.pair.first, + "parentNodeColor" to parentNode.color.toString(), + "parentNodeX" to parentNode.x, + "parentNodeY" to parentNode.y, + "nodeValue" to currentNode.value.pair.second, + "nodeKey" to currentNode.value.pair.first, + "nodeColor" to currentNode.color.toString(), + "nodeX" to currentNode.x, + "nodeY" to currentNode.y, + "nodeID" to id, + ) + ) + } + override fun close() { driver?.close() } } - -// neo4j-admin, backup, restore -/* -у меня есть вершины и ребра между ними, надо уметь сохранять дерево в базе, но как? -вопрос: когда заносить изменения в бд и как это реализовывать? -надо еще подумать над оптимизацией, те чтобы не пересобирать дерево в бд каждый раз, когда мы добавили за сессию всего один узел - -root = tx.run("MATCH (parent: Node)-->(son: Node) " + - "WHERE NOT ()-->(parent) " + - "RETURN parent.value, parent.key, parent.color, parent.x, parent.y").list().map {it.values()}.get(0) - */ diff --git a/lib/src/main/kotlin/initNeo4j.sh b/lib/src/main/kotlin/initNeo4j.sh new file mode 100644 index 0000000..e69de29 diff --git a/lib/src/main/kotlin/loadNeo4j.sh b/lib/src/main/kotlin/loadNeo4j.sh new file mode 100644 index 0000000..d4d9fcd --- /dev/null +++ b/lib/src/main/kotlin/loadNeo4j.sh @@ -0,0 +1,8 @@ + +BASEDIR=$(realpath "$(dirname "$0")") + +. "${BASEDIR}/CONTAINER.conf" + +docker stop "$CONTAINER_NAME" + +neo4j-admin dump --database=neo4j --to=/data/backups/ \ No newline at end of file diff --git a/lib/src/main/kotlin/testNeo4j.sh b/lib/src/main/kotlin/testNeo4j.sh index 97ad8db..87b69c4 100644 --- a/lib/src/main/kotlin/testNeo4j.sh +++ b/lib/src/main/kotlin/testNeo4j.sh @@ -3,13 +3,22 @@ BASEDIR=$(realpath "$(dirname "$0")") . "${BASEDIR}/CONTAINER.conf" +# -d docker run \ - --rm \ - --name "CONTAINER_NAME" \ + -i \ + --name "$CONTAINER_NAME" \ --volume=$HOME/neo4j/data:/data \ --volume=$HOME/neo4j/logs:/logs \ --publish=7474:7474 --publish=7687:7687 \ --env NEO4J_AUTH=neo4j/"$PASSWORD" \ neo4j:latest \ +# -c /bin/bash +#neo4j-admin database dump neo4j --to-path=$HOME/neo4j/data:/data + +#docker ps -a + +#docker stop "$CONTAINER_NAME" + +#cp $HOME/neo4j/data:/data $HOME/ #docker stop neo4j:latest diff --git a/lib/src/main/kotlin/treelib/Main.kt b/lib/src/main/kotlin/treelib/Main.kt index 0aeb3e0..15e0eab 100644 --- a/lib/src/main/kotlin/treelib/Main.kt +++ b/lib/src/main/kotlin/treelib/Main.kt @@ -1,6 +1,8 @@ package treelib import Controller +import treelib.rbTree.RBStruct +import treelib.singleObjects.Container fun main() { @@ -30,10 +32,35 @@ fun main() { neo4jRep.open("bolt://localhost:7687", "neo4j", "test-neo4j") neo4jRep.saveChanges(preArr, inArr) */ + + val tree = RBStruct>() + tree.insert(Container(Pair(25 , 1))) + tree.insert(Container(Pair(15 , 1))) + tree.insert(Container(Pair(50 , 1))) + tree.insert(Container(Pair(10 , 1))) + tree.insert(Container(Pair(22 , 1))) + tree.insert(Container(Pair(35 , 1))) + tree.insert(Container(Pair(70 , 1))) + tree.insert(Container(Pair(4 , 1))) + tree.insert(Container(Pair(12 , 1))) + tree.insert(Container(Pair(18 , 1))) + tree.insert(Container(Pair(24 , 1))) + tree.insert(Container(Pair(31 , 1))) + tree.insert(Container(Pair(44 , 1))) + tree.insert(Container(Pair(66 , 1))) + tree.insert(Container(Pair(90 , 1))) val controller = Controller() - controller.saveTree() + controller.saveTree(tree) + tree.insert(Container(Pair(100, 1))) + controller.saveTree(tree) + controller.initTree() //neo4jRep.exportRBtree() //neo4jRep.close() +} + +fun test() { + val cont = Controller() + cont.initTree() } \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/abstractTree/Tree.kt b/lib/src/main/kotlin/treelib/abstractTree/Tree.kt index 1607caa..1116ad6 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/Tree.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/Tree.kt @@ -4,44 +4,47 @@ import treelib.singleObjects.Container import treelib.singleObjects.exceptions.NonExistentValueException abstract class Tree< - Key : Comparable, - Value, - NodeType : Node, NodeType>, - State : StateContainer, NodeType> + K : Comparable, + V, + NodeType : Node, NodeType>, + State : StateContainer, NodeType>, + VertexType: Vertex> > { - protected abstract val treeStruct: TreeStruct, NodeType, State> + protected abstract val treeStruct: TreeStruct, NodeType, State, VertexType> - private fun wrapForFind(key: Key) = Container(key to null) + private fun wrapForFind(key: K) = Container(key to null) - fun putItem(item: Pair) { + fun putItem(item: Pair) { treeStruct.insert(Container(item)) } - fun putItems(vararg items: Pair) { + fun putItems(vararg items: Pair) { for (element in items) putItem(element) } - fun putItems(items: Iterable>) { + fun putItems(items: Iterable>) { for (element in items) putItem(element) } - fun getItem(key: Key): Value? = treeStruct.find(wrapForFind(key))?.value + fun getItem(key: K): V? = treeStruct.find(wrapForFind(key))?.value - fun deleteItem(key: Key) { + fun deleteItem(key: K) { if (getItem(key) == null) throw NonExistentValueException() treeStruct.delete(wrapForFind(key)) } - private fun createPoorList(info: List): List { - val returnInfo = mutableListOf() - for (element in info) returnInfo.add(element) + private fun createPoorList(info: List): List> { + val returnInfo = mutableListOf>() + for (element in info) { + returnInfo.add(element.value.pair) + } return returnInfo } - fun inOrder(): List = createPoorList(treeStruct.inOrder()) + fun inOrder(): List> = createPoorList(treeStruct.inOrder()) - fun preOrder(): List = createPoorList(treeStruct.preOrder()) + fun preOrder(): List> = createPoorList(treeStruct.preOrder()) - fun postOrder(): List = createPoorList(treeStruct.postOrder()) + fun postOrder(): List> = createPoorList(treeStruct.postOrder()) } diff --git a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt index 2f536d8..c91c6ed 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt @@ -9,7 +9,8 @@ import treelib.singleObjects.exceptions.NonExistentValueException abstract class TreeStruct< Pack : Comparable, NodeType : Node, - State : StateContainer + State : StateContainer, + VertexType: Vertex > { protected abstract var root: NodeType? @@ -141,7 +142,8 @@ abstract class TreeStruct< currentNode?.let { if (obj > it.value) currentNode = it.right else currentNode = it.left - } ?: return generateStateFind(null, null) + } + if (currentNode == null) return generateStateFind(null, null) } } } @@ -259,7 +261,7 @@ abstract class TreeStruct< fun find(obj: Pack): Pack? = findItem(obj).contentNode?.value - fun inOrder(): List { + fun inOrder(): List { val arrayNodes = mutableListOf() var flagVisited = 0 var current = root @@ -283,16 +285,18 @@ abstract class TreeStruct< current = it.right } else { if (parents.isEmpty()) - return@inOrder arrayNodes + return@inOrder arrayNodes.map {toVertex(it)} flagVisited = 1 current = parents.removeLast() } } } - return arrayNodes + return arrayNodes.map{toVertex(it)} } - fun postOrder(): List { + abstract fun toVertex(node: NodeType): VertexType + + fun postOrder(): List { val parents = ArrayDeque() val arrayNodes = mutableListOf() var flagVisited = 0 @@ -317,7 +321,7 @@ abstract class TreeStruct< } else { arrayNodes.add(it) if (parents.isEmpty()) - return@postOrder arrayNodes + return@postOrder arrayNodes.map{toVertex(it)} val parent = parents.removeLast() if (parent.right == it) { flagVisited = 2 @@ -326,10 +330,10 @@ abstract class TreeStruct< } } ?: throw MultithreadingException(ImpossibleCaseException()) } - return arrayNodes + return arrayNodes.map{toVertex(it)} } - fun preOrder(): List { + fun preOrder(): List { val arrayNodes = mutableListOf() var current: NodeType val queue = ArrayDeque() @@ -350,6 +354,8 @@ abstract class TreeStruct< } ?: throw MultithreadingException(ImpossibleCaseException()) } } - return arrayNodes + return arrayNodes.map {toVertex(it)} } + + } diff --git a/lib/src/main/kotlin/treelib/abstractTree/Vertex.kt b/lib/src/main/kotlin/treelib/abstractTree/Vertex.kt new file mode 100644 index 0000000..abbb7a5 --- /dev/null +++ b/lib/src/main/kotlin/treelib/abstractTree/Vertex.kt @@ -0,0 +1,5 @@ +package treelib.abstractTree + +abstract class Vertex>{ + abstract val value: Pack +} \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/abstractTree/balanced/BalancedTreeStruct.kt b/lib/src/main/kotlin/treelib/abstractTree/balanced/BalancedTreeStruct.kt index 5dd24c3..96e8458 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/balanced/BalancedTreeStruct.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/balanced/BalancedTreeStruct.kt @@ -3,13 +3,15 @@ package treelib.abstractTree.balanced import treelib.abstractTree.Node import treelib.abstractTree.StateContainer import treelib.abstractTree.TreeStruct +import treelib.abstractTree.Vertex abstract class BalancedTreeStruct< Pack : Comparable, NodeType : Node, State : StateContainer, + VertexType: Vertex, BalancerType : Balancer, - > : TreeStruct() { + > : TreeStruct() { protected abstract val balancer: BalancerType diff --git a/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt b/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt index f275439..7893341 100644 --- a/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt +++ b/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt @@ -3,7 +3,7 @@ package treelib.avlTree import treelib.abstractTree.balanced.BalancedTreeStruct class AVLStruct> : - BalancedTreeStruct, AVLStateContainer, AVLBalancer>() { + BalancedTreeStruct, AVLStateContainer, AVLVertex, AVLBalancer>() { override var root: AVLNode? = null override val balancer = AVLBalancer(root) @@ -40,6 +40,10 @@ class AVLStruct> : } } + override fun toVertex(node: AVLNode): AVLVertex { + return AVLVertex(node.value, node.height) + } + override fun createNode(item: Pack): AVLNode = AVLNode(item) override fun getNodeKernel(node: AVLNode): AVLNode = AVLNode(node.value, height = node.height) diff --git a/lib/src/main/kotlin/treelib/avlTree/AVLTree.kt b/lib/src/main/kotlin/treelib/avlTree/AVLTree.kt index 6155af6..5df840f 100644 --- a/lib/src/main/kotlin/treelib/avlTree/AVLTree.kt +++ b/lib/src/main/kotlin/treelib/avlTree/AVLTree.kt @@ -4,12 +4,12 @@ import treelib.abstractTree.Tree import treelib.singleObjects.Container -class AVLTree, Value> : - Tree>, AVLStateContainer>>() { +class AVLTree, V> : + Tree>, AVLStateContainer>, AVLVertex>>() { - override val treeStruct = AVLStruct>() + override val treeStruct = AVLStruct>() - operator fun AVLTree.get(key: Key): Value? = getItem(key) + operator fun AVLTree.get(key: K): V? = getItem(key) - operator fun AVLTree.set(key: Key, value: Value) = putItem(key to value) + operator fun AVLTree.set(key: K, value: V) = putItem(key to value) } diff --git a/lib/src/main/kotlin/treelib/avlTree/AVLVertex.kt b/lib/src/main/kotlin/treelib/avlTree/AVLVertex.kt new file mode 100644 index 0000000..a43ea26 --- /dev/null +++ b/lib/src/main/kotlin/treelib/avlTree/AVLVertex.kt @@ -0,0 +1,8 @@ +package treelib.avlTree + +import treelib.abstractTree.Vertex + +class AVLVertex>( + override val value: Pack, + val height: UInt, +) : Vertex() \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/binTree/BINStruct.kt b/lib/src/main/kotlin/treelib/binTree/BINStruct.kt index e555924..f3bfc09 100644 --- a/lib/src/main/kotlin/treelib/binTree/BINStruct.kt +++ b/lib/src/main/kotlin/treelib/binTree/BINStruct.kt @@ -3,7 +3,7 @@ package treelib.binTree import treelib.abstractTree.TreeStruct class BINStruct> : - TreeStruct, BINStateContainer>() { + TreeStruct, BINStateContainer, BINVertex>() { override var root: BINNode? = null @@ -53,6 +53,10 @@ class BINStruct> : return node } + override fun toVertex(node: BINNode): BINVertex { + return BINVertex(node.value) + } + override fun createNode(item: Pack) = BINNode(item) override fun delete(item: Pack) { diff --git a/lib/src/main/kotlin/treelib/binTree/BINTree.kt b/lib/src/main/kotlin/treelib/binTree/BINTree.kt index f8ac560..f0a92d9 100644 --- a/lib/src/main/kotlin/treelib/binTree/BINTree.kt +++ b/lib/src/main/kotlin/treelib/binTree/BINTree.kt @@ -3,12 +3,12 @@ package treelib.binTree import treelib.abstractTree.Tree import treelib.singleObjects.Container -class BINTree, Value> - : Tree>, BINStateContainer>>() { +class BINTree, V> + : Tree>, BINStateContainer>, BINVertex>>() { - override val treeStruct = BINStruct>() + override val treeStruct = BINStruct>() - operator fun BINTree.get(key: Key): Value? = getItem(key) + operator fun BINTree.get(key: K): V? = getItem(key) - operator fun BINTree.set(key: Key, value: Value) = putItem(key to value) + operator fun BINTree.set(key: K, value: V) = putItem(key to value) } diff --git a/lib/src/main/kotlin/treelib/binTree/BINVertex.kt b/lib/src/main/kotlin/treelib/binTree/BINVertex.kt new file mode 100644 index 0000000..e660d8c --- /dev/null +++ b/lib/src/main/kotlin/treelib/binTree/BINVertex.kt @@ -0,0 +1,5 @@ +package treelib.binTree + +import treelib.abstractTree.Vertex + +class BINVertex>(override val value: Pack): Vertex() \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt b/lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt new file mode 100644 index 0000000..b3ee499 --- /dev/null +++ b/lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt @@ -0,0 +1,10 @@ +package treelib.rbTree + +import treelib.singleObjects.Markers + +class DrawRBVertex>( + value: Pack, + color: Markers, + val x: Double = 0.0, + val y: Double = 0.0 +) : RBVertex(value, color) \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt b/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt index 211e007..c8c4cf6 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt @@ -2,6 +2,8 @@ package treelib.rbTree import treelib.abstractTree.balanced.BalancerParent import treelib.singleObjects.Markers +import treelib.singleObjects.exceptions.IllegalBaseNodeException +import treelib.singleObjects.exceptions.IllegalNodeStateException class RBBalancer>(private var root: RBNode?) : BalancerParent, RBStateContainer>() { @@ -42,7 +44,7 @@ class RBBalancer>(private var root: RBNode?) : override fun balance(stateContainer: RBStateContainer): RBNode { val node = stateContainer.contentNode - ?: throw IllegalStateException() //IllegalBaseNodeException("A non-existent node (null) was passed to the method") + ?: throw IllegalBaseNodeException() val uncle = getUncle(node) when { /** node insertion case **/ @@ -65,7 +67,7 @@ class RBBalancer>(private var root: RBNode?) : currentNode = parent } parent = - currentNode.parent?.parent ?: throw IllegalStateException() // IllegalNodeStateException() + currentNode.parent?.parent ?: throw IllegalNodeStateException() currentNode = rightRotate(parent) currentNode.color = Markers.BLACK currentNode.right?.color = Markers.RED @@ -78,7 +80,7 @@ class RBBalancer>(private var root: RBNode?) : currentNode = parent } parent = - currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() + currentNode.parent?.parent ?: throw IllegalNodeStateException() currentNode = leftRotate(parent) currentNode.color = Markers.BLACK currentNode.right?.color = Markers.RED @@ -133,7 +135,7 @@ class RBBalancer>(private var root: RBNode?) : val uncle = getUncle(currentNode) if (uncle?.color == Markers.RED) { currentNode.parent?.color = Markers.BLACK - currentNode = currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() + currentNode = currentNode.parent?.parent ?: throw IllegalNodeStateException() currentNode.color = Markers.RED uncle.color = Markers.BLACK } else if (uncle != null) { @@ -156,13 +158,13 @@ class RBBalancer>(private var root: RBNode?) : getRoot(parent) } - else -> getRoot(node ?: throw NullPointerException() /* IllegalNodeStateException() */) + else -> getRoot(node ?: throw IllegalNodeStateException()) } } /** parent is red **/ private fun secondCase(parent: RBNode, node: RBNode?) { - var brother = getBrother(parent, node) ?: throw NullPointerException() // IllegalNodeStateException() + var brother = getBrother(parent, node) ?: throw IllegalNodeStateException() if (brother.color == Markers.RED) throw NullPointerException() @@ -214,7 +216,7 @@ class RBBalancer>(private var root: RBNode?) : /** parent is black **/ private fun thirdCase(parent: RBNode, node: RBNode?) { - val brother = getBrother(parent, node) ?: throw NullPointerException() // IllegalNodeStateException() + val brother = getBrother(parent, node) ?: throw IllegalNodeStateException() when (brother.color) { Markers.RED -> thirdCaseSubFirst(brother, parent) Markers.BLACK -> thirdCaseSubSecond(brother, parent) @@ -225,7 +227,7 @@ class RBBalancer>(private var root: RBNode?) : private fun thirdCaseSubFirst(brother: RBNode, parent: RBNode) { when (brother) { brother.parent?.left -> { - var rightBrotherSon = brother.right ?: throw NullPointerException() // IllegalNodeStateException() + var rightBrotherSon = brother.right ?: throw IllegalNodeStateException() if (rightBrotherSon.right?.color != Markers.RED && rightBrotherSon.left?.color != Markers.RED) { rightBrotherSon.color = Markers.RED @@ -242,7 +244,7 @@ class RBBalancer>(private var root: RBNode?) : leftRotate(rightBrotherSon) rightBrotherSon = - rightBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() + rightBrotherSon.parent ?: throw IllegalNodeStateException() rightBrotherSon.color = Markers.BLACK } @@ -258,7 +260,7 @@ class RBBalancer>(private var root: RBNode?) : if (leftBrotherSon.right?.color != Markers.RED && leftBrotherSon.left?.color != Markers.RED) { leftBrotherSon.color = Markers.RED brother.color = Markers.BLACK - leftRotate(brother.parent ?: throw NullPointerException()) // IllegalNodeStateException() + leftRotate(brother.parent ?: throw IllegalNodeStateException()) return } @@ -266,7 +268,7 @@ class RBBalancer>(private var root: RBNode?) : rightRotate(leftBrotherSon) leftBrotherSon.color = Markers.RED leftBrotherSon = - leftBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() + leftBrotherSon.parent ?: throw IllegalNodeStateException() leftBrotherSon.color = Markers.BLACK } diff --git a/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt b/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt index ee6a216..47dd91d 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt @@ -1,6 +1,5 @@ package treelib.rbTree -import treelib.DBNodeRB import treelib.abstractTree.balanced.BalancedTreeStruct import treelib.singleObjects.Markers import treelib.singleObjects.exceptions.ImpossibleCaseException @@ -8,7 +7,7 @@ import treelib.singleObjects.exceptions.MultithreadingException import java.util.* class RBStruct> : - BalancedTreeStruct, RBStateContainer, RBBalancer>() { + BalancedTreeStruct, RBStateContainer, RBVertex, RBBalancer>() { override var root: RBNode? = null @@ -57,6 +56,10 @@ class RBStruct> : override fun getNodeKernel(node: RBNode): RBNode = RBNode(node.value, color = node.color) + override fun toVertex(node: RBNode): RBVertex { + return RBVertex(node.value, node.color) + } + override fun createNode(item: Pack): RBNode = RBNode(item) override fun linkNewNode(node: RBNode, parent: RBNode?): RBNode { @@ -73,7 +76,7 @@ class RBStruct> : return node } - fun restoreTreeFromDatabase(preOrder: List>, inOrder: List>) { + fun > restoreTreeFromDatabase(preOrder: List, inOrder: List) { var inOrderIndex = 0 var preOrderIndex = 0 val set = HashSet>() @@ -81,7 +84,7 @@ class RBStruct> : while (preOrderIndex in preOrder.indices) { var currentNode: RBNode? - var drawNode: DBNodeRB + var drawNode: RBVertexType do { drawNode = preOrder[preOrderIndex] @@ -117,7 +120,7 @@ class RBStruct> : } - private fun createRBNode(drawNode: DBNodeRB): RBNode { + private fun > createRBNode(drawNode: RBVertexType): RBNode { val node = RBNode(value = drawNode.value, color = drawNode.color) return node } diff --git a/lib/src/main/kotlin/treelib/rbTree/RBTree.kt b/lib/src/main/kotlin/treelib/rbTree/RBTree.kt index 6ccfa32..a29234e 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBTree.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBTree.kt @@ -4,12 +4,12 @@ import treelib.abstractTree.Tree import treelib.singleObjects.Container -class RBTree, Value> : - Tree>, RBStateContainer>>() { +class RBTree, V> : + Tree>, RBStateContainer>, RBVertex>>() { - override val treeStruct = RBStruct>() + override val treeStruct = RBStruct>() - operator fun RBTree.get(key: Key): Value? = getItem(key) + operator fun RBTree.get(key: K): V? = getItem(key) - operator fun RBTree.set(key: Key, value: Value) = putItem(key to value) + operator fun RBTree.set(key: K, value: V) = putItem(key to value) } diff --git a/lib/src/main/kotlin/treelib/rbTree/RBVertex.kt b/lib/src/main/kotlin/treelib/rbTree/RBVertex.kt new file mode 100644 index 0000000..5d9d161 --- /dev/null +++ b/lib/src/main/kotlin/treelib/rbTree/RBVertex.kt @@ -0,0 +1,9 @@ +package treelib.rbTree + +import treelib.abstractTree.Vertex +import treelib.singleObjects.Markers + +open class RBVertex>( + override val value: Pack, + val color: Markers, +):Vertex() \ No newline at end of file From 8a03667eef9c13706d2496abadedc6029576561c Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 18 Apr 2023 22:04:52 +0300 Subject: [PATCH 18/84] fix: Add running on multiple OS --- .github/workflows/CI.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index ae15aca..8697f86 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -4,7 +4,10 @@ on: [push, pull_request] jobs: run: - runs-on: ubuntu-latest + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + runs-on: ${{ matrix.os }} steps: - name: Checkout uses: actions/checkout@v3 From 6cee47dd2b3fcfcfea6bba407f174c0670942c82 Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 18 Apr 2023 22:37:53 +0300 Subject: [PATCH 19/84] fix: Fix tree class definitions --- .gitignore | 3 ++- lib/src/test/kotlin/treelib/AVLStructTest.kt | 3 ++- lib/src/test/kotlin/treelib/BINStructTest.kt | 3 ++- lib/src/test/kotlin/treelib/RBStructTest.kt | 3 ++- lib/src/test/kotlin/utils/TreeStructWrapper.kt | 3 ++- lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt | 3 ++- lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt | 3 ++- .../test/kotlin/utils/fuzzers/TreeStructFuzzer.kt | 12 +++++++----- 8 files changed, 21 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 7061064..38f0b3d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /.gradle/ /.idea/ /build/ -/lib/build/ \ No newline at end of file +/lib/build/ +/lib/TEST_TEST/ diff --git a/lib/src/test/kotlin/treelib/AVLStructTest.kt b/lib/src/test/kotlin/treelib/AVLStructTest.kt index 347892c..0e4f7dc 100644 --- a/lib/src/test/kotlin/treelib/AVLStructTest.kt +++ b/lib/src/test/kotlin/treelib/AVLStructTest.kt @@ -7,12 +7,13 @@ import org.junit.jupiter.api.fail import treelib.avlTree.AVLNode import treelib.avlTree.AVLStateContainer import treelib.avlTree.AVLStruct +import treelib.avlTree.AVLVertex import utils.AVLAnalyzer import utils.TreeStructWrapper @DisplayName("Test: AVL Struct") class AVLStructTest { - private val treeW = TreeStructWrapper, AVLStateContainer, AVLStruct>() + private val treeW = TreeStructWrapper, AVLVertex, AVLStateContainer, AVLStruct>() private val treeH = AVLAnalyzer(::testAssert) private var treeStruct = AVLStruct() diff --git a/lib/src/test/kotlin/treelib/BINStructTest.kt b/lib/src/test/kotlin/treelib/BINStructTest.kt index 952a6fa..1075631 100644 --- a/lib/src/test/kotlin/treelib/BINStructTest.kt +++ b/lib/src/test/kotlin/treelib/BINStructTest.kt @@ -7,13 +7,14 @@ import org.junit.jupiter.api.fail import treelib.binTree.BINNode import treelib.binTree.BINStateContainer import treelib.binTree.BINStruct +import treelib.binTree.BINVertex import utils.BINAnalyzer import utils.TreeStructWrapper import kotlin.test.assertEquals @DisplayName("Test: Binary Search Tree Struct") class BINStructTest { - val treeW = TreeStructWrapper, BINStateContainer, BINStruct>() + val treeW = TreeStructWrapper, BINVertex, BINStateContainer, BINStruct>() var treeStruct = BINStruct() private fun testAssert(msg: String): Nothing = fail(msg) diff --git a/lib/src/test/kotlin/treelib/RBStructTest.kt b/lib/src/test/kotlin/treelib/RBStructTest.kt index 606ca40..3196207 100644 --- a/lib/src/test/kotlin/treelib/RBStructTest.kt +++ b/lib/src/test/kotlin/treelib/RBStructTest.kt @@ -4,6 +4,7 @@ import org.junit.jupiter.api.* import treelib.rbTree.RBNode import treelib.rbTree.RBStateContainer import treelib.rbTree.RBStruct +import treelib.rbTree.RBVertex import treelib.singleObjects.Markers import utils.RBAnalyzer import utils.TreeStructWrapper @@ -12,7 +13,7 @@ import kotlin.test.assertEquals @DisplayName("Test: Red-Black Tree Struct") class RBStructTest { - private val treeW = TreeStructWrapper, RBStateContainer, RBStruct>() + private val treeW = TreeStructWrapper, RBVertex, RBStateContainer, RBStruct>() private var treeStruct = RBStruct() private fun testAssert(msg: String): Nothing = fail(msg) diff --git a/lib/src/test/kotlin/utils/TreeStructWrapper.kt b/lib/src/test/kotlin/utils/TreeStructWrapper.kt index 1bdb93e..64fea41 100644 --- a/lib/src/test/kotlin/utils/TreeStructWrapper.kt +++ b/lib/src/test/kotlin/utils/TreeStructWrapper.kt @@ -3,8 +3,9 @@ package utils import treelib.abstractTree.Node import treelib.abstractTree.StateContainer import treelib.abstractTree.TreeStruct +import treelib.abstractTree.Vertex -class TreeStructWrapper, NodeType : Node, State: StateContainer, TStruct : TreeStruct> { +class TreeStructWrapper, NodeType : Node, VertexType: Vertex, State: StateContainer, TStruct : TreeStruct> { fun getPrivateNode(tree: TStruct, name: String = "root"): NodeType? { val field = tree.javaClass.getDeclaredField(name) diff --git a/lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt b/lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt index 5ce3959..bc79507 100644 --- a/lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt +++ b/lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt @@ -3,12 +3,13 @@ package utils.fuzzers import treelib.binTree.BINNode import treelib.binTree.BINStateContainer import treelib.binTree.BINStruct +import treelib.binTree.BINVertex import utils.BINAnalyzer class BINStructFuzzer>( override val baseInput: Array, override val assertMethod: (input: String) -> Unit -): TreeStructFuzzer, BINAnalyzer, BINStateContainer, BINStruct>() { +): TreeStructFuzzer, BINVertex, BINAnalyzer, BINStateContainer, BINStruct>() { override fun createTreeStruct(): BINStruct = BINStruct() diff --git a/lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt b/lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt index 6b59799..2a6bb7f 100644 --- a/lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt +++ b/lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt @@ -3,12 +3,13 @@ package utils.fuzzers import treelib.rbTree.RBNode import treelib.rbTree.RBStateContainer import treelib.rbTree.RBStruct +import treelib.rbTree.RBVertex import utils.RBAnalyzer class RBStructFuzzer>( override val baseInput: Array, override val assertMethod: (input: String) -> Unit -): TreeStructFuzzer, RBAnalyzer, RBStateContainer, RBStruct>() { +): TreeStructFuzzer, RBVertex, RBAnalyzer, RBStateContainer, RBStruct>() { override fun createTreeStruct(): RBStruct = RBStruct() diff --git a/lib/src/test/kotlin/utils/fuzzers/TreeStructFuzzer.kt b/lib/src/test/kotlin/utils/fuzzers/TreeStructFuzzer.kt index a5390b9..7d5e0d6 100644 --- a/lib/src/test/kotlin/utils/fuzzers/TreeStructFuzzer.kt +++ b/lib/src/test/kotlin/utils/fuzzers/TreeStructFuzzer.kt @@ -3,20 +3,22 @@ package utils.fuzzers import treelib.abstractTree.Node import treelib.abstractTree.StateContainer import treelib.abstractTree.TreeStruct -import kotlin.random.Random -import utils.Analyzer +import treelib.abstractTree.Vertex import treelib.singleObjects.exceptions.* -import kotlin.random.nextInt +import utils.Analyzer import utils.TreeStructWrapper import java.io.File import java.time.Instant +import kotlin.random.Random +import kotlin.random.nextInt abstract class TreeStructFuzzer< Pack : Comparable, NodeType : Node, + VertexType: Vertex, AnalyzerType : Analyzer, State : StateContainer, - TreeStructType : TreeStruct, + TreeStructType : TreeStruct, > { abstract val baseInput: Array @@ -26,7 +28,7 @@ abstract class TreeStructFuzzer< private var dirPath: String? = null - protected val treeWrapper = TreeStructWrapper() + protected val treeWrapper = TreeStructWrapper() protected abstract fun createTreeStruct(): TreeStructType From fc047c023cf71694ed9bce559a8ca91ad2e7974a Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 18 Apr 2023 23:33:36 +0300 Subject: [PATCH 20/84] fix(CI): Add a condition to run jacoco --- .github/workflows/CI.yml | 6 ++++-- lib/src/test/kotlin/{ => treelib}/AVLBalancerTest.kt | 0 lib/src/test/kotlin/{ => treelib}/RBBalancerTest.kt | 0 lib/src/test/kotlin/{ => treelib}/TestModelAVL.kt | 0 lib/src/test/kotlin/{ => treelib}/TestModelRBT.kt | 0 5 files changed, 4 insertions(+), 2 deletions(-) rename lib/src/test/kotlin/{ => treelib}/AVLBalancerTest.kt (100%) rename lib/src/test/kotlin/{ => treelib}/RBBalancerTest.kt (100%) rename lib/src/test/kotlin/{ => treelib}/TestModelAVL.kt (100%) rename lib/src/test/kotlin/{ => treelib}/TestModelRBT.kt (100%) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 8697f86..243bd23 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -22,10 +22,12 @@ jobs: - name: Run Tests run: ./gradlew clean test - - name: Run Test Coverage + - if: matrix.os == 'ubuntu-latest' # Container action is only supported on Linux + name: Run Test Coverage run: ./gradlew jacocoTestReport - - name: Jacoco Code Coverage Report + - if: matrix.os == 'ubuntu-latest' + name: Jacoco Code Coverage Report uses: cicirello/jacoco-badge-generator@v2.8.0 with: generate-branches-badge: true diff --git a/lib/src/test/kotlin/AVLBalancerTest.kt b/lib/src/test/kotlin/treelib/AVLBalancerTest.kt similarity index 100% rename from lib/src/test/kotlin/AVLBalancerTest.kt rename to lib/src/test/kotlin/treelib/AVLBalancerTest.kt diff --git a/lib/src/test/kotlin/RBBalancerTest.kt b/lib/src/test/kotlin/treelib/RBBalancerTest.kt similarity index 100% rename from lib/src/test/kotlin/RBBalancerTest.kt rename to lib/src/test/kotlin/treelib/RBBalancerTest.kt diff --git a/lib/src/test/kotlin/TestModelAVL.kt b/lib/src/test/kotlin/treelib/TestModelAVL.kt similarity index 100% rename from lib/src/test/kotlin/TestModelAVL.kt rename to lib/src/test/kotlin/treelib/TestModelAVL.kt diff --git a/lib/src/test/kotlin/TestModelRBT.kt b/lib/src/test/kotlin/treelib/TestModelRBT.kt similarity index 100% rename from lib/src/test/kotlin/TestModelRBT.kt rename to lib/src/test/kotlin/treelib/TestModelRBT.kt From f4af1f2c95d51badae5a3057c2cb6bd53e43f00b Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 18 Apr 2023 23:36:42 +0300 Subject: [PATCH 21/84] refactor: Rename some methods in test classes --- lib/build.gradle.kts | 6 +++--- lib/src/test/kotlin/treelib/AVLBalancerTest.kt | 2 ++ lib/src/test/kotlin/treelib/RBBalancerTest.kt | 2 ++ lib/src/test/kotlin/treelib/TestModelAVL.kt | 2 ++ lib/src/test/kotlin/treelib/TestModelRBT.kt | 2 ++ 5 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 0f9f88e..6c76505 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -82,7 +82,7 @@ tasks.jacocoTestReport { tasks.jacocoTestCoverageVerification { classDirectories.setFrom( classDirectories.files.flatMap { fileTree(it) { - include("**/RBBalancer.class", "**/AVLBalancer.class", "**/BINStruct") + include("**/RBBalancer.class", "**/AVLBalancer.class", "**/BINStruct", "**/AVLStruct.class", "**/BINStruct.class") } }) dependsOn(tasks.jacocoTestReport) violationRules { @@ -90,7 +90,7 @@ tasks.jacocoTestCoverageVerification { element = "CLASS" limit { counter = "BRANCH" - minimum = 0.4.toBigDecimal() + minimum = 0.5.toBigDecimal() } } rule { @@ -104,7 +104,7 @@ tasks.jacocoTestCoverageVerification { element = "CLASS" limit { counter = "METHOD" - minimum = 1.0.toBigDecimal() + minimum = 0.9.toBigDecimal() } } } diff --git a/lib/src/test/kotlin/treelib/AVLBalancerTest.kt b/lib/src/test/kotlin/treelib/AVLBalancerTest.kt index 862a497..3ee5452 100644 --- a/lib/src/test/kotlin/treelib/AVLBalancerTest.kt +++ b/lib/src/test/kotlin/treelib/AVLBalancerTest.kt @@ -1,3 +1,5 @@ +package treelib + import org.junit.jupiter.api.* import org.junit.jupiter.api.Assertions.assertEquals import treelib.avlTree.AVLBalancer diff --git a/lib/src/test/kotlin/treelib/RBBalancerTest.kt b/lib/src/test/kotlin/treelib/RBBalancerTest.kt index 0bc9e43..d18134e 100644 --- a/lib/src/test/kotlin/treelib/RBBalancerTest.kt +++ b/lib/src/test/kotlin/treelib/RBBalancerTest.kt @@ -1,3 +1,5 @@ +package treelib + import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Nested diff --git a/lib/src/test/kotlin/treelib/TestModelAVL.kt b/lib/src/test/kotlin/treelib/TestModelAVL.kt index c96773d..8a3ba26 100644 --- a/lib/src/test/kotlin/treelib/TestModelAVL.kt +++ b/lib/src/test/kotlin/treelib/TestModelAVL.kt @@ -1,3 +1,5 @@ +package treelib + import treelib.avlTree.AVLNode class TestModelAVL { diff --git a/lib/src/test/kotlin/treelib/TestModelRBT.kt b/lib/src/test/kotlin/treelib/TestModelRBT.kt index ac86a6c..ca7efe7 100644 --- a/lib/src/test/kotlin/treelib/TestModelRBT.kt +++ b/lib/src/test/kotlin/treelib/TestModelRBT.kt @@ -1,3 +1,5 @@ +package treelib + import treelib.rbTree.RBNode import treelib.singleObjects.Markers From c56546bfc5411ca77b4522f7a6992f39aee6f064 Mon Sep 17 00:00:00 2001 From: Georgy S Date: Wed, 19 Apr 2023 01:51:44 +0300 Subject: [PATCH 22/84] feat: Implement class for saving AVLStruct in SQLite. --- gradle.properties | 2 + lib/build.gradle.kts | 7 +- .../kotlin/treelib/controller/DrawVertex.kt | 7 + .../treelib/dbSave/avlSQLite/AVLDrawVertex.kt | 10 + .../treelib/dbSave/avlSQLite/SQLiteAVL.kt | 227 ++++++++++++++++++ 5 files changed, 252 insertions(+), 1 deletion(-) create mode 100644 gradle.properties create mode 100644 lib/src/main/kotlin/treelib/controller/DrawVertex.kt create mode 100644 lib/src/main/kotlin/treelib/dbSave/avlSQLite/AVLDrawVertex.kt create mode 100644 lib/src/main/kotlin/treelib/dbSave/avlSQLite/SQLiteAVL.kt diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..e08d4b3 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,2 @@ +kotlinVersion=1.8.10 +sqliteJdbcVersion=3.41.2.1 diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 09124dc..3782254 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -1,3 +1,5 @@ +val sqliteJdbcVersion: String by project + plugins { java kotlin("jvm") version "1.8.10" @@ -24,6 +26,9 @@ dependencies { testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.2") api("org.apache.commons:commons-math3:3.6.1") implementation("com.google.guava:guava:31.1-jre") + + // JDBC Sqlite + implementation("org.xerial", "sqlite-jdbc", sqliteJdbcVersion) } tasks.test { @@ -113,4 +118,4 @@ publishing { from(components["java"]) } } -} \ No newline at end of file +} diff --git a/lib/src/main/kotlin/treelib/controller/DrawVertex.kt b/lib/src/main/kotlin/treelib/controller/DrawVertex.kt new file mode 100644 index 0000000..8ccd5dc --- /dev/null +++ b/lib/src/main/kotlin/treelib/controller/DrawVertex.kt @@ -0,0 +1,7 @@ +package treelib.controller + +interface DrawVertex> { + val value: Pack + val x: Double + val y: Double +} diff --git a/lib/src/main/kotlin/treelib/dbSave/avlSQLite/AVLDrawVertex.kt b/lib/src/main/kotlin/treelib/dbSave/avlSQLite/AVLDrawVertex.kt new file mode 100644 index 0000000..be2938c --- /dev/null +++ b/lib/src/main/kotlin/treelib/dbSave/avlSQLite/AVLDrawVertex.kt @@ -0,0 +1,10 @@ +package treelib.dbSave.avlSQLite + +import treelib.controller.DrawVertex + +class AVLDrawVertex>( + override val value: Pack, + override val x: Double, + override val y: Double, + val height: Int, +) : DrawVertex diff --git a/lib/src/main/kotlin/treelib/dbSave/avlSQLite/SQLiteAVL.kt b/lib/src/main/kotlin/treelib/dbSave/avlSQLite/SQLiteAVL.kt new file mode 100644 index 0000000..c125768 --- /dev/null +++ b/lib/src/main/kotlin/treelib/dbSave/avlSQLite/SQLiteAVL.kt @@ -0,0 +1,227 @@ +package treelib.dbSave.avlSQLite + +import java.io.Closeable +import java.sql.DriverManager +import java.sql.SQLException + +class SQLiteAVL>( + private val dbPath: String, + private val serializeData: (input: Pack) -> String, + private val deSerializeData: (input: String) -> Pack, + private val logErrorMethod: (input: Exception) -> Unit = { throw it }, + private val logInfoMethod: (input: String) -> Unit = { /* Nothing to do */ }, +) : Closeable { + + private val treeTable = "AVLTreesTable" + private val avlTreeName = "name" + + private val value = "value" + private val height = "height" + private val xCord = "x" + private val yCord = "y" + + private val dbDriver = "jdbc:sqlite" + private val connection = DriverManager.getConnection("$dbDriver:$dbPath") + ?: throw SQLException("Cannot connect to database") + + init { + createTreeTable() + } + + fun createTreeTable() { + connection.createStatement().also { stmt -> + try { + stmt.execute("CREATE TABLE if not exists $treeTable(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name text);") + logInfoMethod("Table with trees created or already exists") + } catch (ex: SQLException) { + logErrorMethod(ex) + } finally { + stmt.close() + } + } + } + + fun clearTreeTable() { + connection.createStatement().also { stmt -> + try { + stmt.execute("DELETE FROM $treeTable;") + logInfoMethod("TreeTable: $treeTable has been deleted") + } catch (ex: SQLException) { + logErrorMethod(ex) + } finally { + stmt.close() + } + } + } + + fun addTree(treeName: String) { + val isInDB = isNameInDB(treeName, avlTreeName, treeTable) + + if (isInDB) { + logInfoMethod("Tree - $treeName, have been exist yet in treeTable - $treeTable") + return + } + + connection.createStatement().also { stmt -> + try { + stmt.execute("CREATE TABLE if not exists $treeName(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, $value text, $height INT, $xCord DOUBLE, $yCord DOUBLE);") + stmt.execute("INSERT INTO $treeTable ($avlTreeName) VALUES ('$treeName');") + logInfoMethod("Was created Tree: $treeName in table: $treeTable") + } catch (ex: SQLException) { + logErrorMethod(ex) + } finally { + stmt.close() + } + } + } + + fun getTreeNames(): MutableList { + val info = mutableListOf() + connection.createStatement().also { stmt -> + try { + val result = stmt.executeQuery("SELECT $treeTable.$avlTreeName as $avlTreeName FROM $treeTable;") + while (result.next()) { + info.add(result.getString(avlTreeName)) + } + logInfoMethod("") + } catch (ex: SQLException) { + logErrorMethod(ex) + } finally { + stmt.close() + } + return info + } + } + + fun deleteTree(treeName: String) { + val deleteId = getTreeId(treeName) + if (deleteId == 0) return + + connection.createStatement().also { stmt -> + try { + stmt.execute("DROP TABLE $treeName;") + stmt.execute("DELETE FROM $treeTable WHERE id=$deleteId;") + logInfoMethod("Tree: $treeName has been deleted") + } catch (ex: SQLException) { + logErrorMethod(ex) + } finally { + stmt.close() + } + } + } + + private fun getTreeId(treeName: String): Int { + var id: Int? = null + try { + val statement = connection.prepareStatement("SELECT id FROM $treeTable WHERE name=?;") + statement.setString(1, treeName) + id = statement.executeQuery().getInt(1) + statement.close() + } catch (ex: SQLException) { + logErrorMethod(ex) + } + if (id != null) return id + else throw SQLException("Impossible case") + } + + fun addVertex(avlDVertex: AVLDrawVertex, treeName: String) { + val isInDB = getVertexId(avlDVertex, treeName) + if (isInDB != 0) { + deleteVertex(isInDB, treeName) + logInfoMethod("Attempt write duplicate of the vertex: value = ${avlDVertex.value}; hieght = ${avlDVertex.height}; x = ${avlDVertex.x}; y = ${avlDVertex.y}") + } + + try { + val stmt = connection.prepareStatement("INSERT INTO $treeName (value, height, x, y) VALUES (?, ?, ?, ?);") + val info = serializeData(avlDVertex.value) + stmt.setString(1, info) + stmt.setInt(2, avlDVertex.height) + stmt.setDouble(3, avlDVertex.x) + stmt.setDouble(4, avlDVertex.y) + stmt.execute() + stmt.close() + logInfoMethod("Vertex: value = $info has been saved") + } catch (ex: SQLException) { + logErrorMethod(ex) + } + + } + + fun addVertexes(list: List>, treeName: String) { + for (el in list) addVertex(el, treeName) + } + + fun deleteVertex(id: Int, treeName: String) { + try { + val stmt = connection.prepareStatement("DELETE FROM $treeName WHERE id=?;") + stmt.setInt(1, id) + stmt.execute() + stmt.close() + logInfoMethod("Element: id = $id has been deleted in table: $treeName") + } catch (ex: SQLException) { + logErrorMethod(ex) + } + } + + fun getAllVertexes(treeName: String): MutableList> { + val info = mutableListOf>() + connection.createStatement().also { stmt -> + try { + val result = + stmt.executeQuery("SELECT $treeName.$value as $value, $treeName.$height as $height, $treeName.$xCord as $xCord, $treeName.$yCord as $yCord FROM $treeName;") + while (result.next()) { + info.add( + AVLDrawVertex( + value = deSerializeData(result.getString(value)), + height = result.getInt(height), + x = result.getDouble(xCord), + y = result.getDouble(yCord), + ) + ) + } + logInfoMethod("Vertexes from $treeName have been received") + } catch (ex: SQLException) { + logErrorMethod(ex) + } finally { + stmt.close() + } + return info + } + } + + private fun getVertexId(vertex: AVLDrawVertex, tableName: String): Int { + var id: Int? = null + try { + val stmt = + connection.prepareStatement("SELECT id FROM $tableName WHERE value=? AND height=? AND x=? AND y=?;") + stmt.setString(1, serializeData(vertex.value)) + stmt.setInt(2, vertex.height) + stmt.setDouble(3, vertex.x) + stmt.setDouble(4, vertex.y) + id = stmt.executeQuery().getInt(1) + stmt.close() + } catch (ex: SQLException) { + logErrorMethod(ex) + } + if (id != null) return id + else throw SQLException("Impossible case") + } + + private fun isNameInDB(rowName: String, columnName: String, tableName: String): Boolean { + var isInDB: Boolean? = null + try { + val statement = connection.prepareStatement("SELECT EXISTS(SELECT 1 FROM $tableName WHERE $columnName=?);") + statement.setString(1, rowName) + isInDB = statement.executeQuery().getBoolean(1) + statement.close() + } catch (ex: SQLException) { + logErrorMethod(ex) + } + if (isInDB != null) return isInDB + else throw SQLException("Impossible case") + } + + override fun close() { + connection.close() + } +} From f964e3d659af14af5d9a489b4b92dceb039af329 Mon Sep 17 00:00:00 2001 From: Aleksandr Date: Wed, 19 Apr 2023 01:59:08 +0300 Subject: [PATCH 23/84] feat:add TreeWrapper and BINTreeTest --- lib/build.gradle.kts | 2 + lib/src/test/kotlin/treelib/BINTreeTest.kt | 86 ++++++++++++++++++++++ lib/src/test/kotlin/utils/TreeWrapper.kt | 24 ++++++ 3 files changed, 112 insertions(+) create mode 100644 lib/src/test/kotlin/treelib/BINTreeTest.kt create mode 100644 lib/src/test/kotlin/utils/TreeWrapper.kt diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 09124dc..99f9538 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -19,6 +19,7 @@ repositories { } dependencies { + testImplementation("org.junit.jupiter:junit-jupiter-params:5.9.2") testImplementation("io.mockk:mockk:1.13.4") testImplementation("org.jetbrains.kotlin:kotlin-test-junit5:1.8.10") testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.2") @@ -26,6 +27,7 @@ dependencies { implementation("com.google.guava:guava:31.1-jre") } + tasks.test { finalizedBy(tasks.jacocoTestReport) useJUnitPlatform() diff --git a/lib/src/test/kotlin/treelib/BINTreeTest.kt b/lib/src/test/kotlin/treelib/BINTreeTest.kt new file mode 100644 index 0000000..172c545 --- /dev/null +++ b/lib/src/test/kotlin/treelib/BINTreeTest.kt @@ -0,0 +1,86 @@ +package treelib + +import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource +import treelib.binTree.BINNode +import treelib.binTree.BINStateContainer +import treelib.binTree.BINStruct +import treelib.binTree.BINTree +import utils.TreeWrapper +import treelib.singleObjects.Container +import utils.TreeStructWrapper +import kotlin.test.assertEquals + +class BINTreeTest { + private val tree = BINTree() + private val treeW = + TreeWrapper>, BINStateContainer>, BINStruct>, BINTree>() + private val treeSW = + TreeStructWrapper, BINNode>, BINStateContainer>, BINStruct>>() + + +// line - 0.6, branch - 0.5, methods = 0.9 + @ParameterizedTest + @ValueSource(ints = [1, 2, 0, 6, 4]) + fun `test putItem`(str: Int) { + tree.putItem((Pair(str, 1))) + } + + @ParameterizedTest + @ValueSource(strings = ["1 2 3 4", "5 6 7 8 9"]) + fun `test putItems`(str: String) { + val numbers = str.split(" ").map{ it.toInt() }.toMutableList() + val num = mutableListOf>() + for (i in numbers) { + num.add(Pair(i, 1)) + } + tree.putItems(num) + assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, actual = numbers[0]) + assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.right?.value?.key, actual = numbers[1]) + } + + @Test + fun `test getItem`() { + val num = mutableListOf(Pair(1, 1), Pair(2, 1), Pair(5, 1), Pair(4, 1), Pair(3, 5)) + tree.putItems(num) + val temp = tree.getItem(3) + + assertEquals( + expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.right?.right?.left?.left?.value?.value, + actual = temp + ) + } + + @ParameterizedTest + @ValueSource(strings = ["5 2 3", "5 6 7", "5 6 13", "5 6 1", "192 5 6"]) + fun `test putItems and delete`(str: String) { + val numbers = str.split(" ").map{ it.toInt() }.toMutableList() + val num = mutableListOf>() + for (i in numbers) { + num.add(Pair(i, 1)) + } + tree.putItems(num) + tree.deleteItem(numbers[2]) + + assertEquals(expected = tree.getItem(numbers[2]), actual = null) + assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, actual = numbers[0]) + } + + @ParameterizedTest + @ValueSource(strings = ["5 2 3 9", "5 6 7 1", "5 6 13 4", "5 6 1", "192 5 6 222"]) + fun `test putItems and delete root`(str: String) { + val numbers = str.split(" ").map{ it.toInt() }.toMutableList() + val num = mutableListOf>() + for (i in numbers) { + num.add(Pair(i, 1)) + } + tree.putItems(num) + val root = numbers[0] + numbers.sort() + val index = numbers.indexOf(root) + tree.deleteItem(root) + + assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, actual = numbers[index + 1]) + } +} \ No newline at end of file diff --git a/lib/src/test/kotlin/utils/TreeWrapper.kt b/lib/src/test/kotlin/utils/TreeWrapper.kt new file mode 100644 index 0000000..5ca8ea7 --- /dev/null +++ b/lib/src/test/kotlin/utils/TreeWrapper.kt @@ -0,0 +1,24 @@ +package utils + +import treelib.abstractTree.Node +import treelib.abstractTree.StateContainer +import treelib.abstractTree.Tree +import treelib.abstractTree.TreeStruct +import treelib.singleObjects.Container + + +class TreeWrapper < + V : Comparable, + Value, + NodeType: Node, NodeType>, + State: StateContainer, NodeType>, + TStruct: TreeStruct, NodeType, State>, + Wood : Tree> { + fun getPrivateNode(tree: Wood, name: String = "treeStruct"): TStruct { + val treeS = tree.javaClass.getDeclaredField(name) + treeS.isAccessible = true + val treeStruct = treeS.get(tree) + + return treeStruct as TStruct + } +} \ No newline at end of file From f1d668a041292f6f613aee4fd599c8175f3a49f3 Mon Sep 17 00:00:00 2001 From: Aleksandr Date: Wed, 19 Apr 2023 03:15:39 +0300 Subject: [PATCH 24/84] fix: delete !! --- lib/src/test/kotlin/treelib/AVLStructTest.kt | 35 ++++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/lib/src/test/kotlin/treelib/AVLStructTest.kt b/lib/src/test/kotlin/treelib/AVLStructTest.kt index 347892c..1e522fe 100644 --- a/lib/src/test/kotlin/treelib/AVLStructTest.kt +++ b/lib/src/test/kotlin/treelib/AVLStructTest.kt @@ -28,7 +28,10 @@ class AVLStructTest { for (i in num) { treeStruct.insert(i) } - treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + val node = treeW.getPrivateNode(treeStruct) + if (node != null) { + treeW.getPrivateNode(treeStruct)?.let { treeH.checkTree(it) } + } } @Test @@ -37,7 +40,10 @@ class AVLStructTest { for (i in num) { treeStruct.insert(i) } - treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + val node = treeW.getPrivateNode(treeStruct) + if (node != null) { + treeW.getPrivateNode(treeStruct)?.let { treeH.checkTree(it) } + } } @Test @@ -47,7 +53,10 @@ class AVLStructTest { treeStruct.insert(i) } treeStruct.delete(2) - treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + val node = treeW.getPrivateNode(treeStruct) + if (node != null) { + treeW.getPrivateNode(treeStruct)?.let { treeH.checkTree(it) } + } } @Test @@ -55,7 +64,10 @@ class AVLStructTest { for (i in 1..100000) { treeStruct.insert(i) } - treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + val node = treeW.getPrivateNode(treeStruct) + if (node != null) { + treeW.getPrivateNode(treeStruct)?.let { treeH.checkTree(it) } + } } @Test @@ -64,14 +76,20 @@ class AVLStructTest { treeStruct.insert(i) } treeStruct.delete(5000) - treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + val node = treeW.getPrivateNode(treeStruct) + if (node != null) { + treeW.getPrivateNode(treeStruct)?.let { treeH.checkTree(it) } + } } @Test fun `test two arguments`() { treeStruct.insert(2) treeStruct.insert(3) - treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + val node = treeW.getPrivateNode(treeStruct) + if (node != null) { + treeW.getPrivateNode(treeStruct)?.let { treeH.checkTree(it) } + } } @Test @@ -80,6 +98,9 @@ class AVLStructTest { for (i in num) { treeStruct.insert(i) } - treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + val node = treeW.getPrivateNode(treeStruct) + if (node != null) { + treeW.getPrivateNode(treeStruct)?.let { treeH.checkTree(it) } + } } } \ No newline at end of file From e90c4fd0b4281d404457f6e9ef336b8791fc4c6f Mon Sep 17 00:00:00 2001 From: Georgy S Date: Wed, 19 Apr 2023 03:20:10 +0300 Subject: [PATCH 25/84] feat: Implement AVLStruct.restoreStruct and BINStruct.restoreStruct. --- lib/src/main/kotlin/Controller.kt | 2 +- .../kotlin/treelib/abstractTree/TreeStruct.kt | 2 +- .../main/kotlin/treelib/avlTree/AVLStruct.kt | 15 ++++++++++++--- .../main/kotlin/treelib/binTree/BINStruct.kt | 13 +++++++++++++ lib/src/main/kotlin/treelib/rbTree/RBStruct.kt | 3 +-- .../singleObjects/exceptions/IncorrectUsage.kt | 18 ++++++++++++++++++ lib/src/test/kotlin/treeTests/RBTreeTest.kt | 16 ++++++++++++++++ 7 files changed, 62 insertions(+), 7 deletions(-) create mode 100644 lib/src/main/kotlin/treelib/singleObjects/exceptions/IncorrectUsage.kt create mode 100644 lib/src/test/kotlin/treeTests/RBTreeTest.kt diff --git a/lib/src/main/kotlin/Controller.kt b/lib/src/main/kotlin/Controller.kt index a59a3b0..e32442e 100644 --- a/lib/src/main/kotlin/Controller.kt +++ b/lib/src/main/kotlin/Controller.kt @@ -14,7 +14,7 @@ class Controller { neo4jDB.exportRBtree() val RBtree = RBStruct>>() - RBtree.restoreTreeFromDatabase(orders.first, orders.second) + RBtree.restoreStruct(orders.first, orders.second) neo4jDB.close() } diff --git a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt index c91c6ed..d9b223b 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt @@ -15,7 +15,7 @@ abstract class TreeStruct< protected abstract var root: NodeType? - private fun getLeafForInsert(item: Pack): NodeType? { + protected fun getLeafForInsert(item: Pack): NodeType? { var currentNode: NodeType? = root ?: return null while (true) { diff --git a/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt b/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt index 7893341..b0ee0ae 100644 --- a/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt +++ b/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt @@ -1,6 +1,7 @@ package treelib.avlTree import treelib.abstractTree.balanced.BalancedTreeStruct +import treelib.singleObjects.exceptions.IncorrectUsage class AVLStruct> : BalancedTreeStruct, AVLStateContainer, AVLVertex, AVLBalancer>() { @@ -40,9 +41,9 @@ class AVLStruct> : } } - override fun toVertex(node: AVLNode): AVLVertex { - return AVLVertex(node.value, node.height) - } + override fun toVertex(node: AVLNode): AVLVertex = AVLVertex(node.value, node.height) + + fun toNode(vertex: AVLVertex): AVLNode = AVLNode(value = vertex.value, height = vertex.height) override fun createNode(item: Pack): AVLNode = AVLNode(item) @@ -56,4 +57,12 @@ class AVLStruct> : } return node } + fun > restoreStruct(preOrder: List){ + if (root != null) throw IncorrectUsage("The tree already exists") + for (vertex in preOrder){ + val currentNode = toNode(vertex) + val leaf = getLeafForInsert(currentNode.value) + linkNewNode(currentNode, leaf) + } + } } diff --git a/lib/src/main/kotlin/treelib/binTree/BINStruct.kt b/lib/src/main/kotlin/treelib/binTree/BINStruct.kt index f3bfc09..ea03cb6 100644 --- a/lib/src/main/kotlin/treelib/binTree/BINStruct.kt +++ b/lib/src/main/kotlin/treelib/binTree/BINStruct.kt @@ -1,6 +1,8 @@ package treelib.binTree import treelib.abstractTree.TreeStruct +import treelib.abstractTree.Vertex +import treelib.singleObjects.exceptions.IncorrectUsage class BINStruct> : TreeStruct, BINStateContainer, BINVertex>() { @@ -66,4 +68,15 @@ class BINStruct> : override fun insert(item: Pack) { insertItem(item).contentNode } + + private fun toNode(vertex: BINVertex): BINNode = BINNode(value = vertex.value) + + fun > restoreStruct(preOrder: List){ + if (root != null) throw IncorrectUsage("The tree already exists") + for (vertex in preOrder){ + val currentNode = toNode(vertex) + val leaf = getLeafForInsert(currentNode.value) + linkNewNode(currentNode, leaf) + } + } } diff --git a/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt b/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt index 47dd91d..999c113 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt @@ -76,7 +76,7 @@ class RBStruct> : return node } - fun > restoreTreeFromDatabase(preOrder: List, inOrder: List) { + fun > restoreStruct(preOrder: List, inOrder: List) { var inOrderIndex = 0 var preOrderIndex = 0 val set = HashSet>() @@ -117,7 +117,6 @@ class RBStruct> : stack.push(currentNode) } } - } private fun > createRBNode(drawNode: RBVertexType): RBNode { diff --git a/lib/src/main/kotlin/treelib/singleObjects/exceptions/IncorrectUsage.kt b/lib/src/main/kotlin/treelib/singleObjects/exceptions/IncorrectUsage.kt new file mode 100644 index 0000000..9fce7ef --- /dev/null +++ b/lib/src/main/kotlin/treelib/singleObjects/exceptions/IncorrectUsage.kt @@ -0,0 +1,18 @@ +package treelib.singleObjects.exceptions + +class IncorrectUsage : Exception { + constructor() : super( + "Incorrect use of the tree" + ) + + constructor(message: String) : super( + "$message", + ) + + constructor(message: String, cause: Throwable) : super( + "$message", + cause, + ) + + constructor(cause: Throwable) : super(cause) +} \ No newline at end of file diff --git a/lib/src/test/kotlin/treeTests/RBTreeTest.kt b/lib/src/test/kotlin/treeTests/RBTreeTest.kt new file mode 100644 index 0000000..fa56cc6 --- /dev/null +++ b/lib/src/test/kotlin/treeTests/RBTreeTest.kt @@ -0,0 +1,16 @@ +package treeTests + +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import treelib.rbTree.RBTree + +@DisplayName("Test: Red-Black Tree") +class RBTreeTest { + private var rbTree = RBTree() + + @Test + fun `insert two elements`(){ + rbTree.putItem(Pair(25, 1)) + rbTree.putItem(Pair(15, 1)) + } +} \ No newline at end of file From b2d93053df81c05a92019f856ce3d183080dc0cf Mon Sep 17 00:00:00 2001 From: Aleksandr Date: Wed, 19 Apr 2023 03:29:17 +0300 Subject: [PATCH 26/84] feat: AVLTreeTest --- lib/src/test/kotlin/treelib/AVLTreeTest.kt | 76 ++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 lib/src/test/kotlin/treelib/AVLTreeTest.kt diff --git a/lib/src/test/kotlin/treelib/AVLTreeTest.kt b/lib/src/test/kotlin/treelib/AVLTreeTest.kt new file mode 100644 index 0000000..5531d35 --- /dev/null +++ b/lib/src/test/kotlin/treelib/AVLTreeTest.kt @@ -0,0 +1,76 @@ +package treelib + +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource +import treelib.avlTree.AVLNode +import treelib.avlTree.AVLStateContainer +import treelib.avlTree.AVLStruct +import treelib.avlTree.AVLTree +import treelib.singleObjects.Container +import utils.TreeStructWrapper +import utils.TreeWrapper +import kotlin.test.assertEquals + + +class AVLTreeTest { + private val tree = AVLTree() + private val treeW = + TreeWrapper>, AVLStateContainer>, AVLStruct>, AVLTree>() + private val treeSW = + TreeStructWrapper, AVLNode>, AVLStateContainer>, AVLStruct>>() + + + @ParameterizedTest + @ValueSource(strings = ["5 3 8 9", "1 2 3 4", "4 3 5 2", "4 3 2 1", "2 3 1 4"]) + fun `test check root`(str: String) { + val numbers = str.split(" ").map{ it.toInt() }.toMutableList() + val num = mutableListOf>() + for (i in numbers) { + num.add(Pair(i, 1)) + } + tree.putItems(num) + + numbers.sort() + val root = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key + if (root == numbers[1]) { + assertEquals(expected = root, actual = numbers[1]) + } + else { + assertEquals(expected = root, actual = numbers[2]) + } + } + + @ParameterizedTest + @ValueSource(strings = ["1 1000", "1 10000", "1 100000", "1 1000000"]) + fun `test add many args and delete root`(str: String) { + val numbers = str.split(" ").map{ it.toInt() }.toMutableList() + for (i in numbers[0] .. numbers[1]) { + tree.putItem(Pair(i, i)) + } + val root = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key + if (root != null) { + treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.let { tree.deleteItem(it.key) } + } + + when (numbers[1]) { + 1000 -> assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, actual = 513) + 10000 -> assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, actual = 4097) + 100000 -> assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, actual = 65537) + else -> assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, actual = 524289) + } + } + + @ParameterizedTest + @ValueSource(strings = ["5", "0"]) + fun `test delete root one arg`(str: String) { + val numbers = str.split(" ").map{ it.toInt() }.toMutableList() + val num = mutableListOf>() + for (i in numbers) { + num.add(Pair(i, 1)) + } + tree.putItems(num) + tree.deleteItem(numbers[0]) + + assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, actual = null) + } +} \ No newline at end of file From ac11aa1898aaaa67f3f0fbb5b1fa331208281eda Mon Sep 17 00:00:00 2001 From: Aleksandr Date: Wed, 19 Apr 2023 04:26:57 +0300 Subject: [PATCH 27/84] feat: RBTreeTest --- lib/src/test/kotlin/treelib/RBTreeTest.kt | 58 +++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 lib/src/test/kotlin/treelib/RBTreeTest.kt diff --git a/lib/src/test/kotlin/treelib/RBTreeTest.kt b/lib/src/test/kotlin/treelib/RBTreeTest.kt new file mode 100644 index 0000000..5a3ceee --- /dev/null +++ b/lib/src/test/kotlin/treelib/RBTreeTest.kt @@ -0,0 +1,58 @@ +package treelib + +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource +import treelib.rbTree.RBNode +import treelib.rbTree.RBStateContainer +import treelib.rbTree.RBStruct +import treelib.rbTree.RBTree +import treelib.singleObjects.Container +import treelib.singleObjects.Markers +import utils.TreeStructWrapper +import utils.TreeWrapper +import kotlin.test.assertEquals + +class RBTreeTest { + private val tree = RBTree() + private val treeW = + TreeWrapper>, RBStateContainer>, RBStruct>, RBTree>() + private val treeSW = + TreeStructWrapper, RBNode>, RBStateContainer>, RBStruct>>() + + + @ParameterizedTest + @ValueSource(strings = ["1 2 3 4 6 5", "5 3 8 6 9 11 13", "10 11 15 12 17 18"]) + fun `test change color delete root`(str: String) { + val numbers = str.split(" ").map { it.toInt() }.toMutableList() + val num = mutableListOf>() + for (i in numbers) { + num.add(Pair(i, i)) + } + + tree.putItems(num) + + val rootR = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.right?.color + assertEquals(expected = rootR, actual = Markers.RED) + val root = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key + if (root != null) { + treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.let { tree.deleteItem(it.key) } + } + assertEquals(expected = rootR, actual = Markers.RED) + } + + @ParameterizedTest + @ValueSource(strings = ["1 2 5", "1 11 13", "10 11 18"]) + fun `test check color`(str: String) { + val numbers = str.split(" ").map { it.toInt() }.toMutableList() + val num = mutableListOf>() + for (i in numbers) { + num.add(Pair(i, i)) + } + + tree.putItems(num) + + assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.right?.color, actual = Markers.RED) + assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.left?.color, actual = Markers.RED) + assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.color, actual = Markers.BLACK) + } +} \ No newline at end of file From cd10d0d0801ecd71ddf3f44900d8c5ec9d272013 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 19 Apr 2023 04:39:37 +0300 Subject: [PATCH 28/84] feat: Implement sketch of jsonRepository --- .gitignore | 1 + lib/build.gradle.kts | 3 + .../Neo4jController.kt} | 6 +- .../kotlin/dbSave/jsonFormat/DrawBINVertex.kt | 9 +++ .../dbSave/jsonFormat/JsonRepository.kt | 34 ++++++++++ .../kotlin/{ => dbSave/neo4j}/CONTAINER.conf | 0 .../rbTree => dbSave/neo4j}/DrawRBVertex.kt | 3 +- .../neo4j/Neo4jRepository.kt} | 4 +- .../kotlin/{ => dbSave/neo4j}/testNeo4j.sh | 11 ---- lib/src/main/kotlin/initNeo4j.sh | 0 lib/src/main/kotlin/loadNeo4j.sh | 8 --- lib/src/main/kotlin/treelib/DBNodeRB.kt | 11 ---- lib/src/main/kotlin/treelib/Main.kt | 66 ------------------- .../main/kotlin/treelib/binTree/BINVertex.kt | 2 +- 14 files changed, 57 insertions(+), 101 deletions(-) rename lib/src/main/kotlin/{Controller.kt => controller/Neo4jController.kt} (91%) create mode 100644 lib/src/main/kotlin/dbSave/jsonFormat/DrawBINVertex.kt create mode 100644 lib/src/main/kotlin/dbSave/jsonFormat/JsonRepository.kt rename lib/src/main/kotlin/{ => dbSave/neo4j}/CONTAINER.conf (100%) rename lib/src/main/kotlin/{treelib/rbTree => dbSave/neo4j}/DrawRBVertex.kt (79%) rename lib/src/main/kotlin/{DataBase.kt => dbSave/neo4j/Neo4jRepository.kt} (99%) rename lib/src/main/kotlin/{ => dbSave/neo4j}/testNeo4j.sh (59%) delete mode 100644 lib/src/main/kotlin/initNeo4j.sh delete mode 100644 lib/src/main/kotlin/loadNeo4j.sh delete mode 100644 lib/src/main/kotlin/treelib/DBNodeRB.kt delete mode 100644 lib/src/main/kotlin/treelib/Main.kt diff --git a/.gitignore b/.gitignore index 38f0b3d..16cba14 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ /build/ /lib/build/ /lib/TEST_TEST/ +/gradle/ diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 6c76505..db61e37 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -22,6 +22,8 @@ dependencies { api("org.apache.commons:commons-math3:3.6.1") implementation("com.google.guava:guava:31.1-jre") + implementation("com.google.code.gson:gson:2.8.5") + val neo4jCore = "4.0.5" implementation("org.neo4j", "neo4j-ogm-core", neo4jCore) implementation("org.neo4j", "neo4j-ogm-bolt-driver", neo4jCore) @@ -30,6 +32,7 @@ dependencies { testImplementation("org.jetbrains.kotlin:kotlin-test-junit5:1.8.10") testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.2") implementation(kotlin("stdlib-jdk8")) + } tasks.test { diff --git a/lib/src/main/kotlin/Controller.kt b/lib/src/main/kotlin/controller/Neo4jController.kt similarity index 91% rename from lib/src/main/kotlin/Controller.kt rename to lib/src/main/kotlin/controller/Neo4jController.kt index a59a3b0..3744351 100644 --- a/lib/src/main/kotlin/Controller.kt +++ b/lib/src/main/kotlin/controller/Neo4jController.kt @@ -1,9 +1,11 @@ +package controller -import treelib.rbTree.DrawRBVertex +import dbSave.neo4j.DrawRBVertex +import dbSave.neo4j.Neo4jRepository import treelib.rbTree.RBStruct import treelib.singleObjects.Container -class Controller { +class Neo4jController { fun initTree() { val neo4jDB = Neo4jRepository() diff --git a/lib/src/main/kotlin/dbSave/jsonFormat/DrawBINVertex.kt b/lib/src/main/kotlin/dbSave/jsonFormat/DrawBINVertex.kt new file mode 100644 index 0000000..783a1de --- /dev/null +++ b/lib/src/main/kotlin/dbSave/jsonFormat/DrawBINVertex.kt @@ -0,0 +1,9 @@ +package dbSave.jsonFormat + +import treelib.binTree.BINVertex + +class DrawBINVertex>( + value: Pack, + val x: Double = 0.0, + val y: Double = 0.0 +) : BINVertex(value) \ No newline at end of file diff --git a/lib/src/main/kotlin/dbSave/jsonFormat/JsonRepository.kt b/lib/src/main/kotlin/dbSave/jsonFormat/JsonRepository.kt new file mode 100644 index 0000000..88a1396 --- /dev/null +++ b/lib/src/main/kotlin/dbSave/jsonFormat/JsonRepository.kt @@ -0,0 +1,34 @@ +package dbSave.jsonFormat +import com.google.common.reflect.TypeToken +import com.google.gson.GsonBuilder +import java.io.File + +class JsonRepository>(private val dirPath: String) { + + init { + File(dirPath).mkdirs() + } + + fun saveChanges(preOrder: Array>, typeToken: TypeToken>>, fileName: String) { + + val gson = GsonBuilder().setPrettyPrinting().create() + val json = gson.toJson(preOrder) + + File(dirPath, fileName).run { + createNewFile() + writeText(json) + } + + val preOrd = gson.fromJson>>(json, typeToken.type) + + } + + fun exportTree(fileName: String) { + val gson = GsonBuilder().setPrettyPrinting().create() + //val json = gson.fromJson(File(dirPath, fileName).readText(), ArrayVertices::class.java) + + + } + + +} \ No newline at end of file diff --git a/lib/src/main/kotlin/CONTAINER.conf b/lib/src/main/kotlin/dbSave/neo4j/CONTAINER.conf similarity index 100% rename from lib/src/main/kotlin/CONTAINER.conf rename to lib/src/main/kotlin/dbSave/neo4j/CONTAINER.conf diff --git a/lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt b/lib/src/main/kotlin/dbSave/neo4j/DrawRBVertex.kt similarity index 79% rename from lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt rename to lib/src/main/kotlin/dbSave/neo4j/DrawRBVertex.kt index b3ee499..37100de 100644 --- a/lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt +++ b/lib/src/main/kotlin/dbSave/neo4j/DrawRBVertex.kt @@ -1,5 +1,6 @@ -package treelib.rbTree +package dbSave.neo4j +import treelib.rbTree.RBVertex import treelib.singleObjects.Markers class DrawRBVertex>( diff --git a/lib/src/main/kotlin/DataBase.kt b/lib/src/main/kotlin/dbSave/neo4j/Neo4jRepository.kt similarity index 99% rename from lib/src/main/kotlin/DataBase.kt rename to lib/src/main/kotlin/dbSave/neo4j/Neo4jRepository.kt index 809eb64..316dc4c 100644 --- a/lib/src/main/kotlin/DataBase.kt +++ b/lib/src/main/kotlin/dbSave/neo4j/Neo4jRepository.kt @@ -1,9 +1,11 @@ +package dbSave.neo4j + + import org.neo4j.driver.AuthTokens import org.neo4j.driver.Driver import org.neo4j.driver.GraphDatabase import org.neo4j.driver.TransactionContext import org.neo4j.driver.exceptions.SessionExpiredException -import treelib.rbTree.DrawRBVertex import treelib.singleObjects.Container import treelib.singleObjects.Markers import java.io.Closeable diff --git a/lib/src/main/kotlin/testNeo4j.sh b/lib/src/main/kotlin/dbSave/neo4j/testNeo4j.sh similarity index 59% rename from lib/src/main/kotlin/testNeo4j.sh rename to lib/src/main/kotlin/dbSave/neo4j/testNeo4j.sh index 87b69c4..6b07269 100644 --- a/lib/src/main/kotlin/testNeo4j.sh +++ b/lib/src/main/kotlin/dbSave/neo4j/testNeo4j.sh @@ -3,7 +3,6 @@ BASEDIR=$(realpath "$(dirname "$0")") . "${BASEDIR}/CONTAINER.conf" -# -d docker run \ -i \ --name "$CONTAINER_NAME" \ @@ -12,13 +11,3 @@ docker run \ --publish=7474:7474 --publish=7687:7687 \ --env NEO4J_AUTH=neo4j/"$PASSWORD" \ neo4j:latest \ -# -c /bin/bash -#neo4j-admin database dump neo4j --to-path=$HOME/neo4j/data:/data - -#docker ps -a - -#docker stop "$CONTAINER_NAME" - -#cp $HOME/neo4j/data:/data $HOME/ - -#docker stop neo4j:latest diff --git a/lib/src/main/kotlin/initNeo4j.sh b/lib/src/main/kotlin/initNeo4j.sh deleted file mode 100644 index e69de29..0000000 diff --git a/lib/src/main/kotlin/loadNeo4j.sh b/lib/src/main/kotlin/loadNeo4j.sh deleted file mode 100644 index d4d9fcd..0000000 --- a/lib/src/main/kotlin/loadNeo4j.sh +++ /dev/null @@ -1,8 +0,0 @@ - -BASEDIR=$(realpath "$(dirname "$0")") - -. "${BASEDIR}/CONTAINER.conf" - -docker stop "$CONTAINER_NAME" - -neo4j-admin dump --database=neo4j --to=/data/backups/ \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/DBNodeRB.kt b/lib/src/main/kotlin/treelib/DBNodeRB.kt deleted file mode 100644 index cf067e1..0000000 --- a/lib/src/main/kotlin/treelib/DBNodeRB.kt +++ /dev/null @@ -1,11 +0,0 @@ -package treelib - -import treelib.singleObjects.Markers - - -class DBNodeRB>( - val value: Pack, - val color: Markers = Markers.RED, - val x: Double = 0.0, - val y: Double = 0.0 -) diff --git a/lib/src/main/kotlin/treelib/Main.kt b/lib/src/main/kotlin/treelib/Main.kt deleted file mode 100644 index 15e0eab..0000000 --- a/lib/src/main/kotlin/treelib/Main.kt +++ /dev/null @@ -1,66 +0,0 @@ -package treelib - -import Controller -import treelib.rbTree.RBStruct -import treelib.singleObjects.Container - - -fun main() { - // 25, 15, 10, 4, 12, 22, 18, 24, 50, 35, 31, 44, 70, 66, 90 - // 4, 10, 12, 15, 18, 22, 24, 25, 31, 35, 44, 50, 66, 70, 90 - - /* - - val neo4jRep = Neo4jRepository() - val a1 = DBNodeRB(Container(Pair(1, 25))) - val a2 = DBNodeRB(Container(Pair(1, 15))) - val a3 = DBNodeRB(Container(Pair(1, 10))) - val a4 = DBNodeRB(Container(Pair(1, 4))) - val a5 = DBNodeRB(Container(Pair(1, 12))) - val a6 = DBNodeRB(Container(Pair(1, 22))) - val a7 = DBNodeRB(Container(Pair(1, 18))) - val a8 = DBNodeRB(Container(Pair(1, 24))) - val a9 = DBNodeRB(Container(Pair(1, 50))) - val a10 = DBNodeRB(Container(Pair(1, 35))) - val a11 = DBNodeRB(Container(Pair(1, 31))) - val a12 = DBNodeRB(Container(Pair(1, 44))) - val a13 = DBNodeRB(Container(Pair(1, 70))) - val a14 = DBNodeRB(Container(Pair(1, 66))) - val a15 = DBNodeRB(Container(Pair(1, 90))) - val preArr = arrayOf(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) - val inArr = arrayOf(a4, a3, a5, a2, a7, a6, a8, a1, a11, a10, a12, a9, a14, a13, a15) - neo4jRep.open("bolt://localhost:7687", "neo4j", "test-neo4j") - neo4jRep.saveChanges(preArr, inArr) - */ - - val tree = RBStruct>() - tree.insert(Container(Pair(25 , 1))) - tree.insert(Container(Pair(15 , 1))) - tree.insert(Container(Pair(50 , 1))) - tree.insert(Container(Pair(10 , 1))) - tree.insert(Container(Pair(22 , 1))) - tree.insert(Container(Pair(35 , 1))) - tree.insert(Container(Pair(70 , 1))) - tree.insert(Container(Pair(4 , 1))) - tree.insert(Container(Pair(12 , 1))) - tree.insert(Container(Pair(18 , 1))) - tree.insert(Container(Pair(24 , 1))) - tree.insert(Container(Pair(31 , 1))) - tree.insert(Container(Pair(44 , 1))) - tree.insert(Container(Pair(66 , 1))) - tree.insert(Container(Pair(90 , 1))) - val controller = Controller() - controller.saveTree(tree) - tree.insert(Container(Pair(100, 1))) - controller.saveTree(tree) - controller.initTree() - - //neo4jRep.exportRBtree() - - //neo4jRep.close() -} - -fun test() { - val cont = Controller() - cont.initTree() -} \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/binTree/BINVertex.kt b/lib/src/main/kotlin/treelib/binTree/BINVertex.kt index e660d8c..8939461 100644 --- a/lib/src/main/kotlin/treelib/binTree/BINVertex.kt +++ b/lib/src/main/kotlin/treelib/binTree/BINVertex.kt @@ -2,4 +2,4 @@ package treelib.binTree import treelib.abstractTree.Vertex -class BINVertex>(override val value: Pack): Vertex() \ No newline at end of file +open class BINVertex>(override val value: Pack): Vertex() \ No newline at end of file From 242481be85a1af14a2b61ac288073fb463b3e055 Mon Sep 17 00:00:00 2001 From: Artem Date: Sat, 15 Apr 2023 15:27:37 +0300 Subject: [PATCH 29/84] fix: Partially change exceptions --- .../kotlin/treelib/avlTree/AVLBalancer.kt | 25 ++++----- .../main/kotlin/treelib/rbTree/RBBalancer.kt | 55 +++++++++---------- 2 files changed, 37 insertions(+), 43 deletions(-) diff --git a/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt b/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt index 703ea69..5f80a87 100644 --- a/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt +++ b/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt @@ -1,11 +1,8 @@ package treelib.avlTree import treelib.abstractTree.balanced.BalancerNoParent -import treelib.singleObjects.exceptions.IllegalBaseNodeException -import treelib.singleObjects.exceptions.IllegalNodeStateException -class AVLBalancer>(private var root: AVLNode?) : - BalancerNoParent, AVLStateContainer>() { +class AVLBalancer>(private var root: AVLNode?): BalancerNoParent, AVLStateContainer>() { private fun updateBalance(node: AVLNode?): Int { return (getHeight(node?.left) - getHeight(node?.right)).toInt() } @@ -16,19 +13,18 @@ class AVLBalancer>(private var root: AVLNode?) : private fun updateHeight(currentNode: AVLNode?) { if (currentNode != null) - currentNode.height = maxOf(getHeight(currentNode.left), getHeight(currentNode.right)) + 1u + currentNode.height = maxOf(getHeight(currentNode.left), getHeight(currentNode.right))+1u } - override fun balance(state: AVLStateContainer): AVLNode { - val node = state.contentNode - root = state.root - return balance(root, node?.value ?: throw IllegalBaseNodeException()) + override fun balance(stateContainer: AVLStateContainer): AVLNode { + val node = stateContainer.contentNode ?: throw IllegalStateException("") // IllegalBaseNodeException("A non-existent node (null) was passed to the method") + root = stateContainer.root + return balance(root, node.value) } - - // В баланс передаем родителя ноды, которую будем удалять + /*** In the method we pass the parent of the removed/inserted node ***/ private fun balance(currentNode: AVLNode?, value: Pack): AVLNode { if (currentNode == null) { - throw IllegalBaseNodeException() + throw NullPointerException() } when { currentNode.value < value -> currentNode.right = balance(currentNode.right, value) @@ -38,7 +34,7 @@ class AVLBalancer>(private var root: AVLNode?) : val balance = updateBalance(currentNode) if (balance == -2) { if (updateBalance(currentNode.right) == 1) { - currentNode.right = currentNode.right?.let { rightRotate(it) } ?: throw IllegalNodeStateException() + currentNode.right = currentNode.right?.let { rightRotate(it) } ?: throw NullPointerException() // IllegalNodeStateException() updateHeight(currentNode.right?.right) } val balancedNode = leftRotate(currentNode) @@ -48,7 +44,7 @@ class AVLBalancer>(private var root: AVLNode?) : } if (balance == 2) { if (updateBalance(currentNode.left) == -1) { - currentNode.left = currentNode.left?.let { leftRotate(it) } ?: throw IllegalNodeStateException() + currentNode.left = currentNode.left?.let { leftRotate(it) } ?: throw NullPointerException() // IllegalNodeStateException("There is no node required by the condition of the algorithm") updateHeight(currentNode.left?.left) } val balanceNode = rightRotate(currentNode) @@ -58,4 +54,5 @@ class AVLBalancer>(private var root: AVLNode?) : } return currentNode } + } diff --git a/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt b/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt index fe73c5b..67e5427 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt @@ -2,9 +2,6 @@ package treelib.rbTree import treelib.abstractTree.balanced.BalancerParent import treelib.singleObjects.Markers -import treelib.singleObjects.exceptions.IllegalBaseNodeException -import treelib.singleObjects.exceptions.IllegalNodeStateException -import treelib.singleObjects.exceptions.ImpossibleCaseException class RBBalancer>(private var root: RBNode?): BalancerParent, RBStateContainer>() { @@ -30,7 +27,7 @@ class RBBalancer>(private var root: RBNode?): Balan private fun getRoot(node: RBNode): RBNode { var currentNode = node while (currentNode.parent != null) - currentNode = currentNode.parent ?: throw IllegalNodeStateException() + currentNode = currentNode.parent ?: throw NullPointerException() root = currentNode root?.color = Markers.BLACK return currentNode @@ -38,12 +35,13 @@ class RBBalancer>(private var root: RBNode?): Balan private fun nodeIsLeaf(node: RBNode?): Boolean { if (node == null) - throw IllegalBaseNodeException() + throw NullPointerException() return node.right == null && node.left == null } - override fun balance(state: RBStateContainer): RBNode { - val node = state.contentNode ?: throw IllegalBaseNodeException() + override fun balance(stateContainer: RBStateContainer): RBNode { + val node = stateContainer.contentNode ?: + throw IllegalStateException() //IllegalBaseNodeException("A non-existent node (null) was passed to the method") val uncle = getUncle(node) when { /** node insertion case **/ @@ -58,14 +56,14 @@ class RBBalancer>(private var root: RBNode?): Balan return getRoot(currentNode) } - var parent = currentNode.parent ?: throw IllegalNodeStateException() + var parent = currentNode.parent ?: throw IllegalStateException() // в данном случае родитель не может быть null when (parent) { parent.parent?.left -> { if (currentNode == parent.right) { leftRotate(parent) currentNode = parent } - parent = currentNode.parent?.parent ?: throw IllegalNodeStateException() + parent = currentNode.parent?.parent ?: throw IllegalStateException() // IllegalNodeStateException() currentNode = rightRotate(parent) currentNode.color = Markers.BLACK currentNode.right?.color = Markers.RED @@ -76,17 +74,17 @@ class RBBalancer>(private var root: RBNode?): Balan rightRotate(parent) currentNode = parent } - parent = currentNode.parent?.parent ?: throw IllegalNodeStateException() + parent = currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() currentNode = leftRotate(parent) currentNode.color = Markers.BLACK currentNode.right?.color = Markers.RED currentNode.left?.color = Markers.RED } - else -> throw IllegalNodeStateException() + else -> throw IllegalStateException() // невозможное условие выполнения } if (currentNode.parent == null) root = currentNode - return root ?: throw IllegalNodeStateException() + return root ?: throw NullPointerException() } /** node removal cases **/ node.color == Markers.RED && (node.right != null || node.left != null) -> @@ -116,12 +114,11 @@ class RBBalancer>(private var root: RBNode?): Balan firstCase(node, null) } - - else -> throw IllegalNodeStateException() + else -> throw IllegalStateException() } } } - throw ImpossibleCaseException() + throw IllegalStateException() } private fun afterInsert(node: RBNode): RBNode { @@ -130,7 +127,7 @@ class RBBalancer>(private var root: RBNode?): Balan val uncle = getUncle(currentNode) if (uncle?.color == Markers.RED) { currentNode.parent?.color = Markers.BLACK - currentNode = currentNode.parent?.parent ?: throw IllegalNodeStateException() + currentNode = currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() currentNode.color = Markers.RED uncle.color = Markers.BLACK } @@ -145,7 +142,7 @@ class RBBalancer>(private var root: RBNode?): Balan /** black node removal case **/ private fun firstCase(parent: RBNode?, node: RBNode?): RBNode { return when { - parent == null && node == null -> throw IllegalBaseNodeException() + parent == null && node == null -> throw NullPointerException() parent != null -> { when (parent.color) { Markers.RED -> secondCase(parent, node) @@ -154,13 +151,13 @@ class RBBalancer>(private var root: RBNode?): Balan getRoot(parent) } - else -> getRoot(node ?: throw IllegalBaseNodeException()) + else -> getRoot(node ?: throw NullPointerException() /* IllegalNodeStateException() */) } } /** parent is red **/ private fun secondCase(parent: RBNode, node: RBNode?) { - var brother = getBrother(parent, node) ?: throw IllegalBaseNodeException() + var brother = getBrother(parent, node) ?: throw NullPointerException() // IllegalNodeStateException() if (brother.color == Markers.RED) throw NullPointerException() @@ -187,7 +184,7 @@ class RBBalancer>(private var root: RBNode?): Balan brother.color = Markers.RED } else { - throw NullPointerException() + throw IllegalStateException() } } parent.right -> @@ -206,17 +203,17 @@ class RBBalancer>(private var root: RBNode?): Balan brother.right?.color = Markers.BLACK } else { - throw NullPointerException() + throw IllegalStateException() } } - else -> throw NullPointerException() + else -> throw IllegalStateException() } } /** parent is black **/ private fun thirdCase(parent: RBNode, node: RBNode?) { - val brother = getBrother(parent, node) ?: throw NullPointerException() + val brother = getBrother(parent, node) ?: throw NullPointerException() // IllegalNodeStateException() when (brother.color) { Markers.RED -> thirdCaseSubFirst(brother, parent) Markers.BLACK -> thirdCaseSubSecond(brother, parent) @@ -228,7 +225,7 @@ class RBBalancer>(private var root: RBNode?): Balan when (brother) { brother.parent?.left -> { - var rightBrotherSon = brother.right ?: throw NullPointerException() + var rightBrotherSon = brother.right ?: throw NullPointerException() // IllegalNodeStateException() if (rightBrotherSon.right?.color != Markers.RED && rightBrotherSon.left?.color != Markers.RED) { rightBrotherSon.color = Markers.RED @@ -244,7 +241,7 @@ class RBBalancer>(private var root: RBNode?): Balan rightBrotherSon.color = Markers.RED leftRotate(rightBrotherSon) - rightBrotherSon = rightBrotherSon.parent ?: throw NullPointerException() + rightBrotherSon = rightBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() rightBrotherSon.color = Markers.BLACK } @@ -260,14 +257,14 @@ class RBBalancer>(private var root: RBNode?): Balan if (leftBrotherSon.right?.color != Markers.RED && leftBrotherSon.left?.color != Markers.RED) { leftBrotherSon.color = Markers.RED brother.color = Markers.BLACK - leftRotate(brother.parent ?: throw NullPointerException()) + leftRotate(brother.parent ?: throw NullPointerException()) // IllegalNodeStateException() return } if (leftBrotherSon.left?.color == Markers.RED) { rightRotate(leftBrotherSon) leftBrotherSon.color = Markers.RED - leftBrotherSon = leftBrotherSon.parent ?: throw NullPointerException() + leftBrotherSon = leftBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() leftBrotherSon.color = Markers.BLACK } @@ -277,7 +274,7 @@ class RBBalancer>(private var root: RBNode?): Balan leftRotate(parent) } } - else -> throw NullPointerException() + else -> throw IllegalStateException() } } @@ -315,7 +312,7 @@ class RBBalancer>(private var root: RBNode?): Balan } } - else -> throw NullPointerException() + else -> throw IllegalStateException() } } From 19980973101302b5b78d7ea9c0e90bfd4b5cf6c3 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 17 Apr 2023 14:37:18 +0300 Subject: [PATCH 30/84] feat: Implement neo4j database sketch --- lib/build.gradle.kts | 12 +- lib/src/main/kotlin/CONTAINER.conf | 3 + lib/src/main/kotlin/DataBase.kt | 172 ++++++++++++++++++++++++ lib/src/main/kotlin/testNeo4j.sh | 15 +++ lib/src/main/kotlin/treelib/DBNodeRB.kt | 14 ++ settings.gradle.kts | 2 +- 6 files changed, 213 insertions(+), 5 deletions(-) create mode 100644 lib/src/main/kotlin/CONTAINER.conf create mode 100644 lib/src/main/kotlin/DataBase.kt create mode 100644 lib/src/main/kotlin/testNeo4j.sh create mode 100644 lib/src/main/kotlin/treelib/DBNodeRB.kt diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 99f9538..0f9f88e 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -19,15 +19,19 @@ repositories { } dependencies { - testImplementation("org.junit.jupiter:junit-jupiter-params:5.9.2") + api("org.apache.commons:commons-math3:3.6.1") + implementation("com.google.guava:guava:31.1-jre") + + val neo4jCore = "4.0.5" + implementation("org.neo4j", "neo4j-ogm-core", neo4jCore) + implementation("org.neo4j", "neo4j-ogm-bolt-driver", neo4jCore) + testImplementation("io.mockk:mockk:1.13.4") testImplementation("org.jetbrains.kotlin:kotlin-test-junit5:1.8.10") testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.2") - api("org.apache.commons:commons-math3:3.6.1") - implementation("com.google.guava:guava:31.1-jre") + implementation(kotlin("stdlib-jdk8")) } - tasks.test { finalizedBy(tasks.jacocoTestReport) useJUnitPlatform() diff --git a/lib/src/main/kotlin/CONTAINER.conf b/lib/src/main/kotlin/CONTAINER.conf new file mode 100644 index 0000000..9b9fb0a --- /dev/null +++ b/lib/src/main/kotlin/CONTAINER.conf @@ -0,0 +1,3 @@ +CONTAINER_NAME=neo4j-db +PASSWORD="test-neo4j" +VOLUMEDIR="/volume" \ No newline at end of file diff --git a/lib/src/main/kotlin/DataBase.kt b/lib/src/main/kotlin/DataBase.kt new file mode 100644 index 0000000..ddc72a3 --- /dev/null +++ b/lib/src/main/kotlin/DataBase.kt @@ -0,0 +1,172 @@ + +import org.neo4j.driver.AuthTokens +import org.neo4j.driver.Driver +import org.neo4j.driver.GraphDatabase +import org.neo4j.driver.exceptions.SessionExpiredException +import treelib.DBNodeRB +import treelib.singleObjects.Markers +import java.io.Closeable +import java.io.IOException +import java.util.* + +class Neo4jRepository: Closeable { + + private var driver: Driver? = null + + fun open(uri: String, username: String, password: String) { + try { + driver = GraphDatabase.driver(uri, AuthTokens.basic(username, password)) + } catch(ex: IllegalArgumentException) { + throw IOException() + } catch(ex: SessionExpiredException) { + throw IOException() + } + + } + + // я наверное смогу получить рут, используя фильтр что-то вроде: на данный узел не указывает ни один другой узел с отношением [left_child] / [right_child] + + fun , V> saveChanges(preOrder: Array>, inOrder: Array>) { + + /*** сюда по ощущениям лучше всего добавлять именно то поддерево исходного дерева, которое было изменено ***/ + val session = driver?.session() ?: throw IOException() + + var inOrderIndex = 0 + var preOrderIndex = 0 + val set = HashSet>() + val stack = LinkedList>() + + while (preOrderIndex in preOrder.indices) { + do { + val currentNode = preOrder[preOrderIndex] + if (preOrderIndex == 0) { + session.executeWrite { tx -> + tx.run( + "MERGE(:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY})", + mutableMapOf( + "nodeValue" to currentNode.value, + "nodeKey" to currentNode.key, + "nodeColor" to currentNode.color.toString(), + "nodeX" to currentNode.x, + "nodeY" to currentNode.y + ) + ) + } + } + if (!stack.isEmpty()) { + if ( set.contains( stack.peek() ) ) { + set.remove(stack.peek()) + val parentNode = stack.pop() + session.executeWrite {tx -> + tx.run("MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + + "MERGE (parent)-[:RIGHT_SON]->(son)", + mutableMapOf( + "parentNodeValue" to parentNode.value, + "parentNodeKey" to parentNode.key, + "parentNodeColor" to parentNode.color.toString(), + "parentNodeX" to parentNode.x, + "parentNodeY" to parentNode.y, + "nodeValue" to currentNode.value, + "nodeKey" to currentNode.key, + "nodeColor" to currentNode.color.toString(), + "nodeX" to currentNode.x, + "nodeY" to currentNode.y + ) + ) + } + } + else { + val parentNode = stack.peek() + session.executeWrite {tx -> + tx.run("MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + + "MERGE (parent)-[:LEFT_SON]->(son)", + mutableMapOf( + "parentNodeValue" to parentNode.value, + "parentNodeKey" to parentNode.key, + "parentNodeColor" to parentNode.color.toString(), + "parentNodeX" to parentNode.x, + "parentNodeY" to parentNode.y, + "nodeValue" to currentNode.value, + "nodeKey" to currentNode.key, + "nodeColor" to currentNode.color.toString(), + "nodeX" to currentNode.x, + "nodeY" to currentNode.y + ) + ) + } + } + } + stack.push(currentNode) + } while (preOrder[preOrderIndex++] != inOrder[inOrderIndex] && preOrderIndex < preOrder.size) + + var currentNode: DBNodeRB? = null + + while(!stack.isEmpty() && inOrderIndex < inOrder.size && stack.peek().key == inOrder[inOrderIndex].key) { + currentNode = stack.pop() + ++inOrderIndex + } + + if (currentNode != null) { + set.add(currentNode) + stack.push(currentNode) + } + + } + + session.close() + } + + // Это скорее всего будем запускать при открытии приложения, нужно будет сразу восстановить дерево + + fun exportRBtree() { + + val session = driver?.session() ?: throw IOException() + var preOrder: List>> = listOf() + var inOrder: List>> = listOf() + + session.executeRead {tx -> + preOrder = tx.run("MATCH (node: Node) " + + "RETURN node.value, node.key, node.color, node.x, node.y ").list() + .map{ DBNodeRB( + value = it.values().get(0).toString(), + key = it.values().get(1).toString(), + color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, + x = it.values().get(3).toString().toDouble(), + y = it.values().get(4).toString().toDouble()) + } + + inOrder = tx.run("MATCH (node: Node) " + + "RETURN node.value, node.key, node.color, node.x, node.y " + + "ORDER BY node.key").list() + .map{ DBNodeRB( + value = it.values().get(0).toString(), + key = it.values().get(1).toString(), + color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, + x = it.values().get(3).toString().toDouble(), + y = it.values().get(4).toString().toDouble()) + } + } + + session.close() + + } + + override fun close() { + driver?.close() + } +} + +// neo4j-admin, backup, restore +/* +у меня есть вершины и ребра между ними, надо уметь сохранять дерево в базе, но как? +вопрос: когда заносить изменения в бд и как это реализовывать? +надо еще подумать над оптимизацией, те чтобы не пересобирать дерево в бд каждый раз, когда мы добавили за сессию всего один узел + +root = tx.run("MATCH (parent: Node)-->(son: Node) " + + "WHERE NOT ()-->(parent) " + + "RETURN parent.value, parent.key, parent.color, parent.x, parent.y").list().map {it.values()}.get(0) + */ diff --git a/lib/src/main/kotlin/testNeo4j.sh b/lib/src/main/kotlin/testNeo4j.sh new file mode 100644 index 0000000..97ad8db --- /dev/null +++ b/lib/src/main/kotlin/testNeo4j.sh @@ -0,0 +1,15 @@ + +BASEDIR=$(realpath "$(dirname "$0")") + +. "${BASEDIR}/CONTAINER.conf" + +docker run \ + --rm \ + --name "CONTAINER_NAME" \ + --volume=$HOME/neo4j/data:/data \ + --volume=$HOME/neo4j/logs:/logs \ + --publish=7474:7474 --publish=7687:7687 \ + --env NEO4J_AUTH=neo4j/"$PASSWORD" \ + neo4j:latest \ + +#docker stop neo4j:latest diff --git a/lib/src/main/kotlin/treelib/DBNodeRB.kt b/lib/src/main/kotlin/treelib/DBNodeRB.kt new file mode 100644 index 0000000..d048930 --- /dev/null +++ b/lib/src/main/kotlin/treelib/DBNodeRB.kt @@ -0,0 +1,14 @@ +package treelib + +import treelib.singleObjects.Markers + + +class DBNodeRB, V>(val value: V, + val key: K, + val color: Markers = Markers.RED, + val x: Double = 0.0, + val y: Double = 0.0) { + + + +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 21643d4..26b0762 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -7,5 +7,5 @@ * in the user manual at https://docs.gradle.org/8.0/userguide/multi_project_builds.html */ -rootProject.name = "TreeLib" +rootProject.name = "treelib" include("lib") From ad94694da73585be3e768e78ddeb68516353cddd Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 17 Apr 2023 19:32:32 +0300 Subject: [PATCH 31/84] feat: Implement initialize tree from DB --- lib/src/main/kotlin/Controller.kt | 50 +++++++++++++++++ lib/src/main/kotlin/DataBase.kt | 55 +++++++++---------- lib/src/main/kotlin/treelib/DBNodeRB.kt | 9 +-- lib/src/main/kotlin/treelib/Main.kt | 39 +++++++++++++ .../main/kotlin/treelib/abstractTree/Tree.kt | 12 ++-- 5 files changed, 124 insertions(+), 41 deletions(-) create mode 100644 lib/src/main/kotlin/Controller.kt create mode 100644 lib/src/main/kotlin/treelib/Main.kt diff --git a/lib/src/main/kotlin/Controller.kt b/lib/src/main/kotlin/Controller.kt new file mode 100644 index 0000000..cc4e699 --- /dev/null +++ b/lib/src/main/kotlin/Controller.kt @@ -0,0 +1,50 @@ +import treelib.DBNodeRB +import treelib.rbTree.RBStruct +import treelib.rbTree.RBTree +import treelib.singleObjects.Container + +class Controller { + + fun initTree() { + val neo4jDB = Neo4jRepository() + neo4jDB.open("bolt://localhost:7687", "neo4j", "test-neo4j") + /*** orders.first = preOrder, orders.second = inOrder ***/ + val orders: Pair>>>, List>>>> = + neo4jDB.exportRBtree() + + val RBtree = RBStruct>>() + RBtree.restoreTreeFromDatabase(orders.first, orders.second) + } + + fun saveTree() { + val tree = RBTree() + tree.putItem(Pair(25, 1)) + tree.putItem(Pair(15, 1)) + tree.putItem(Pair(50, 1)) + tree.putItem(Pair(10, 1)) + tree.putItem(Pair(22, 1)) + tree.putItem(Pair(35, 1)) + tree.putItem(Pair(70, 1)) + tree.putItem(Pair(4, 1)) + tree.putItem(Pair(12, 1)) + tree.putItem(Pair(18, 1)) + tree.putItem(Pair(24, 1)) + tree.putItem(Pair(31, 1)) + tree.putItem(Pair(44, 1)) + tree.putItem(Pair(66, 1)) + tree.putItem(Pair(90, 1)) + + val neo4jDB = Neo4jRepository() + neo4jDB.open("bolt://localhost:7687", "neo4j", "test-neo4j") + + val preOrder = tree.preOrder().map { DBNodeRB(it.value, it.color) } + val inOrder = tree.inOrder().map { DBNodeRB(it.value, it.color) } + + neo4jDB.saveChanges(preOrder.toTypedArray(), inOrder.toTypedArray()) + + neo4jDB.close() + + + } + +} \ No newline at end of file diff --git a/lib/src/main/kotlin/DataBase.kt b/lib/src/main/kotlin/DataBase.kt index ddc72a3..3e94aac 100644 --- a/lib/src/main/kotlin/DataBase.kt +++ b/lib/src/main/kotlin/DataBase.kt @@ -4,6 +4,7 @@ import org.neo4j.driver.Driver import org.neo4j.driver.GraphDatabase import org.neo4j.driver.exceptions.SessionExpiredException import treelib.DBNodeRB +import treelib.singleObjects.Container import treelib.singleObjects.Markers import java.io.Closeable import java.io.IOException @@ -21,31 +22,29 @@ class Neo4jRepository: Closeable { } catch(ex: SessionExpiredException) { throw IOException() } - } - // я наверное смогу получить рут, используя фильтр что-то вроде: на данный узел не указывает ни один другой узел с отношением [left_child] / [right_child] - - fun , V> saveChanges(preOrder: Array>, inOrder: Array>) { + fun > saveChanges(preOrder: Array>, inOrder: Array>) { /*** сюда по ощущениям лучше всего добавлять именно то поддерево исходного дерева, которое было изменено ***/ val session = driver?.session() ?: throw IOException() var inOrderIndex = 0 var preOrderIndex = 0 - val set = HashSet>() - val stack = LinkedList>() + val set = HashSet>() + val stack = LinkedList>() while (preOrderIndex in preOrder.indices) { do { val currentNode = preOrder[preOrderIndex] + currentNode.value as Container<*, *> if (preOrderIndex == 0) { session.executeWrite { tx -> tx.run( "MERGE(:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY})", mutableMapOf( - "nodeValue" to currentNode.value, - "nodeKey" to currentNode.key, + "nodeValue" to currentNode.value.pair.second, + "nodeKey" to currentNode.value.pair.first, "nodeColor" to currentNode.color.toString(), "nodeX" to currentNode.x, "nodeY" to currentNode.y @@ -57,19 +56,20 @@ class Neo4jRepository: Closeable { if ( set.contains( stack.peek() ) ) { set.remove(stack.peek()) val parentNode = stack.pop() + parentNode.value as Container<*, *> session.executeWrite {tx -> tx.run("MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + "MERGE (parent)-[:RIGHT_SON]->(son)", mutableMapOf( - "parentNodeValue" to parentNode.value, - "parentNodeKey" to parentNode.key, + "parentNodeValue" to parentNode.value.pair.second, + "parentNodeKey" to parentNode.value.pair.first, "parentNodeColor" to parentNode.color.toString(), "parentNodeX" to parentNode.x, "parentNodeY" to parentNode.y, - "nodeValue" to currentNode.value, - "nodeKey" to currentNode.key, + "nodeValue" to currentNode.value.pair.second, + "nodeKey" to currentNode.value.pair.first, "nodeColor" to currentNode.color.toString(), "nodeX" to currentNode.x, "nodeY" to currentNode.y @@ -79,19 +79,20 @@ class Neo4jRepository: Closeable { } else { val parentNode = stack.peek() + parentNode.value as Container<*, *> session.executeWrite {tx -> tx.run("MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + "MERGE (parent)-[:LEFT_SON]->(son)", mutableMapOf( - "parentNodeValue" to parentNode.value, - "parentNodeKey" to parentNode.key, + "parentNodeValue" to parentNode.value.pair.second, + "parentNodeKey" to parentNode.value.pair.first, "parentNodeColor" to parentNode.color.toString(), "parentNodeX" to parentNode.x, "parentNodeY" to parentNode.y, - "nodeValue" to currentNode.value, - "nodeKey" to currentNode.key, + "nodeValue" to currentNode.value.pair.second, + "nodeKey" to currentNode.value.pair.first, "nodeColor" to currentNode.color.toString(), "nodeX" to currentNode.x, "nodeY" to currentNode.y @@ -103,9 +104,9 @@ class Neo4jRepository: Closeable { stack.push(currentNode) } while (preOrder[preOrderIndex++] != inOrder[inOrderIndex] && preOrderIndex < preOrder.size) - var currentNode: DBNodeRB? = null + var currentNode: DBNodeRB? = null - while(!stack.isEmpty() && inOrderIndex < inOrder.size && stack.peek().key == inOrder[inOrderIndex].key) { + while(!stack.isEmpty() && inOrderIndex < inOrder.size && stack.peek().value == inOrder[inOrderIndex].value) { currentNode = stack.pop() ++inOrderIndex } @@ -120,20 +121,17 @@ class Neo4jRepository: Closeable { session.close() } - // Это скорее всего будем запускать при открытии приложения, нужно будет сразу восстановить дерево - - fun exportRBtree() { + fun exportRBtree(): Pair>>>, List>>>>{ val session = driver?.session() ?: throw IOException() - var preOrder: List>> = listOf() - var inOrder: List>> = listOf() + var preOrder: List>>> = listOf() + var inOrder: List>>> = listOf() session.executeRead {tx -> preOrder = tx.run("MATCH (node: Node) " + "RETURN node.value, node.key, node.color, node.x, node.y ").list() .map{ DBNodeRB( - value = it.values().get(0).toString(), - key = it.values().get(1).toString(), + value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, x = it.values().get(3).toString().toDouble(), y = it.values().get(4).toString().toDouble()) @@ -143,16 +141,17 @@ class Neo4jRepository: Closeable { "RETURN node.value, node.key, node.color, node.x, node.y " + "ORDER BY node.key").list() .map{ DBNodeRB( - value = it.values().get(0).toString(), - key = it.values().get(1).toString(), + value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, x = it.values().get(3).toString().toDouble(), y = it.values().get(4).toString().toDouble()) } } - + session.close() + return Pair(preOrder, inOrder) + } override fun close() { diff --git a/lib/src/main/kotlin/treelib/DBNodeRB.kt b/lib/src/main/kotlin/treelib/DBNodeRB.kt index d048930..b28228f 100644 --- a/lib/src/main/kotlin/treelib/DBNodeRB.kt +++ b/lib/src/main/kotlin/treelib/DBNodeRB.kt @@ -3,12 +3,7 @@ package treelib import treelib.singleObjects.Markers -class DBNodeRB, V>(val value: V, - val key: K, +class DBNodeRB>(val value: Pack, val color: Markers = Markers.RED, val x: Double = 0.0, - val y: Double = 0.0) { - - - -} + val y: Double = 0.0) diff --git a/lib/src/main/kotlin/treelib/Main.kt b/lib/src/main/kotlin/treelib/Main.kt new file mode 100644 index 0000000..0aeb3e0 --- /dev/null +++ b/lib/src/main/kotlin/treelib/Main.kt @@ -0,0 +1,39 @@ +package treelib + +import Controller + + +fun main() { + // 25, 15, 10, 4, 12, 22, 18, 24, 50, 35, 31, 44, 70, 66, 90 + // 4, 10, 12, 15, 18, 22, 24, 25, 31, 35, 44, 50, 66, 70, 90 + + /* + + val neo4jRep = Neo4jRepository() + val a1 = DBNodeRB(Container(Pair(1, 25))) + val a2 = DBNodeRB(Container(Pair(1, 15))) + val a3 = DBNodeRB(Container(Pair(1, 10))) + val a4 = DBNodeRB(Container(Pair(1, 4))) + val a5 = DBNodeRB(Container(Pair(1, 12))) + val a6 = DBNodeRB(Container(Pair(1, 22))) + val a7 = DBNodeRB(Container(Pair(1, 18))) + val a8 = DBNodeRB(Container(Pair(1, 24))) + val a9 = DBNodeRB(Container(Pair(1, 50))) + val a10 = DBNodeRB(Container(Pair(1, 35))) + val a11 = DBNodeRB(Container(Pair(1, 31))) + val a12 = DBNodeRB(Container(Pair(1, 44))) + val a13 = DBNodeRB(Container(Pair(1, 70))) + val a14 = DBNodeRB(Container(Pair(1, 66))) + val a15 = DBNodeRB(Container(Pair(1, 90))) + val preArr = arrayOf(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) + val inArr = arrayOf(a4, a3, a5, a2, a7, a6, a8, a1, a11, a10, a12, a9, a14, a13, a15) + neo4jRep.open("bolt://localhost:7687", "neo4j", "test-neo4j") + neo4jRep.saveChanges(preArr, inArr) + */ + val controller = Controller() + controller.saveTree() + + //neo4jRep.exportRBtree() + + //neo4jRep.close() +} \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/abstractTree/Tree.kt b/lib/src/main/kotlin/treelib/abstractTree/Tree.kt index b64cca1..1607caa 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/Tree.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/Tree.kt @@ -33,15 +33,15 @@ abstract class Tree< treeStruct.delete(wrapForFind(key)) } - private fun createPoorList(info: List>): List> { - val returnInfo = mutableListOf>() - for (element in info) returnInfo.add(element.pair) + private fun createPoorList(info: List): List { + val returnInfo = mutableListOf() + for (element in info) returnInfo.add(element) return returnInfo } - fun inOrder(): List> = createPoorList(treeStruct.inOrder()) + fun inOrder(): List = createPoorList(treeStruct.inOrder()) - fun preOrder(): List> = createPoorList(treeStruct.preOrder()) + fun preOrder(): List = createPoorList(treeStruct.preOrder()) - fun postOrder(): List> = createPoorList(treeStruct.postOrder()) + fun postOrder(): List = createPoorList(treeStruct.postOrder()) } From 42fca1200f72bd355d9b75558209b6a5e26f895e Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 17 Apr 2023 20:21:27 +0300 Subject: [PATCH 32/84] fix: Fix adding to database (neo4j) --- lib/src/main/kotlin/DataBase.kt | 82 ++++++++++-------- lib/src/main/kotlin/treelib/DBNodeRB.kt | 10 ++- .../kotlin/treelib/avlTree/AVLBalancer.kt | 15 ++-- .../main/kotlin/treelib/rbTree/RBBalancer.kt | 85 ++++++++++--------- .../main/kotlin/treelib/rbTree/RBStruct.kt | 63 ++++++++++++-- 5 files changed, 161 insertions(+), 94 deletions(-) diff --git a/lib/src/main/kotlin/DataBase.kt b/lib/src/main/kotlin/DataBase.kt index 3e94aac..e7ca4c6 100644 --- a/lib/src/main/kotlin/DataBase.kt +++ b/lib/src/main/kotlin/DataBase.kt @@ -1,4 +1,3 @@ - import org.neo4j.driver.AuthTokens import org.neo4j.driver.Driver import org.neo4j.driver.GraphDatabase @@ -10,21 +9,21 @@ import java.io.Closeable import java.io.IOException import java.util.* -class Neo4jRepository: Closeable { +class Neo4jRepository : Closeable { private var driver: Driver? = null fun open(uri: String, username: String, password: String) { try { driver = GraphDatabase.driver(uri, AuthTokens.basic(username, password)) - } catch(ex: IllegalArgumentException) { - throw IOException() - } catch(ex: SessionExpiredException) { + } catch (ex: IllegalArgumentException) { + throw IOException() + } catch (ex: SessionExpiredException) { throw IOException() } } - fun > saveChanges(preOrder: Array>, inOrder: Array>) { + fun > saveChanges(preOrder: Array>, inOrder: Array>) { /*** сюда по ощущениям лучше всего добавлять именно то поддерево исходного дерева, которое было изменено ***/ val session = driver?.session() ?: throw IOException() @@ -53,15 +52,16 @@ class Neo4jRepository: Closeable { } } if (!stack.isEmpty()) { - if ( set.contains( stack.peek() ) ) { + if (set.contains(stack.peek())) { set.remove(stack.peek()) val parentNode = stack.pop() parentNode.value as Container<*, *> - session.executeWrite {tx -> - tx.run("MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + - "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + - "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + - "MERGE (parent)-[:RIGHT_SON]->(son)", + session.executeWrite { tx -> + tx.run( + "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + + "MERGE (parent)-[:RIGHT_SON]->(son)", mutableMapOf( "parentNodeValue" to parentNode.value.pair.second, "parentNodeKey" to parentNode.value.pair.first, @@ -76,15 +76,15 @@ class Neo4jRepository: Closeable { ) ) } - } - else { + } else { val parentNode = stack.peek() parentNode.value as Container<*, *> - session.executeWrite {tx -> - tx.run("MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + - "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + - "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + - "MERGE (parent)-[:LEFT_SON]->(son)", + session.executeWrite { tx -> + tx.run( + "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + + "MERGE (parent)-[:LEFT_SON]->(son)", mutableMapOf( "parentNodeValue" to parentNode.value.pair.second, "parentNodeKey" to parentNode.value.pair.first, @@ -106,7 +106,7 @@ class Neo4jRepository: Closeable { var currentNode: DBNodeRB? = null - while(!stack.isEmpty() && inOrderIndex < inOrder.size && stack.peek().value == inOrder[inOrderIndex].value) { + while (!stack.isEmpty() && inOrderIndex < inOrder.size && stack.peek().value == inOrder[inOrderIndex].value) { currentNode = stack.pop() ++inOrderIndex } @@ -121,30 +121,38 @@ class Neo4jRepository: Closeable { session.close() } - fun exportRBtree(): Pair>>>, List>>>>{ + fun exportRBtree(): Pair>>>, List>>>> { val session = driver?.session() ?: throw IOException() var preOrder: List>>> = listOf() var inOrder: List>>> = listOf() - session.executeRead {tx -> - preOrder = tx.run("MATCH (node: Node) " + - "RETURN node.value, node.key, node.color, node.x, node.y ").list() - .map{ DBNodeRB( - value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), - color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, - x = it.values().get(3).toString().toDouble(), - y = it.values().get(4).toString().toDouble()) + session.executeRead { tx -> + preOrder = tx.run( + "MATCH (node: Node) " + + "RETURN node.value, node.key, node.color, node.x, node.y " + ).list() + .map { + DBNodeRB( + value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), + color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, + x = it.values().get(3).toString().toDouble(), + y = it.values().get(4).toString().toDouble() + ) } - inOrder = tx.run("MATCH (node: Node) " + - "RETURN node.value, node.key, node.color, node.x, node.y " + - "ORDER BY node.key").list() - .map{ DBNodeRB( - value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), - color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, - x = it.values().get(3).toString().toDouble(), - y = it.values().get(4).toString().toDouble()) + inOrder = tx.run( + "MATCH (node: Node) " + + "RETURN node.value, node.key, node.color, node.x, node.y " + + "ORDER BY node.key" + ).list() + .map { + DBNodeRB( + value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), + color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, + x = it.values().get(3).toString().toDouble(), + y = it.values().get(4).toString().toDouble() + ) } } diff --git a/lib/src/main/kotlin/treelib/DBNodeRB.kt b/lib/src/main/kotlin/treelib/DBNodeRB.kt index b28228f..cf067e1 100644 --- a/lib/src/main/kotlin/treelib/DBNodeRB.kt +++ b/lib/src/main/kotlin/treelib/DBNodeRB.kt @@ -3,7 +3,9 @@ package treelib import treelib.singleObjects.Markers -class DBNodeRB>(val value: Pack, - val color: Markers = Markers.RED, - val x: Double = 0.0, - val y: Double = 0.0) +class DBNodeRB>( + val value: Pack, + val color: Markers = Markers.RED, + val x: Double = 0.0, + val y: Double = 0.0 +) diff --git a/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt b/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt index 5f80a87..1a3afb9 100644 --- a/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt +++ b/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt @@ -2,7 +2,8 @@ package treelib.avlTree import treelib.abstractTree.balanced.BalancerNoParent -class AVLBalancer>(private var root: AVLNode?): BalancerNoParent, AVLStateContainer>() { +class AVLBalancer>(private var root: AVLNode?) : + BalancerNoParent, AVLStateContainer>() { private fun updateBalance(node: AVLNode?): Int { return (getHeight(node?.left) - getHeight(node?.right)).toInt() } @@ -13,14 +14,16 @@ class AVLBalancer>(private var root: AVLNode?): Bal private fun updateHeight(currentNode: AVLNode?) { if (currentNode != null) - currentNode.height = maxOf(getHeight(currentNode.left), getHeight(currentNode.right))+1u + currentNode.height = maxOf(getHeight(currentNode.left), getHeight(currentNode.right)) + 1u } override fun balance(stateContainer: AVLStateContainer): AVLNode { - val node = stateContainer.contentNode ?: throw IllegalStateException("") // IllegalBaseNodeException("A non-existent node (null) was passed to the method") + val node = stateContainer.contentNode + ?: throw IllegalStateException("") // IllegalBaseNodeException("A non-existent node (null) was passed to the method") root = stateContainer.root return balance(root, node.value) } + /*** In the method we pass the parent of the removed/inserted node ***/ private fun balance(currentNode: AVLNode?, value: Pack): AVLNode { if (currentNode == null) { @@ -34,7 +37,8 @@ class AVLBalancer>(private var root: AVLNode?): Bal val balance = updateBalance(currentNode) if (balance == -2) { if (updateBalance(currentNode.right) == 1) { - currentNode.right = currentNode.right?.let { rightRotate(it) } ?: throw NullPointerException() // IllegalNodeStateException() + currentNode.right = currentNode.right?.let { rightRotate(it) } + ?: throw NullPointerException() // IllegalNodeStateException() updateHeight(currentNode.right?.right) } val balancedNode = leftRotate(currentNode) @@ -44,7 +48,8 @@ class AVLBalancer>(private var root: AVLNode?): Bal } if (balance == 2) { if (updateBalance(currentNode.left) == -1) { - currentNode.left = currentNode.left?.let { leftRotate(it) } ?: throw NullPointerException() // IllegalNodeStateException("There is no node required by the condition of the algorithm") + currentNode.left = currentNode.left?.let { leftRotate(it) } + ?: throw NullPointerException() // IllegalNodeStateException("There is no node required by the condition of the algorithm") updateHeight(currentNode.left?.left) } val balanceNode = rightRotate(currentNode) diff --git a/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt b/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt index 67e5427..211e007 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt @@ -3,7 +3,8 @@ package treelib.rbTree import treelib.abstractTree.balanced.BalancerParent import treelib.singleObjects.Markers -class RBBalancer>(private var root: RBNode?): BalancerParent, RBStateContainer>() { +class RBBalancer>(private var root: RBNode?) : + BalancerParent, RBStateContainer>() { init { root?.color = Markers.BLACK @@ -39,14 +40,13 @@ class RBBalancer>(private var root: RBNode?): Balan return node.right == null && node.left == null } - override fun balance(stateContainer: RBStateContainer): RBNode { - val node = stateContainer.contentNode ?: - throw IllegalStateException() //IllegalBaseNodeException("A non-existent node (null) was passed to the method") + override fun balance(stateContainer: RBStateContainer): RBNode { + val node = stateContainer.contentNode + ?: throw IllegalStateException() //IllegalBaseNodeException("A non-existent node (null) was passed to the method") val uncle = getUncle(node) when { /** node insertion case **/ - node.color == Markers.RED && node.right == null && node.left == null-> - { + node.color == Markers.RED && node.right == null && node.left == null -> { var currentNode = node if (currentNode.parent?.color == Markers.RED && uncle?.color == Markers.RED) { @@ -56,30 +56,35 @@ class RBBalancer>(private var root: RBNode?): Balan return getRoot(currentNode) } - var parent = currentNode.parent ?: throw IllegalStateException() // в данном случае родитель не может быть null + var parent = + currentNode.parent ?: throw IllegalStateException() // в данном случае родитель не может быть null when (parent) { parent.parent?.left -> { if (currentNode == parent.right) { leftRotate(parent) currentNode = parent } - parent = currentNode.parent?.parent ?: throw IllegalStateException() // IllegalNodeStateException() + parent = + currentNode.parent?.parent ?: throw IllegalStateException() // IllegalNodeStateException() currentNode = rightRotate(parent) currentNode.color = Markers.BLACK currentNode.right?.color = Markers.RED currentNode.left?.color = Markers.RED } + parent.parent?.right -> { if (currentNode == parent.left) { rightRotate(parent) currentNode = parent } - parent = currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() + parent = + currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() currentNode = leftRotate(parent) currentNode.color = Markers.BLACK currentNode.right?.color = Markers.RED currentNode.left?.color = Markers.RED } + else -> throw IllegalStateException() // невозможное условие выполнения } if (currentNode.parent == null) @@ -87,21 +92,21 @@ class RBBalancer>(private var root: RBNode?): Balan return root ?: throw NullPointerException() } /** node removal cases **/ - node.color == Markers.RED && (node.right != null || node.left != null) -> - { + node.color == Markers.RED && (node.right != null || node.left != null) -> { when { /** black leaf removal case **/ node.right?.color == Markers.BLACK -> { return firstCase(node, node.left) } + node.left?.color == Markers.BLACK -> { return firstCase(node, node.right) } } } - node.color == Markers.BLACK -> - { + + node.color == Markers.BLACK -> { return when { /** red leaf removal case **/ (node.left == null && node.right == null) || @@ -110,10 +115,11 @@ class RBBalancer>(private var root: RBNode?): Balan getRoot(node) } /** black leaf removal case **/ - node.left == null || node.right == null-> { + node.left == null || node.right == null -> { firstCase(node, null) } + else -> throw IllegalStateException() } } @@ -130,8 +136,7 @@ class RBBalancer>(private var root: RBNode?): Balan currentNode = currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() currentNode.color = Markers.RED uncle.color = Markers.BLACK - } - else if(uncle != null){ + } else if (uncle != null) { return currentNode } } @@ -168,45 +173,41 @@ class RBBalancer>(private var root: RBNode?): Balan } when (node) { - parent.left -> - { + parent.left -> { if (brother.right?.color == Markers.RED) { leftRotate(parent) brother.left?.color = Markers.RED brother.right?.color = Markers.RED brother.color = Markers.BLACK - } - else if (brother.left?.color == Markers.RED) { + } else if (brother.left?.color == Markers.RED) { brother = rightRotate(brother) leftRotate(parent) brother.left?.color = Markers.BLACK brother.left?.color = Markers.BLACK brother.color = Markers.RED - } - else { + } else { throw IllegalStateException() } } - parent.right -> - { + + parent.right -> { if (brother.left?.color == Markers.RED) { rightRotate(parent) brother.color = Markers.BLACK brother.left?.color = Markers.RED brother.right?.color = Markers.RED - } - else if (brother.right?.color == Markers.RED) { + } else if (brother.right?.color == Markers.RED) { brother = leftRotate(brother) rightRotate(parent) brother.color = Markers.RED brother.left?.color = Markers.BLACK brother.right?.color = Markers.BLACK - } - else { + } else { throw IllegalStateException() } } + else -> throw IllegalStateException() } } @@ -223,8 +224,7 @@ class RBBalancer>(private var root: RBNode?): Balan /** black parent and red brother **/ private fun thirdCaseSubFirst(brother: RBNode, parent: RBNode) { when (brother) { - brother.parent?.left -> - { + brother.parent?.left -> { var rightBrotherSon = brother.right ?: throw NullPointerException() // IllegalNodeStateException() if (rightBrotherSon.right?.color != Markers.RED && rightBrotherSon.left?.color != Markers.RED) { @@ -241,7 +241,8 @@ class RBBalancer>(private var root: RBNode?): Balan rightBrotherSon.color = Markers.RED leftRotate(rightBrotherSon) - rightBrotherSon = rightBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() + rightBrotherSon = + rightBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() rightBrotherSon.color = Markers.BLACK } @@ -251,8 +252,8 @@ class RBBalancer>(private var root: RBNode?): Balan rightRotate(parent) } } - brother.parent?.right -> - { + + brother.parent?.right -> { var leftBrotherSon = brother.left ?: throw NullPointerException() if (leftBrotherSon.right?.color != Markers.RED && leftBrotherSon.left?.color != Markers.RED) { leftBrotherSon.color = Markers.RED @@ -264,7 +265,8 @@ class RBBalancer>(private var root: RBNode?): Balan if (leftBrotherSon.left?.color == Markers.RED) { rightRotate(leftBrotherSon) leftBrotherSon.color = Markers.RED - leftBrotherSon = leftBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() + leftBrotherSon = + leftBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() leftBrotherSon.color = Markers.BLACK } @@ -274,6 +276,7 @@ class RBBalancer>(private var root: RBNode?): Balan leftRotate(parent) } } + else -> throw IllegalStateException() } } @@ -289,29 +292,27 @@ class RBBalancer>(private var root: RBNode?): Balan return } when { - brother.left?.color == Markers.RED -> - { + brother.left?.color == Markers.RED -> { brother.left?.color = Markers.BLACK if (brother == parent.left) { rightRotate(parent) - } - else { + } else { rightRotate(brother) leftRotate(parent) } } - brother.right?.color == Markers.RED -> - { + + brother.right?.color == Markers.RED -> { brother.right?.color = Markers.BLACK if (brother == parent.right) { leftRotate(parent) - } - else { + } else { leftRotate(brother) rightRotate(parent) } } + else -> throw IllegalStateException() } } diff --git a/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt b/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt index 67ffc27..ee6a216 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt @@ -1,9 +1,11 @@ package treelib.rbTree +import treelib.DBNodeRB import treelib.abstractTree.balanced.BalancedTreeStruct import treelib.singleObjects.Markers import treelib.singleObjects.exceptions.ImpossibleCaseException import treelib.singleObjects.exceptions.MultithreadingException +import java.util.* class RBStruct> : BalancedTreeStruct, RBStateContainer, RBBalancer>() { @@ -15,17 +17,17 @@ class RBStruct> : override fun generateStateDelete( deletedNode: RBNode?, contentNode: RBNode?, - ): RBStateContainer = RBStateContainer(contentNode) + ): RBStateContainer = RBStateContainer(contentNode) override fun generateStateInsert( insertNode: RBNode?, contentNode: RBNode?, - ): RBStateContainer = RBStateContainer(insertNode) + ): RBStateContainer = RBStateContainer(insertNode) override fun generateStateFind( findNode: RBNode?, contentNode: RBNode?, - ): RBStateContainer = RBStateContainer(findNode) + ): RBStateContainer = RBStateContainer(findNode) override fun connectUnlinkedSubTreeWithParent( node: RBNode, @@ -39,11 +41,12 @@ class RBStruct> : (node.value < parent.value) -> { parent.left = childForLink } + (node.value > parent.value) -> { parent.right = childForLink } } - if (childForLink != null){ + if (childForLink != null) { childForLink.parent = parent } } else root?.let { @@ -62,12 +65,60 @@ class RBStruct> : root?.let { it.color = Markers.BLACK } ?: throw MultithreadingException(ImpossibleCaseException()) - } - else { + } else { if (node.value > parent.value) parent.right = node else parent.left = node node.parent = parent } return node } + + fun restoreTreeFromDatabase(preOrder: List>, inOrder: List>) { + var inOrderIndex = 0 + var preOrderIndex = 0 + val set = HashSet>() + val stack = LinkedList>() + + while (preOrderIndex in preOrder.indices) { + var currentNode: RBNode? + var drawNode: DBNodeRB + + do { + drawNode = preOrder[preOrderIndex] + currentNode = createRBNode(drawNode) + if (root == null) { + root = currentNode + } + if (!stack.isEmpty()) { + if (set.contains(stack.peek())) { + set.remove(stack.peek()) + stack.pop().right = currentNode + } else { + stack.peek().left = currentNode + // связь с ролитилем + } + } + stack.push(currentNode) + } while (preOrder[preOrderIndex++] != inOrder[inOrderIndex] && preOrderIndex < preOrder.size) + + currentNode = null + while (stack.isEmpty() && inOrderIndex < inOrder.size && + stack.peek().value == inOrder[inOrderIndex].value + ) { + currentNode = stack.pop() + ++inOrderIndex + } + + if (currentNode != null) { + set.add(currentNode) + stack.push(currentNode) + } + } + + } + + private fun createRBNode(drawNode: DBNodeRB): RBNode { + val node = RBNode(value = drawNode.value, color = drawNode.color) + return node + } } From 1e7f2a8151abe81d3a34958ec5a99150c97a8735 Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 18 Apr 2023 21:33:22 +0300 Subject: [PATCH 33/84] fix: Fix database interaction --- lib/src/main/kotlin/Controller.kt | 35 +--- lib/src/main/kotlin/DataBase.kt | 186 ++++++++++-------- lib/src/main/kotlin/initNeo4j.sh | 0 lib/src/main/kotlin/loadNeo4j.sh | 8 + lib/src/main/kotlin/testNeo4j.sh | 13 +- lib/src/main/kotlin/treelib/Main.kt | 29 ++- .../main/kotlin/treelib/abstractTree/Tree.kt | 37 ++-- .../kotlin/treelib/abstractTree/TreeStruct.kt | 39 ++-- .../kotlin/treelib/abstractTree/Vertex.kt | 5 + .../balanced/BalancedTreeStruct.kt | 4 +- .../main/kotlin/treelib/avlTree/AVLStruct.kt | 6 +- .../main/kotlin/treelib/avlTree/AVLTree.kt | 10 +- .../main/kotlin/treelib/avlTree/AVLVertex.kt | 8 + .../main/kotlin/treelib/binTree/BINStruct.kt | 6 +- .../main/kotlin/treelib/binTree/BINTree.kt | 10 +- .../main/kotlin/treelib/binTree/BINVertex.kt | 5 + .../kotlin/treelib/rbTree/DrawRBVertex.kt | 10 + .../main/kotlin/treelib/rbTree/RBBalancer.kt | 24 +-- .../main/kotlin/treelib/rbTree/RBStruct.kt | 13 +- lib/src/main/kotlin/treelib/rbTree/RBTree.kt | 10 +- .../main/kotlin/treelib/rbTree/RBVertex.kt | 9 + 21 files changed, 292 insertions(+), 175 deletions(-) create mode 100644 lib/src/main/kotlin/initNeo4j.sh create mode 100644 lib/src/main/kotlin/loadNeo4j.sh create mode 100644 lib/src/main/kotlin/treelib/abstractTree/Vertex.kt create mode 100644 lib/src/main/kotlin/treelib/avlTree/AVLVertex.kt create mode 100644 lib/src/main/kotlin/treelib/binTree/BINVertex.kt create mode 100644 lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt create mode 100644 lib/src/main/kotlin/treelib/rbTree/RBVertex.kt diff --git a/lib/src/main/kotlin/Controller.kt b/lib/src/main/kotlin/Controller.kt index cc4e699..a59a3b0 100644 --- a/lib/src/main/kotlin/Controller.kt +++ b/lib/src/main/kotlin/Controller.kt @@ -1,6 +1,6 @@ -import treelib.DBNodeRB + +import treelib.rbTree.DrawRBVertex import treelib.rbTree.RBStruct -import treelib.rbTree.RBTree import treelib.singleObjects.Container class Controller { @@ -8,43 +8,28 @@ class Controller { fun initTree() { val neo4jDB = Neo4jRepository() neo4jDB.open("bolt://localhost:7687", "neo4j", "test-neo4j") + /*** orders.first = preOrder, orders.second = inOrder ***/ - val orders: Pair>>>, List>>>> = + val orders: Pair>>>, List>>>> = neo4jDB.exportRBtree() val RBtree = RBStruct>>() RBtree.restoreTreeFromDatabase(orders.first, orders.second) + neo4jDB.close() } - fun saveTree() { - val tree = RBTree() - tree.putItem(Pair(25, 1)) - tree.putItem(Pair(15, 1)) - tree.putItem(Pair(50, 1)) - tree.putItem(Pair(10, 1)) - tree.putItem(Pair(22, 1)) - tree.putItem(Pair(35, 1)) - tree.putItem(Pair(70, 1)) - tree.putItem(Pair(4, 1)) - tree.putItem(Pair(12, 1)) - tree.putItem(Pair(18, 1)) - tree.putItem(Pair(24, 1)) - tree.putItem(Pair(31, 1)) - tree.putItem(Pair(44, 1)) - tree.putItem(Pair(66, 1)) - tree.putItem(Pair(90, 1)) - + fun > saveTree(tree: RBStruct) { val neo4jDB = Neo4jRepository() neo4jDB.open("bolt://localhost:7687", "neo4j", "test-neo4j") - val preOrder = tree.preOrder().map { DBNodeRB(it.value, it.color) } - val inOrder = tree.inOrder().map { DBNodeRB(it.value, it.color) } + // вот тут плохо, потому что тут надо получать не base nodes, а для рисовалки - neo4jDB.saveChanges(preOrder.toTypedArray(), inOrder.toTypedArray()) + val preOrder = tree.preOrder().map { DrawRBVertex(it.value, it.color) } + val inOrder = tree.inOrder().map { DrawRBVertex(it.value, it.color) } + neo4jDB.saveChanges(preOrder.toTypedArray(), inOrder.toTypedArray()) neo4jDB.close() - } } \ No newline at end of file diff --git a/lib/src/main/kotlin/DataBase.kt b/lib/src/main/kotlin/DataBase.kt index e7ca4c6..809eb64 100644 --- a/lib/src/main/kotlin/DataBase.kt +++ b/lib/src/main/kotlin/DataBase.kt @@ -1,8 +1,9 @@ import org.neo4j.driver.AuthTokens import org.neo4j.driver.Driver import org.neo4j.driver.GraphDatabase +import org.neo4j.driver.TransactionContext import org.neo4j.driver.exceptions.SessionExpiredException -import treelib.DBNodeRB +import treelib.rbTree.DrawRBVertex import treelib.singleObjects.Container import treelib.singleObjects.Markers import java.io.Closeable @@ -23,88 +24,50 @@ class Neo4jRepository : Closeable { } } - fun > saveChanges(preOrder: Array>, inOrder: Array>) { + fun > saveChanges(preOrder: Array>, inOrder: Array>) { /*** сюда по ощущениям лучше всего добавлять именно то поддерево исходного дерева, которое было изменено ***/ val session = driver?.session() ?: throw IOException() var inOrderIndex = 0 var preOrderIndex = 0 - val set = HashSet>() - val stack = LinkedList>() + val set = HashSet>() + val stack = LinkedList>() + var id = 0 while (preOrderIndex in preOrder.indices) { do { val currentNode = preOrder[preOrderIndex] - currentNode.value as Container<*, *> + //currentNode.value as Container<*, *> if (preOrderIndex == 0) { session.executeWrite { tx -> - tx.run( - "MERGE(:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY})", - mutableMapOf( - "nodeValue" to currentNode.value.pair.second, - "nodeKey" to currentNode.value.pair.first, - "nodeColor" to currentNode.color.toString(), - "nodeX" to currentNode.x, - "nodeY" to currentNode.y - ) - ) + cleanDB(tx) + createRoot(tx, currentNode, id) } + ++id } if (!stack.isEmpty()) { if (set.contains(stack.peek())) { set.remove(stack.peek()) val parentNode = stack.pop() - parentNode.value as Container<*, *> + //parentNode.value as Container<*, *> session.executeWrite { tx -> - tx.run( - "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + - "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + - "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + - "MERGE (parent)-[:RIGHT_SON]->(son)", - mutableMapOf( - "parentNodeValue" to parentNode.value.pair.second, - "parentNodeKey" to parentNode.value.pair.first, - "parentNodeColor" to parentNode.color.toString(), - "parentNodeX" to parentNode.x, - "parentNodeY" to parentNode.y, - "nodeValue" to currentNode.value.pair.second, - "nodeKey" to currentNode.value.pair.first, - "nodeColor" to currentNode.color.toString(), - "nodeX" to currentNode.x, - "nodeY" to currentNode.y - ) - ) + createRightSon(tx, parentNode, currentNode, id) } + ++id } else { val parentNode = stack.peek() parentNode.value as Container<*, *> session.executeWrite { tx -> - tx.run( - "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + - "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + - "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + - "MERGE (parent)-[:LEFT_SON]->(son)", - mutableMapOf( - "parentNodeValue" to parentNode.value.pair.second, - "parentNodeKey" to parentNode.value.pair.first, - "parentNodeColor" to parentNode.color.toString(), - "parentNodeX" to parentNode.x, - "parentNodeY" to parentNode.y, - "nodeValue" to currentNode.value.pair.second, - "nodeKey" to currentNode.value.pair.first, - "nodeColor" to currentNode.color.toString(), - "nodeX" to currentNode.x, - "nodeY" to currentNode.y - ) - ) + createLeftSon(tx, parentNode, currentNode, id) } + ++id } } stack.push(currentNode) - } while (preOrder[preOrderIndex++] != inOrder[inOrderIndex] && preOrderIndex < preOrder.size) + } while (preOrder[preOrderIndex++].value != inOrder[inOrderIndex].value && preOrderIndex < preOrder.size) - var currentNode: DBNodeRB? = null + var currentNode: DrawRBVertex? = null while (!stack.isEmpty() && inOrderIndex < inOrder.size && stack.peek().value == inOrder[inOrderIndex].value) { currentNode = stack.pop() @@ -121,23 +84,26 @@ class Neo4jRepository : Closeable { session.close() } - fun exportRBtree(): Pair>>>, List>>>> { + fun exportRBtree(): Pair>>>, List>>>> { + + /*** Вот тут короче надо обращаться к neo4j с темЮ чтобы она инициализировала себя как-то ***/ val session = driver?.session() ?: throw IOException() - var preOrder: List>>> = listOf() - var inOrder: List>>> = listOf() + var preOrder: List>>> = listOf() + var inOrder: List>>> = listOf() session.executeRead { tx -> preOrder = tx.run( "MATCH (node: Node) " + - "RETURN node.value, node.key, node.color, node.x, node.y " + "RETURN node.value, node.key, node.color, node.x, node.y " + + "ORDER BY node.id" ).list() .map { - DBNodeRB( - value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), - color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, - x = it.values().get(3).toString().toDouble(), - y = it.values().get(4).toString().toDouble() + DrawRBVertex( + value = Container(Pair(it.values()[1].toString(), it.values()[0].toString())), + color = if (it.values()[2].toString() == """RED""") Markers.RED else Markers.BLACK, + x = it.values()[3].toString().toDouble(), + y = it.values()[4].toString().toDouble() ) } @@ -147,11 +113,11 @@ class Neo4jRepository : Closeable { "ORDER BY node.key" ).list() .map { - DBNodeRB( - value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), - color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, - x = it.values().get(3).toString().toDouble(), - y = it.values().get(4).toString().toDouble() + DrawRBVertex( + value = Container(Pair(it.values()[1].toString(), it.values()[0].toString())), + color = if (it.values()[2].toString() == """RED""") Markers.RED else Markers.BLACK, + x = it.values()[3].toString().toDouble(), + y = it.values()[4].toString().toDouble() ) } } @@ -162,18 +128,80 @@ class Neo4jRepository : Closeable { } + private fun cleanDB(tx: TransactionContext) { + tx.run("MATCH (n: Node) DETACH DELETE n") + } + + private fun > createRoot(tx: TransactionContext, rootNode: DrawRBVertex, id: Int) { + rootNode.value as Container<*, *> + tx.run( + "MERGE(:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY, id: \$nodeID})", + mutableMapOf( + "nodeValue" to rootNode.value.pair.second, + "nodeKey" to rootNode.value.pair.first, + "nodeColor" to rootNode.color.toString(), + "nodeX" to rootNode.x, + "nodeY" to rootNode.y, + "nodeID" to id + ) + ) + } + + private fun > createRightSon( + tx: TransactionContext, parentNode: DrawRBVertex, + currentNode: DrawRBVertex, id: Int + ) { + parentNode.value as Container<*, *> + currentNode.value as Container<*, *> + tx.run( + "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY, id: \$nodeID}) " + + "MERGE (parent)-[:RIGHT_SON]->(son)", + mutableMapOf( + "parentNodeValue" to parentNode.value.pair.second, + "parentNodeKey" to parentNode.value.pair.first, + "parentNodeColor" to parentNode.color.toString(), + "parentNodeX" to parentNode.x, + "parentNodeY" to parentNode.y, + "nodeValue" to currentNode.value.pair.second, + "nodeKey" to currentNode.value.pair.first, + "nodeColor" to currentNode.color.toString(), + "nodeX" to currentNode.x, + "nodeY" to currentNode.y, + "nodeID" to id, + ) + ) + } + + private fun > createLeftSon( + tx: TransactionContext, parentNode: DrawRBVertex, + currentNode: DrawRBVertex, id: Int + ) { + parentNode.value as Container<*, *> + currentNode.value as Container<*, *> + tx.run( + "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY, id: \$nodeID}) " + + "MERGE (parent)-[:LEFT_SON]->(son)", + mutableMapOf( + "parentNodeValue" to parentNode.value.pair.second, + "parentNodeKey" to parentNode.value.pair.first, + "parentNodeColor" to parentNode.color.toString(), + "parentNodeX" to parentNode.x, + "parentNodeY" to parentNode.y, + "nodeValue" to currentNode.value.pair.second, + "nodeKey" to currentNode.value.pair.first, + "nodeColor" to currentNode.color.toString(), + "nodeX" to currentNode.x, + "nodeY" to currentNode.y, + "nodeID" to id, + ) + ) + } + override fun close() { driver?.close() } } - -// neo4j-admin, backup, restore -/* -у меня есть вершины и ребра между ними, надо уметь сохранять дерево в базе, но как? -вопрос: когда заносить изменения в бд и как это реализовывать? -надо еще подумать над оптимизацией, те чтобы не пересобирать дерево в бд каждый раз, когда мы добавили за сессию всего один узел - -root = tx.run("MATCH (parent: Node)-->(son: Node) " + - "WHERE NOT ()-->(parent) " + - "RETURN parent.value, parent.key, parent.color, parent.x, parent.y").list().map {it.values()}.get(0) - */ diff --git a/lib/src/main/kotlin/initNeo4j.sh b/lib/src/main/kotlin/initNeo4j.sh new file mode 100644 index 0000000..e69de29 diff --git a/lib/src/main/kotlin/loadNeo4j.sh b/lib/src/main/kotlin/loadNeo4j.sh new file mode 100644 index 0000000..d4d9fcd --- /dev/null +++ b/lib/src/main/kotlin/loadNeo4j.sh @@ -0,0 +1,8 @@ + +BASEDIR=$(realpath "$(dirname "$0")") + +. "${BASEDIR}/CONTAINER.conf" + +docker stop "$CONTAINER_NAME" + +neo4j-admin dump --database=neo4j --to=/data/backups/ \ No newline at end of file diff --git a/lib/src/main/kotlin/testNeo4j.sh b/lib/src/main/kotlin/testNeo4j.sh index 97ad8db..87b69c4 100644 --- a/lib/src/main/kotlin/testNeo4j.sh +++ b/lib/src/main/kotlin/testNeo4j.sh @@ -3,13 +3,22 @@ BASEDIR=$(realpath "$(dirname "$0")") . "${BASEDIR}/CONTAINER.conf" +# -d docker run \ - --rm \ - --name "CONTAINER_NAME" \ + -i \ + --name "$CONTAINER_NAME" \ --volume=$HOME/neo4j/data:/data \ --volume=$HOME/neo4j/logs:/logs \ --publish=7474:7474 --publish=7687:7687 \ --env NEO4J_AUTH=neo4j/"$PASSWORD" \ neo4j:latest \ +# -c /bin/bash +#neo4j-admin database dump neo4j --to-path=$HOME/neo4j/data:/data + +#docker ps -a + +#docker stop "$CONTAINER_NAME" + +#cp $HOME/neo4j/data:/data $HOME/ #docker stop neo4j:latest diff --git a/lib/src/main/kotlin/treelib/Main.kt b/lib/src/main/kotlin/treelib/Main.kt index 0aeb3e0..15e0eab 100644 --- a/lib/src/main/kotlin/treelib/Main.kt +++ b/lib/src/main/kotlin/treelib/Main.kt @@ -1,6 +1,8 @@ package treelib import Controller +import treelib.rbTree.RBStruct +import treelib.singleObjects.Container fun main() { @@ -30,10 +32,35 @@ fun main() { neo4jRep.open("bolt://localhost:7687", "neo4j", "test-neo4j") neo4jRep.saveChanges(preArr, inArr) */ + + val tree = RBStruct>() + tree.insert(Container(Pair(25 , 1))) + tree.insert(Container(Pair(15 , 1))) + tree.insert(Container(Pair(50 , 1))) + tree.insert(Container(Pair(10 , 1))) + tree.insert(Container(Pair(22 , 1))) + tree.insert(Container(Pair(35 , 1))) + tree.insert(Container(Pair(70 , 1))) + tree.insert(Container(Pair(4 , 1))) + tree.insert(Container(Pair(12 , 1))) + tree.insert(Container(Pair(18 , 1))) + tree.insert(Container(Pair(24 , 1))) + tree.insert(Container(Pair(31 , 1))) + tree.insert(Container(Pair(44 , 1))) + tree.insert(Container(Pair(66 , 1))) + tree.insert(Container(Pair(90 , 1))) val controller = Controller() - controller.saveTree() + controller.saveTree(tree) + tree.insert(Container(Pair(100, 1))) + controller.saveTree(tree) + controller.initTree() //neo4jRep.exportRBtree() //neo4jRep.close() +} + +fun test() { + val cont = Controller() + cont.initTree() } \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/abstractTree/Tree.kt b/lib/src/main/kotlin/treelib/abstractTree/Tree.kt index 1607caa..1116ad6 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/Tree.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/Tree.kt @@ -4,44 +4,47 @@ import treelib.singleObjects.Container import treelib.singleObjects.exceptions.NonExistentValueException abstract class Tree< - Key : Comparable, - Value, - NodeType : Node, NodeType>, - State : StateContainer, NodeType> + K : Comparable, + V, + NodeType : Node, NodeType>, + State : StateContainer, NodeType>, + VertexType: Vertex> > { - protected abstract val treeStruct: TreeStruct, NodeType, State> + protected abstract val treeStruct: TreeStruct, NodeType, State, VertexType> - private fun wrapForFind(key: Key) = Container(key to null) + private fun wrapForFind(key: K) = Container(key to null) - fun putItem(item: Pair) { + fun putItem(item: Pair) { treeStruct.insert(Container(item)) } - fun putItems(vararg items: Pair) { + fun putItems(vararg items: Pair) { for (element in items) putItem(element) } - fun putItems(items: Iterable>) { + fun putItems(items: Iterable>) { for (element in items) putItem(element) } - fun getItem(key: Key): Value? = treeStruct.find(wrapForFind(key))?.value + fun getItem(key: K): V? = treeStruct.find(wrapForFind(key))?.value - fun deleteItem(key: Key) { + fun deleteItem(key: K) { if (getItem(key) == null) throw NonExistentValueException() treeStruct.delete(wrapForFind(key)) } - private fun createPoorList(info: List): List { - val returnInfo = mutableListOf() - for (element in info) returnInfo.add(element) + private fun createPoorList(info: List): List> { + val returnInfo = mutableListOf>() + for (element in info) { + returnInfo.add(element.value.pair) + } return returnInfo } - fun inOrder(): List = createPoorList(treeStruct.inOrder()) + fun inOrder(): List> = createPoorList(treeStruct.inOrder()) - fun preOrder(): List = createPoorList(treeStruct.preOrder()) + fun preOrder(): List> = createPoorList(treeStruct.preOrder()) - fun postOrder(): List = createPoorList(treeStruct.postOrder()) + fun postOrder(): List> = createPoorList(treeStruct.postOrder()) } diff --git a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt index 5b96f98..c91c6ed 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt @@ -9,7 +9,8 @@ import treelib.singleObjects.exceptions.NonExistentValueException abstract class TreeStruct< Pack : Comparable, NodeType : Node, - State : StateContainer + State : StateContainer, + VertexType: Vertex > { protected abstract var root: NodeType? @@ -163,8 +164,8 @@ abstract class TreeStruct< linkNewNode(currentNode, parentNode) - if (parentNode == null) return generateStateInsert(currentNode, currentNode) - else return generateStateInsert(currentNode, parentNode) + if (parentNode != null) return generateStateInsert(currentNode, parentNode) + else return generateStateInsert(currentNode, currentNode) } updateNode.value = item @@ -260,8 +261,8 @@ abstract class TreeStruct< fun find(obj: Pack): Pack? = findItem(obj).contentNode?.value - fun inOrder(): List { - val arrayNodes = mutableListOf() + fun inOrder(): List { + val arrayNodes = mutableListOf() var flagVisited = 0 var current = root val parents = ArrayDeque() @@ -278,24 +279,26 @@ abstract class TreeStruct< } } current?.let { - arrayNodes.add(it.value) + arrayNodes.add(it) if (it.right != null) { flagVisited = 0 current = it.right } else { if (parents.isEmpty()) - return@inOrder arrayNodes + return@inOrder arrayNodes.map {toVertex(it)} flagVisited = 1 current = parents.removeLast() } } } - return arrayNodes + return arrayNodes.map{toVertex(it)} } - fun postOrder(): List { + abstract fun toVertex(node: NodeType): VertexType + + fun postOrder(): List { val parents = ArrayDeque() - val arrayNodes = mutableListOf() + val arrayNodes = mutableListOf() var flagVisited = 0 var current = root @@ -316,9 +319,9 @@ abstract class TreeStruct< current = it.right flagVisited = 0 } else { - arrayNodes.add(it.value) + arrayNodes.add(it) if (parents.isEmpty()) - return@postOrder arrayNodes + return@postOrder arrayNodes.map{toVertex(it)} val parent = parents.removeLast() if (parent.right == it) { flagVisited = 2 @@ -327,11 +330,11 @@ abstract class TreeStruct< } } ?: throw MultithreadingException(ImpossibleCaseException()) } - return arrayNodes + return arrayNodes.map{toVertex(it)} } - fun preOrder(): List { - val arrayNodes = mutableListOf() + fun preOrder(): List { + val arrayNodes = mutableListOf() var current: NodeType val queue = ArrayDeque() @@ -339,7 +342,7 @@ abstract class TreeStruct< queue.add(root) while (queue.isNotEmpty()) { current = queue.removeLast() - arrayNodes.add(current.value) + arrayNodes.add(current) if (current.right != null) current.right?.let { queue.add(it) @@ -351,6 +354,8 @@ abstract class TreeStruct< } ?: throw MultithreadingException(ImpossibleCaseException()) } } - return arrayNodes + return arrayNodes.map {toVertex(it)} } + + } diff --git a/lib/src/main/kotlin/treelib/abstractTree/Vertex.kt b/lib/src/main/kotlin/treelib/abstractTree/Vertex.kt new file mode 100644 index 0000000..abbb7a5 --- /dev/null +++ b/lib/src/main/kotlin/treelib/abstractTree/Vertex.kt @@ -0,0 +1,5 @@ +package treelib.abstractTree + +abstract class Vertex>{ + abstract val value: Pack +} \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/abstractTree/balanced/BalancedTreeStruct.kt b/lib/src/main/kotlin/treelib/abstractTree/balanced/BalancedTreeStruct.kt index 5dd24c3..96e8458 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/balanced/BalancedTreeStruct.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/balanced/BalancedTreeStruct.kt @@ -3,13 +3,15 @@ package treelib.abstractTree.balanced import treelib.abstractTree.Node import treelib.abstractTree.StateContainer import treelib.abstractTree.TreeStruct +import treelib.abstractTree.Vertex abstract class BalancedTreeStruct< Pack : Comparable, NodeType : Node, State : StateContainer, + VertexType: Vertex, BalancerType : Balancer, - > : TreeStruct() { + > : TreeStruct() { protected abstract val balancer: BalancerType diff --git a/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt b/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt index f275439..7893341 100644 --- a/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt +++ b/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt @@ -3,7 +3,7 @@ package treelib.avlTree import treelib.abstractTree.balanced.BalancedTreeStruct class AVLStruct> : - BalancedTreeStruct, AVLStateContainer, AVLBalancer>() { + BalancedTreeStruct, AVLStateContainer, AVLVertex, AVLBalancer>() { override var root: AVLNode? = null override val balancer = AVLBalancer(root) @@ -40,6 +40,10 @@ class AVLStruct> : } } + override fun toVertex(node: AVLNode): AVLVertex { + return AVLVertex(node.value, node.height) + } + override fun createNode(item: Pack): AVLNode = AVLNode(item) override fun getNodeKernel(node: AVLNode): AVLNode = AVLNode(node.value, height = node.height) diff --git a/lib/src/main/kotlin/treelib/avlTree/AVLTree.kt b/lib/src/main/kotlin/treelib/avlTree/AVLTree.kt index 6155af6..5df840f 100644 --- a/lib/src/main/kotlin/treelib/avlTree/AVLTree.kt +++ b/lib/src/main/kotlin/treelib/avlTree/AVLTree.kt @@ -4,12 +4,12 @@ import treelib.abstractTree.Tree import treelib.singleObjects.Container -class AVLTree, Value> : - Tree>, AVLStateContainer>>() { +class AVLTree, V> : + Tree>, AVLStateContainer>, AVLVertex>>() { - override val treeStruct = AVLStruct>() + override val treeStruct = AVLStruct>() - operator fun AVLTree.get(key: Key): Value? = getItem(key) + operator fun AVLTree.get(key: K): V? = getItem(key) - operator fun AVLTree.set(key: Key, value: Value) = putItem(key to value) + operator fun AVLTree.set(key: K, value: V) = putItem(key to value) } diff --git a/lib/src/main/kotlin/treelib/avlTree/AVLVertex.kt b/lib/src/main/kotlin/treelib/avlTree/AVLVertex.kt new file mode 100644 index 0000000..a43ea26 --- /dev/null +++ b/lib/src/main/kotlin/treelib/avlTree/AVLVertex.kt @@ -0,0 +1,8 @@ +package treelib.avlTree + +import treelib.abstractTree.Vertex + +class AVLVertex>( + override val value: Pack, + val height: UInt, +) : Vertex() \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/binTree/BINStruct.kt b/lib/src/main/kotlin/treelib/binTree/BINStruct.kt index e555924..f3bfc09 100644 --- a/lib/src/main/kotlin/treelib/binTree/BINStruct.kt +++ b/lib/src/main/kotlin/treelib/binTree/BINStruct.kt @@ -3,7 +3,7 @@ package treelib.binTree import treelib.abstractTree.TreeStruct class BINStruct> : - TreeStruct, BINStateContainer>() { + TreeStruct, BINStateContainer, BINVertex>() { override var root: BINNode? = null @@ -53,6 +53,10 @@ class BINStruct> : return node } + override fun toVertex(node: BINNode): BINVertex { + return BINVertex(node.value) + } + override fun createNode(item: Pack) = BINNode(item) override fun delete(item: Pack) { diff --git a/lib/src/main/kotlin/treelib/binTree/BINTree.kt b/lib/src/main/kotlin/treelib/binTree/BINTree.kt index f8ac560..f0a92d9 100644 --- a/lib/src/main/kotlin/treelib/binTree/BINTree.kt +++ b/lib/src/main/kotlin/treelib/binTree/BINTree.kt @@ -3,12 +3,12 @@ package treelib.binTree import treelib.abstractTree.Tree import treelib.singleObjects.Container -class BINTree, Value> - : Tree>, BINStateContainer>>() { +class BINTree, V> + : Tree>, BINStateContainer>, BINVertex>>() { - override val treeStruct = BINStruct>() + override val treeStruct = BINStruct>() - operator fun BINTree.get(key: Key): Value? = getItem(key) + operator fun BINTree.get(key: K): V? = getItem(key) - operator fun BINTree.set(key: Key, value: Value) = putItem(key to value) + operator fun BINTree.set(key: K, value: V) = putItem(key to value) } diff --git a/lib/src/main/kotlin/treelib/binTree/BINVertex.kt b/lib/src/main/kotlin/treelib/binTree/BINVertex.kt new file mode 100644 index 0000000..e660d8c --- /dev/null +++ b/lib/src/main/kotlin/treelib/binTree/BINVertex.kt @@ -0,0 +1,5 @@ +package treelib.binTree + +import treelib.abstractTree.Vertex + +class BINVertex>(override val value: Pack): Vertex() \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt b/lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt new file mode 100644 index 0000000..b3ee499 --- /dev/null +++ b/lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt @@ -0,0 +1,10 @@ +package treelib.rbTree + +import treelib.singleObjects.Markers + +class DrawRBVertex>( + value: Pack, + color: Markers, + val x: Double = 0.0, + val y: Double = 0.0 +) : RBVertex(value, color) \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt b/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt index 211e007..c8c4cf6 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt @@ -2,6 +2,8 @@ package treelib.rbTree import treelib.abstractTree.balanced.BalancerParent import treelib.singleObjects.Markers +import treelib.singleObjects.exceptions.IllegalBaseNodeException +import treelib.singleObjects.exceptions.IllegalNodeStateException class RBBalancer>(private var root: RBNode?) : BalancerParent, RBStateContainer>() { @@ -42,7 +44,7 @@ class RBBalancer>(private var root: RBNode?) : override fun balance(stateContainer: RBStateContainer): RBNode { val node = stateContainer.contentNode - ?: throw IllegalStateException() //IllegalBaseNodeException("A non-existent node (null) was passed to the method") + ?: throw IllegalBaseNodeException() val uncle = getUncle(node) when { /** node insertion case **/ @@ -65,7 +67,7 @@ class RBBalancer>(private var root: RBNode?) : currentNode = parent } parent = - currentNode.parent?.parent ?: throw IllegalStateException() // IllegalNodeStateException() + currentNode.parent?.parent ?: throw IllegalNodeStateException() currentNode = rightRotate(parent) currentNode.color = Markers.BLACK currentNode.right?.color = Markers.RED @@ -78,7 +80,7 @@ class RBBalancer>(private var root: RBNode?) : currentNode = parent } parent = - currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() + currentNode.parent?.parent ?: throw IllegalNodeStateException() currentNode = leftRotate(parent) currentNode.color = Markers.BLACK currentNode.right?.color = Markers.RED @@ -133,7 +135,7 @@ class RBBalancer>(private var root: RBNode?) : val uncle = getUncle(currentNode) if (uncle?.color == Markers.RED) { currentNode.parent?.color = Markers.BLACK - currentNode = currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() + currentNode = currentNode.parent?.parent ?: throw IllegalNodeStateException() currentNode.color = Markers.RED uncle.color = Markers.BLACK } else if (uncle != null) { @@ -156,13 +158,13 @@ class RBBalancer>(private var root: RBNode?) : getRoot(parent) } - else -> getRoot(node ?: throw NullPointerException() /* IllegalNodeStateException() */) + else -> getRoot(node ?: throw IllegalNodeStateException()) } } /** parent is red **/ private fun secondCase(parent: RBNode, node: RBNode?) { - var brother = getBrother(parent, node) ?: throw NullPointerException() // IllegalNodeStateException() + var brother = getBrother(parent, node) ?: throw IllegalNodeStateException() if (brother.color == Markers.RED) throw NullPointerException() @@ -214,7 +216,7 @@ class RBBalancer>(private var root: RBNode?) : /** parent is black **/ private fun thirdCase(parent: RBNode, node: RBNode?) { - val brother = getBrother(parent, node) ?: throw NullPointerException() // IllegalNodeStateException() + val brother = getBrother(parent, node) ?: throw IllegalNodeStateException() when (brother.color) { Markers.RED -> thirdCaseSubFirst(brother, parent) Markers.BLACK -> thirdCaseSubSecond(brother, parent) @@ -225,7 +227,7 @@ class RBBalancer>(private var root: RBNode?) : private fun thirdCaseSubFirst(brother: RBNode, parent: RBNode) { when (brother) { brother.parent?.left -> { - var rightBrotherSon = brother.right ?: throw NullPointerException() // IllegalNodeStateException() + var rightBrotherSon = brother.right ?: throw IllegalNodeStateException() if (rightBrotherSon.right?.color != Markers.RED && rightBrotherSon.left?.color != Markers.RED) { rightBrotherSon.color = Markers.RED @@ -242,7 +244,7 @@ class RBBalancer>(private var root: RBNode?) : leftRotate(rightBrotherSon) rightBrotherSon = - rightBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() + rightBrotherSon.parent ?: throw IllegalNodeStateException() rightBrotherSon.color = Markers.BLACK } @@ -258,7 +260,7 @@ class RBBalancer>(private var root: RBNode?) : if (leftBrotherSon.right?.color != Markers.RED && leftBrotherSon.left?.color != Markers.RED) { leftBrotherSon.color = Markers.RED brother.color = Markers.BLACK - leftRotate(brother.parent ?: throw NullPointerException()) // IllegalNodeStateException() + leftRotate(brother.parent ?: throw IllegalNodeStateException()) return } @@ -266,7 +268,7 @@ class RBBalancer>(private var root: RBNode?) : rightRotate(leftBrotherSon) leftBrotherSon.color = Markers.RED leftBrotherSon = - leftBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() + leftBrotherSon.parent ?: throw IllegalNodeStateException() leftBrotherSon.color = Markers.BLACK } diff --git a/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt b/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt index ee6a216..47dd91d 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt @@ -1,6 +1,5 @@ package treelib.rbTree -import treelib.DBNodeRB import treelib.abstractTree.balanced.BalancedTreeStruct import treelib.singleObjects.Markers import treelib.singleObjects.exceptions.ImpossibleCaseException @@ -8,7 +7,7 @@ import treelib.singleObjects.exceptions.MultithreadingException import java.util.* class RBStruct> : - BalancedTreeStruct, RBStateContainer, RBBalancer>() { + BalancedTreeStruct, RBStateContainer, RBVertex, RBBalancer>() { override var root: RBNode? = null @@ -57,6 +56,10 @@ class RBStruct> : override fun getNodeKernel(node: RBNode): RBNode = RBNode(node.value, color = node.color) + override fun toVertex(node: RBNode): RBVertex { + return RBVertex(node.value, node.color) + } + override fun createNode(item: Pack): RBNode = RBNode(item) override fun linkNewNode(node: RBNode, parent: RBNode?): RBNode { @@ -73,7 +76,7 @@ class RBStruct> : return node } - fun restoreTreeFromDatabase(preOrder: List>, inOrder: List>) { + fun > restoreTreeFromDatabase(preOrder: List, inOrder: List) { var inOrderIndex = 0 var preOrderIndex = 0 val set = HashSet>() @@ -81,7 +84,7 @@ class RBStruct> : while (preOrderIndex in preOrder.indices) { var currentNode: RBNode? - var drawNode: DBNodeRB + var drawNode: RBVertexType do { drawNode = preOrder[preOrderIndex] @@ -117,7 +120,7 @@ class RBStruct> : } - private fun createRBNode(drawNode: DBNodeRB): RBNode { + private fun > createRBNode(drawNode: RBVertexType): RBNode { val node = RBNode(value = drawNode.value, color = drawNode.color) return node } diff --git a/lib/src/main/kotlin/treelib/rbTree/RBTree.kt b/lib/src/main/kotlin/treelib/rbTree/RBTree.kt index 6ccfa32..a29234e 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBTree.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBTree.kt @@ -4,12 +4,12 @@ import treelib.abstractTree.Tree import treelib.singleObjects.Container -class RBTree, Value> : - Tree>, RBStateContainer>>() { +class RBTree, V> : + Tree>, RBStateContainer>, RBVertex>>() { - override val treeStruct = RBStruct>() + override val treeStruct = RBStruct>() - operator fun RBTree.get(key: Key): Value? = getItem(key) + operator fun RBTree.get(key: K): V? = getItem(key) - operator fun RBTree.set(key: Key, value: Value) = putItem(key to value) + operator fun RBTree.set(key: K, value: V) = putItem(key to value) } diff --git a/lib/src/main/kotlin/treelib/rbTree/RBVertex.kt b/lib/src/main/kotlin/treelib/rbTree/RBVertex.kt new file mode 100644 index 0000000..5d9d161 --- /dev/null +++ b/lib/src/main/kotlin/treelib/rbTree/RBVertex.kt @@ -0,0 +1,9 @@ +package treelib.rbTree + +import treelib.abstractTree.Vertex +import treelib.singleObjects.Markers + +open class RBVertex>( + override val value: Pack, + val color: Markers, +):Vertex() \ No newline at end of file From 8c05840c6f810f1baed01431a3d972aae0fabbfa Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 18 Apr 2023 22:04:52 +0300 Subject: [PATCH 34/84] fix: Add running on multiple OS --- .github/workflows/CI.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index ae15aca..8697f86 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -4,7 +4,10 @@ on: [push, pull_request] jobs: run: - runs-on: ubuntu-latest + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + runs-on: ${{ matrix.os }} steps: - name: Checkout uses: actions/checkout@v3 From 93b4cf76b6ba15fdbb0adcb3901cd20ae25aca9e Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 18 Apr 2023 22:37:53 +0300 Subject: [PATCH 35/84] fix: Fix tree class definitions --- .gitignore | 3 ++- lib/src/test/kotlin/treelib/AVLStructTest.kt | 3 ++- lib/src/test/kotlin/treelib/BINStructTest.kt | 3 ++- lib/src/test/kotlin/treelib/RBStructTest.kt | 3 ++- lib/src/test/kotlin/utils/TreeStructWrapper.kt | 3 ++- lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt | 3 ++- lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt | 3 ++- .../test/kotlin/utils/fuzzers/TreeStructFuzzer.kt | 12 +++++++----- 8 files changed, 21 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 7061064..38f0b3d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /.gradle/ /.idea/ /build/ -/lib/build/ \ No newline at end of file +/lib/build/ +/lib/TEST_TEST/ diff --git a/lib/src/test/kotlin/treelib/AVLStructTest.kt b/lib/src/test/kotlin/treelib/AVLStructTest.kt index 1e522fe..f003b60 100644 --- a/lib/src/test/kotlin/treelib/AVLStructTest.kt +++ b/lib/src/test/kotlin/treelib/AVLStructTest.kt @@ -7,12 +7,13 @@ import org.junit.jupiter.api.fail import treelib.avlTree.AVLNode import treelib.avlTree.AVLStateContainer import treelib.avlTree.AVLStruct +import treelib.avlTree.AVLVertex import utils.AVLAnalyzer import utils.TreeStructWrapper @DisplayName("Test: AVL Struct") class AVLStructTest { - private val treeW = TreeStructWrapper, AVLStateContainer, AVLStruct>() + private val treeW = TreeStructWrapper, AVLVertex, AVLStateContainer, AVLStruct>() private val treeH = AVLAnalyzer(::testAssert) private var treeStruct = AVLStruct() diff --git a/lib/src/test/kotlin/treelib/BINStructTest.kt b/lib/src/test/kotlin/treelib/BINStructTest.kt index 952a6fa..1075631 100644 --- a/lib/src/test/kotlin/treelib/BINStructTest.kt +++ b/lib/src/test/kotlin/treelib/BINStructTest.kt @@ -7,13 +7,14 @@ import org.junit.jupiter.api.fail import treelib.binTree.BINNode import treelib.binTree.BINStateContainer import treelib.binTree.BINStruct +import treelib.binTree.BINVertex import utils.BINAnalyzer import utils.TreeStructWrapper import kotlin.test.assertEquals @DisplayName("Test: Binary Search Tree Struct") class BINStructTest { - val treeW = TreeStructWrapper, BINStateContainer, BINStruct>() + val treeW = TreeStructWrapper, BINVertex, BINStateContainer, BINStruct>() var treeStruct = BINStruct() private fun testAssert(msg: String): Nothing = fail(msg) diff --git a/lib/src/test/kotlin/treelib/RBStructTest.kt b/lib/src/test/kotlin/treelib/RBStructTest.kt index 606ca40..3196207 100644 --- a/lib/src/test/kotlin/treelib/RBStructTest.kt +++ b/lib/src/test/kotlin/treelib/RBStructTest.kt @@ -4,6 +4,7 @@ import org.junit.jupiter.api.* import treelib.rbTree.RBNode import treelib.rbTree.RBStateContainer import treelib.rbTree.RBStruct +import treelib.rbTree.RBVertex import treelib.singleObjects.Markers import utils.RBAnalyzer import utils.TreeStructWrapper @@ -12,7 +13,7 @@ import kotlin.test.assertEquals @DisplayName("Test: Red-Black Tree Struct") class RBStructTest { - private val treeW = TreeStructWrapper, RBStateContainer, RBStruct>() + private val treeW = TreeStructWrapper, RBVertex, RBStateContainer, RBStruct>() private var treeStruct = RBStruct() private fun testAssert(msg: String): Nothing = fail(msg) diff --git a/lib/src/test/kotlin/utils/TreeStructWrapper.kt b/lib/src/test/kotlin/utils/TreeStructWrapper.kt index 1bdb93e..64fea41 100644 --- a/lib/src/test/kotlin/utils/TreeStructWrapper.kt +++ b/lib/src/test/kotlin/utils/TreeStructWrapper.kt @@ -3,8 +3,9 @@ package utils import treelib.abstractTree.Node import treelib.abstractTree.StateContainer import treelib.abstractTree.TreeStruct +import treelib.abstractTree.Vertex -class TreeStructWrapper, NodeType : Node, State: StateContainer, TStruct : TreeStruct> { +class TreeStructWrapper, NodeType : Node, VertexType: Vertex, State: StateContainer, TStruct : TreeStruct> { fun getPrivateNode(tree: TStruct, name: String = "root"): NodeType? { val field = tree.javaClass.getDeclaredField(name) diff --git a/lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt b/lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt index 5ce3959..bc79507 100644 --- a/lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt +++ b/lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt @@ -3,12 +3,13 @@ package utils.fuzzers import treelib.binTree.BINNode import treelib.binTree.BINStateContainer import treelib.binTree.BINStruct +import treelib.binTree.BINVertex import utils.BINAnalyzer class BINStructFuzzer>( override val baseInput: Array, override val assertMethod: (input: String) -> Unit -): TreeStructFuzzer, BINAnalyzer, BINStateContainer, BINStruct>() { +): TreeStructFuzzer, BINVertex, BINAnalyzer, BINStateContainer, BINStruct>() { override fun createTreeStruct(): BINStruct = BINStruct() diff --git a/lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt b/lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt index 6b59799..2a6bb7f 100644 --- a/lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt +++ b/lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt @@ -3,12 +3,13 @@ package utils.fuzzers import treelib.rbTree.RBNode import treelib.rbTree.RBStateContainer import treelib.rbTree.RBStruct +import treelib.rbTree.RBVertex import utils.RBAnalyzer class RBStructFuzzer>( override val baseInput: Array, override val assertMethod: (input: String) -> Unit -): TreeStructFuzzer, RBAnalyzer, RBStateContainer, RBStruct>() { +): TreeStructFuzzer, RBVertex, RBAnalyzer, RBStateContainer, RBStruct>() { override fun createTreeStruct(): RBStruct = RBStruct() diff --git a/lib/src/test/kotlin/utils/fuzzers/TreeStructFuzzer.kt b/lib/src/test/kotlin/utils/fuzzers/TreeStructFuzzer.kt index a5390b9..7d5e0d6 100644 --- a/lib/src/test/kotlin/utils/fuzzers/TreeStructFuzzer.kt +++ b/lib/src/test/kotlin/utils/fuzzers/TreeStructFuzzer.kt @@ -3,20 +3,22 @@ package utils.fuzzers import treelib.abstractTree.Node import treelib.abstractTree.StateContainer import treelib.abstractTree.TreeStruct -import kotlin.random.Random -import utils.Analyzer +import treelib.abstractTree.Vertex import treelib.singleObjects.exceptions.* -import kotlin.random.nextInt +import utils.Analyzer import utils.TreeStructWrapper import java.io.File import java.time.Instant +import kotlin.random.Random +import kotlin.random.nextInt abstract class TreeStructFuzzer< Pack : Comparable, NodeType : Node, + VertexType: Vertex, AnalyzerType : Analyzer, State : StateContainer, - TreeStructType : TreeStruct, + TreeStructType : TreeStruct, > { abstract val baseInput: Array @@ -26,7 +28,7 @@ abstract class TreeStructFuzzer< private var dirPath: String? = null - protected val treeWrapper = TreeStructWrapper() + protected val treeWrapper = TreeStructWrapper() protected abstract fun createTreeStruct(): TreeStructType From b5f52408959763f6ee8caaf54ab00d01f2cc9f05 Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 18 Apr 2023 23:33:36 +0300 Subject: [PATCH 36/84] fix(CI): Add a condition to run jacoco --- .github/workflows/CI.yml | 6 ++++-- lib/src/test/kotlin/{ => treelib}/AVLBalancerTest.kt | 0 lib/src/test/kotlin/{ => treelib}/RBBalancerTest.kt | 0 lib/src/test/kotlin/{ => treelib}/TestModelAVL.kt | 0 lib/src/test/kotlin/{ => treelib}/TestModelRBT.kt | 0 5 files changed, 4 insertions(+), 2 deletions(-) rename lib/src/test/kotlin/{ => treelib}/AVLBalancerTest.kt (100%) rename lib/src/test/kotlin/{ => treelib}/RBBalancerTest.kt (100%) rename lib/src/test/kotlin/{ => treelib}/TestModelAVL.kt (100%) rename lib/src/test/kotlin/{ => treelib}/TestModelRBT.kt (100%) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 8697f86..243bd23 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -22,10 +22,12 @@ jobs: - name: Run Tests run: ./gradlew clean test - - name: Run Test Coverage + - if: matrix.os == 'ubuntu-latest' # Container action is only supported on Linux + name: Run Test Coverage run: ./gradlew jacocoTestReport - - name: Jacoco Code Coverage Report + - if: matrix.os == 'ubuntu-latest' + name: Jacoco Code Coverage Report uses: cicirello/jacoco-badge-generator@v2.8.0 with: generate-branches-badge: true diff --git a/lib/src/test/kotlin/AVLBalancerTest.kt b/lib/src/test/kotlin/treelib/AVLBalancerTest.kt similarity index 100% rename from lib/src/test/kotlin/AVLBalancerTest.kt rename to lib/src/test/kotlin/treelib/AVLBalancerTest.kt diff --git a/lib/src/test/kotlin/RBBalancerTest.kt b/lib/src/test/kotlin/treelib/RBBalancerTest.kt similarity index 100% rename from lib/src/test/kotlin/RBBalancerTest.kt rename to lib/src/test/kotlin/treelib/RBBalancerTest.kt diff --git a/lib/src/test/kotlin/TestModelAVL.kt b/lib/src/test/kotlin/treelib/TestModelAVL.kt similarity index 100% rename from lib/src/test/kotlin/TestModelAVL.kt rename to lib/src/test/kotlin/treelib/TestModelAVL.kt diff --git a/lib/src/test/kotlin/TestModelRBT.kt b/lib/src/test/kotlin/treelib/TestModelRBT.kt similarity index 100% rename from lib/src/test/kotlin/TestModelRBT.kt rename to lib/src/test/kotlin/treelib/TestModelRBT.kt From 52ef73c68d9608474f97e331808c2dc60c92bcea Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 18 Apr 2023 23:36:42 +0300 Subject: [PATCH 37/84] refactor: Rename some methods in test classes --- lib/build.gradle.kts | 6 +++--- lib/src/test/kotlin/treelib/AVLBalancerTest.kt | 2 ++ lib/src/test/kotlin/treelib/RBBalancerTest.kt | 2 ++ lib/src/test/kotlin/treelib/TestModelAVL.kt | 2 ++ lib/src/test/kotlin/treelib/TestModelRBT.kt | 2 ++ 5 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 0f9f88e..6c76505 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -82,7 +82,7 @@ tasks.jacocoTestReport { tasks.jacocoTestCoverageVerification { classDirectories.setFrom( classDirectories.files.flatMap { fileTree(it) { - include("**/RBBalancer.class", "**/AVLBalancer.class", "**/BINStruct") + include("**/RBBalancer.class", "**/AVLBalancer.class", "**/BINStruct", "**/AVLStruct.class", "**/BINStruct.class") } }) dependsOn(tasks.jacocoTestReport) violationRules { @@ -90,7 +90,7 @@ tasks.jacocoTestCoverageVerification { element = "CLASS" limit { counter = "BRANCH" - minimum = 0.4.toBigDecimal() + minimum = 0.5.toBigDecimal() } } rule { @@ -104,7 +104,7 @@ tasks.jacocoTestCoverageVerification { element = "CLASS" limit { counter = "METHOD" - minimum = 1.0.toBigDecimal() + minimum = 0.9.toBigDecimal() } } } diff --git a/lib/src/test/kotlin/treelib/AVLBalancerTest.kt b/lib/src/test/kotlin/treelib/AVLBalancerTest.kt index 862a497..3ee5452 100644 --- a/lib/src/test/kotlin/treelib/AVLBalancerTest.kt +++ b/lib/src/test/kotlin/treelib/AVLBalancerTest.kt @@ -1,3 +1,5 @@ +package treelib + import org.junit.jupiter.api.* import org.junit.jupiter.api.Assertions.assertEquals import treelib.avlTree.AVLBalancer diff --git a/lib/src/test/kotlin/treelib/RBBalancerTest.kt b/lib/src/test/kotlin/treelib/RBBalancerTest.kt index 0bc9e43..d18134e 100644 --- a/lib/src/test/kotlin/treelib/RBBalancerTest.kt +++ b/lib/src/test/kotlin/treelib/RBBalancerTest.kt @@ -1,3 +1,5 @@ +package treelib + import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Nested diff --git a/lib/src/test/kotlin/treelib/TestModelAVL.kt b/lib/src/test/kotlin/treelib/TestModelAVL.kt index c96773d..8a3ba26 100644 --- a/lib/src/test/kotlin/treelib/TestModelAVL.kt +++ b/lib/src/test/kotlin/treelib/TestModelAVL.kt @@ -1,3 +1,5 @@ +package treelib + import treelib.avlTree.AVLNode class TestModelAVL { diff --git a/lib/src/test/kotlin/treelib/TestModelRBT.kt b/lib/src/test/kotlin/treelib/TestModelRBT.kt index ac86a6c..ca7efe7 100644 --- a/lib/src/test/kotlin/treelib/TestModelRBT.kt +++ b/lib/src/test/kotlin/treelib/TestModelRBT.kt @@ -1,3 +1,5 @@ +package treelib + import treelib.rbTree.RBNode import treelib.singleObjects.Markers From b983b6c5e60340c1e139c6d6c656bfbff8393184 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 19 Apr 2023 04:39:37 +0300 Subject: [PATCH 38/84] feat: Implement sketch of jsonRepository --- .gitignore | 1 + lib/build.gradle.kts | 3 + .../Neo4jController.kt} | 6 +- .../kotlin/dbSave/jsonFormat/DrawBINVertex.kt | 9 +++ .../dbSave/jsonFormat/JsonRepository.kt | 34 ++++++++++ .../kotlin/{ => dbSave/neo4j}/CONTAINER.conf | 0 .../rbTree => dbSave/neo4j}/DrawRBVertex.kt | 3 +- .../neo4j/Neo4jRepository.kt} | 4 +- .../kotlin/{ => dbSave/neo4j}/testNeo4j.sh | 11 ---- lib/src/main/kotlin/initNeo4j.sh | 0 lib/src/main/kotlin/loadNeo4j.sh | 8 --- lib/src/main/kotlin/treelib/DBNodeRB.kt | 11 ---- lib/src/main/kotlin/treelib/Main.kt | 66 ------------------- .../main/kotlin/treelib/binTree/BINVertex.kt | 2 +- 14 files changed, 57 insertions(+), 101 deletions(-) rename lib/src/main/kotlin/{Controller.kt => controller/Neo4jController.kt} (91%) create mode 100644 lib/src/main/kotlin/dbSave/jsonFormat/DrawBINVertex.kt create mode 100644 lib/src/main/kotlin/dbSave/jsonFormat/JsonRepository.kt rename lib/src/main/kotlin/{ => dbSave/neo4j}/CONTAINER.conf (100%) rename lib/src/main/kotlin/{treelib/rbTree => dbSave/neo4j}/DrawRBVertex.kt (79%) rename lib/src/main/kotlin/{DataBase.kt => dbSave/neo4j/Neo4jRepository.kt} (99%) rename lib/src/main/kotlin/{ => dbSave/neo4j}/testNeo4j.sh (59%) delete mode 100644 lib/src/main/kotlin/initNeo4j.sh delete mode 100644 lib/src/main/kotlin/loadNeo4j.sh delete mode 100644 lib/src/main/kotlin/treelib/DBNodeRB.kt delete mode 100644 lib/src/main/kotlin/treelib/Main.kt diff --git a/.gitignore b/.gitignore index 38f0b3d..16cba14 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ /build/ /lib/build/ /lib/TEST_TEST/ +/gradle/ diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 6c76505..db61e37 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -22,6 +22,8 @@ dependencies { api("org.apache.commons:commons-math3:3.6.1") implementation("com.google.guava:guava:31.1-jre") + implementation("com.google.code.gson:gson:2.8.5") + val neo4jCore = "4.0.5" implementation("org.neo4j", "neo4j-ogm-core", neo4jCore) implementation("org.neo4j", "neo4j-ogm-bolt-driver", neo4jCore) @@ -30,6 +32,7 @@ dependencies { testImplementation("org.jetbrains.kotlin:kotlin-test-junit5:1.8.10") testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.2") implementation(kotlin("stdlib-jdk8")) + } tasks.test { diff --git a/lib/src/main/kotlin/Controller.kt b/lib/src/main/kotlin/controller/Neo4jController.kt similarity index 91% rename from lib/src/main/kotlin/Controller.kt rename to lib/src/main/kotlin/controller/Neo4jController.kt index a59a3b0..3744351 100644 --- a/lib/src/main/kotlin/Controller.kt +++ b/lib/src/main/kotlin/controller/Neo4jController.kt @@ -1,9 +1,11 @@ +package controller -import treelib.rbTree.DrawRBVertex +import dbSave.neo4j.DrawRBVertex +import dbSave.neo4j.Neo4jRepository import treelib.rbTree.RBStruct import treelib.singleObjects.Container -class Controller { +class Neo4jController { fun initTree() { val neo4jDB = Neo4jRepository() diff --git a/lib/src/main/kotlin/dbSave/jsonFormat/DrawBINVertex.kt b/lib/src/main/kotlin/dbSave/jsonFormat/DrawBINVertex.kt new file mode 100644 index 0000000..783a1de --- /dev/null +++ b/lib/src/main/kotlin/dbSave/jsonFormat/DrawBINVertex.kt @@ -0,0 +1,9 @@ +package dbSave.jsonFormat + +import treelib.binTree.BINVertex + +class DrawBINVertex>( + value: Pack, + val x: Double = 0.0, + val y: Double = 0.0 +) : BINVertex(value) \ No newline at end of file diff --git a/lib/src/main/kotlin/dbSave/jsonFormat/JsonRepository.kt b/lib/src/main/kotlin/dbSave/jsonFormat/JsonRepository.kt new file mode 100644 index 0000000..88a1396 --- /dev/null +++ b/lib/src/main/kotlin/dbSave/jsonFormat/JsonRepository.kt @@ -0,0 +1,34 @@ +package dbSave.jsonFormat +import com.google.common.reflect.TypeToken +import com.google.gson.GsonBuilder +import java.io.File + +class JsonRepository>(private val dirPath: String) { + + init { + File(dirPath).mkdirs() + } + + fun saveChanges(preOrder: Array>, typeToken: TypeToken>>, fileName: String) { + + val gson = GsonBuilder().setPrettyPrinting().create() + val json = gson.toJson(preOrder) + + File(dirPath, fileName).run { + createNewFile() + writeText(json) + } + + val preOrd = gson.fromJson>>(json, typeToken.type) + + } + + fun exportTree(fileName: String) { + val gson = GsonBuilder().setPrettyPrinting().create() + //val json = gson.fromJson(File(dirPath, fileName).readText(), ArrayVertices::class.java) + + + } + + +} \ No newline at end of file diff --git a/lib/src/main/kotlin/CONTAINER.conf b/lib/src/main/kotlin/dbSave/neo4j/CONTAINER.conf similarity index 100% rename from lib/src/main/kotlin/CONTAINER.conf rename to lib/src/main/kotlin/dbSave/neo4j/CONTAINER.conf diff --git a/lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt b/lib/src/main/kotlin/dbSave/neo4j/DrawRBVertex.kt similarity index 79% rename from lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt rename to lib/src/main/kotlin/dbSave/neo4j/DrawRBVertex.kt index b3ee499..37100de 100644 --- a/lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt +++ b/lib/src/main/kotlin/dbSave/neo4j/DrawRBVertex.kt @@ -1,5 +1,6 @@ -package treelib.rbTree +package dbSave.neo4j +import treelib.rbTree.RBVertex import treelib.singleObjects.Markers class DrawRBVertex>( diff --git a/lib/src/main/kotlin/DataBase.kt b/lib/src/main/kotlin/dbSave/neo4j/Neo4jRepository.kt similarity index 99% rename from lib/src/main/kotlin/DataBase.kt rename to lib/src/main/kotlin/dbSave/neo4j/Neo4jRepository.kt index 809eb64..316dc4c 100644 --- a/lib/src/main/kotlin/DataBase.kt +++ b/lib/src/main/kotlin/dbSave/neo4j/Neo4jRepository.kt @@ -1,9 +1,11 @@ +package dbSave.neo4j + + import org.neo4j.driver.AuthTokens import org.neo4j.driver.Driver import org.neo4j.driver.GraphDatabase import org.neo4j.driver.TransactionContext import org.neo4j.driver.exceptions.SessionExpiredException -import treelib.rbTree.DrawRBVertex import treelib.singleObjects.Container import treelib.singleObjects.Markers import java.io.Closeable diff --git a/lib/src/main/kotlin/testNeo4j.sh b/lib/src/main/kotlin/dbSave/neo4j/testNeo4j.sh similarity index 59% rename from lib/src/main/kotlin/testNeo4j.sh rename to lib/src/main/kotlin/dbSave/neo4j/testNeo4j.sh index 87b69c4..6b07269 100644 --- a/lib/src/main/kotlin/testNeo4j.sh +++ b/lib/src/main/kotlin/dbSave/neo4j/testNeo4j.sh @@ -3,7 +3,6 @@ BASEDIR=$(realpath "$(dirname "$0")") . "${BASEDIR}/CONTAINER.conf" -# -d docker run \ -i \ --name "$CONTAINER_NAME" \ @@ -12,13 +11,3 @@ docker run \ --publish=7474:7474 --publish=7687:7687 \ --env NEO4J_AUTH=neo4j/"$PASSWORD" \ neo4j:latest \ -# -c /bin/bash -#neo4j-admin database dump neo4j --to-path=$HOME/neo4j/data:/data - -#docker ps -a - -#docker stop "$CONTAINER_NAME" - -#cp $HOME/neo4j/data:/data $HOME/ - -#docker stop neo4j:latest diff --git a/lib/src/main/kotlin/initNeo4j.sh b/lib/src/main/kotlin/initNeo4j.sh deleted file mode 100644 index e69de29..0000000 diff --git a/lib/src/main/kotlin/loadNeo4j.sh b/lib/src/main/kotlin/loadNeo4j.sh deleted file mode 100644 index d4d9fcd..0000000 --- a/lib/src/main/kotlin/loadNeo4j.sh +++ /dev/null @@ -1,8 +0,0 @@ - -BASEDIR=$(realpath "$(dirname "$0")") - -. "${BASEDIR}/CONTAINER.conf" - -docker stop "$CONTAINER_NAME" - -neo4j-admin dump --database=neo4j --to=/data/backups/ \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/DBNodeRB.kt b/lib/src/main/kotlin/treelib/DBNodeRB.kt deleted file mode 100644 index cf067e1..0000000 --- a/lib/src/main/kotlin/treelib/DBNodeRB.kt +++ /dev/null @@ -1,11 +0,0 @@ -package treelib - -import treelib.singleObjects.Markers - - -class DBNodeRB>( - val value: Pack, - val color: Markers = Markers.RED, - val x: Double = 0.0, - val y: Double = 0.0 -) diff --git a/lib/src/main/kotlin/treelib/Main.kt b/lib/src/main/kotlin/treelib/Main.kt deleted file mode 100644 index 15e0eab..0000000 --- a/lib/src/main/kotlin/treelib/Main.kt +++ /dev/null @@ -1,66 +0,0 @@ -package treelib - -import Controller -import treelib.rbTree.RBStruct -import treelib.singleObjects.Container - - -fun main() { - // 25, 15, 10, 4, 12, 22, 18, 24, 50, 35, 31, 44, 70, 66, 90 - // 4, 10, 12, 15, 18, 22, 24, 25, 31, 35, 44, 50, 66, 70, 90 - - /* - - val neo4jRep = Neo4jRepository() - val a1 = DBNodeRB(Container(Pair(1, 25))) - val a2 = DBNodeRB(Container(Pair(1, 15))) - val a3 = DBNodeRB(Container(Pair(1, 10))) - val a4 = DBNodeRB(Container(Pair(1, 4))) - val a5 = DBNodeRB(Container(Pair(1, 12))) - val a6 = DBNodeRB(Container(Pair(1, 22))) - val a7 = DBNodeRB(Container(Pair(1, 18))) - val a8 = DBNodeRB(Container(Pair(1, 24))) - val a9 = DBNodeRB(Container(Pair(1, 50))) - val a10 = DBNodeRB(Container(Pair(1, 35))) - val a11 = DBNodeRB(Container(Pair(1, 31))) - val a12 = DBNodeRB(Container(Pair(1, 44))) - val a13 = DBNodeRB(Container(Pair(1, 70))) - val a14 = DBNodeRB(Container(Pair(1, 66))) - val a15 = DBNodeRB(Container(Pair(1, 90))) - val preArr = arrayOf(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) - val inArr = arrayOf(a4, a3, a5, a2, a7, a6, a8, a1, a11, a10, a12, a9, a14, a13, a15) - neo4jRep.open("bolt://localhost:7687", "neo4j", "test-neo4j") - neo4jRep.saveChanges(preArr, inArr) - */ - - val tree = RBStruct>() - tree.insert(Container(Pair(25 , 1))) - tree.insert(Container(Pair(15 , 1))) - tree.insert(Container(Pair(50 , 1))) - tree.insert(Container(Pair(10 , 1))) - tree.insert(Container(Pair(22 , 1))) - tree.insert(Container(Pair(35 , 1))) - tree.insert(Container(Pair(70 , 1))) - tree.insert(Container(Pair(4 , 1))) - tree.insert(Container(Pair(12 , 1))) - tree.insert(Container(Pair(18 , 1))) - tree.insert(Container(Pair(24 , 1))) - tree.insert(Container(Pair(31 , 1))) - tree.insert(Container(Pair(44 , 1))) - tree.insert(Container(Pair(66 , 1))) - tree.insert(Container(Pair(90 , 1))) - val controller = Controller() - controller.saveTree(tree) - tree.insert(Container(Pair(100, 1))) - controller.saveTree(tree) - controller.initTree() - - //neo4jRep.exportRBtree() - - //neo4jRep.close() -} - -fun test() { - val cont = Controller() - cont.initTree() -} \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/binTree/BINVertex.kt b/lib/src/main/kotlin/treelib/binTree/BINVertex.kt index e660d8c..8939461 100644 --- a/lib/src/main/kotlin/treelib/binTree/BINVertex.kt +++ b/lib/src/main/kotlin/treelib/binTree/BINVertex.kt @@ -2,4 +2,4 @@ package treelib.binTree import treelib.abstractTree.Vertex -class BINVertex>(override val value: Pack): Vertex() \ No newline at end of file +open class BINVertex>(override val value: Pack): Vertex() \ No newline at end of file From 155ff6defca0f7f9236ef3f183bef4b92ea4173a Mon Sep 17 00:00:00 2001 From: Georgy S Date: Wed, 19 Apr 2023 03:20:10 +0300 Subject: [PATCH 39/84] feat: Implement AVLStruct.restoreStruct and BINStruct.restoreStruct. --- .../main/kotlin/controller/Neo4jController.kt | 2 +- .../kotlin/treelib/abstractTree/TreeStruct.kt | 2 +- .../main/kotlin/treelib/avlTree/AVLStruct.kt | 15 ++++++++++++--- .../main/kotlin/treelib/binTree/BINStruct.kt | 13 +++++++++++++ lib/src/main/kotlin/treelib/rbTree/RBStruct.kt | 3 +-- .../singleObjects/exceptions/IncorrectUsage.kt | 18 ++++++++++++++++++ lib/src/test/kotlin/treeTests/RBTreeTest.kt | 16 ++++++++++++++++ 7 files changed, 62 insertions(+), 7 deletions(-) create mode 100644 lib/src/main/kotlin/treelib/singleObjects/exceptions/IncorrectUsage.kt create mode 100644 lib/src/test/kotlin/treeTests/RBTreeTest.kt diff --git a/lib/src/main/kotlin/controller/Neo4jController.kt b/lib/src/main/kotlin/controller/Neo4jController.kt index 3744351..5c47c63 100644 --- a/lib/src/main/kotlin/controller/Neo4jController.kt +++ b/lib/src/main/kotlin/controller/Neo4jController.kt @@ -16,7 +16,7 @@ class Neo4jController { neo4jDB.exportRBtree() val RBtree = RBStruct>>() - RBtree.restoreTreeFromDatabase(orders.first, orders.second) + RBtree.restoreStruct(orders.first, orders.second) neo4jDB.close() } diff --git a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt index c91c6ed..d9b223b 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt @@ -15,7 +15,7 @@ abstract class TreeStruct< protected abstract var root: NodeType? - private fun getLeafForInsert(item: Pack): NodeType? { + protected fun getLeafForInsert(item: Pack): NodeType? { var currentNode: NodeType? = root ?: return null while (true) { diff --git a/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt b/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt index 7893341..b0ee0ae 100644 --- a/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt +++ b/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt @@ -1,6 +1,7 @@ package treelib.avlTree import treelib.abstractTree.balanced.BalancedTreeStruct +import treelib.singleObjects.exceptions.IncorrectUsage class AVLStruct> : BalancedTreeStruct, AVLStateContainer, AVLVertex, AVLBalancer>() { @@ -40,9 +41,9 @@ class AVLStruct> : } } - override fun toVertex(node: AVLNode): AVLVertex { - return AVLVertex(node.value, node.height) - } + override fun toVertex(node: AVLNode): AVLVertex = AVLVertex(node.value, node.height) + + fun toNode(vertex: AVLVertex): AVLNode = AVLNode(value = vertex.value, height = vertex.height) override fun createNode(item: Pack): AVLNode = AVLNode(item) @@ -56,4 +57,12 @@ class AVLStruct> : } return node } + fun > restoreStruct(preOrder: List){ + if (root != null) throw IncorrectUsage("The tree already exists") + for (vertex in preOrder){ + val currentNode = toNode(vertex) + val leaf = getLeafForInsert(currentNode.value) + linkNewNode(currentNode, leaf) + } + } } diff --git a/lib/src/main/kotlin/treelib/binTree/BINStruct.kt b/lib/src/main/kotlin/treelib/binTree/BINStruct.kt index f3bfc09..ea03cb6 100644 --- a/lib/src/main/kotlin/treelib/binTree/BINStruct.kt +++ b/lib/src/main/kotlin/treelib/binTree/BINStruct.kt @@ -1,6 +1,8 @@ package treelib.binTree import treelib.abstractTree.TreeStruct +import treelib.abstractTree.Vertex +import treelib.singleObjects.exceptions.IncorrectUsage class BINStruct> : TreeStruct, BINStateContainer, BINVertex>() { @@ -66,4 +68,15 @@ class BINStruct> : override fun insert(item: Pack) { insertItem(item).contentNode } + + private fun toNode(vertex: BINVertex): BINNode = BINNode(value = vertex.value) + + fun > restoreStruct(preOrder: List){ + if (root != null) throw IncorrectUsage("The tree already exists") + for (vertex in preOrder){ + val currentNode = toNode(vertex) + val leaf = getLeafForInsert(currentNode.value) + linkNewNode(currentNode, leaf) + } + } } diff --git a/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt b/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt index 47dd91d..999c113 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt @@ -76,7 +76,7 @@ class RBStruct> : return node } - fun > restoreTreeFromDatabase(preOrder: List, inOrder: List) { + fun > restoreStruct(preOrder: List, inOrder: List) { var inOrderIndex = 0 var preOrderIndex = 0 val set = HashSet>() @@ -117,7 +117,6 @@ class RBStruct> : stack.push(currentNode) } } - } private fun > createRBNode(drawNode: RBVertexType): RBNode { diff --git a/lib/src/main/kotlin/treelib/singleObjects/exceptions/IncorrectUsage.kt b/lib/src/main/kotlin/treelib/singleObjects/exceptions/IncorrectUsage.kt new file mode 100644 index 0000000..9fce7ef --- /dev/null +++ b/lib/src/main/kotlin/treelib/singleObjects/exceptions/IncorrectUsage.kt @@ -0,0 +1,18 @@ +package treelib.singleObjects.exceptions + +class IncorrectUsage : Exception { + constructor() : super( + "Incorrect use of the tree" + ) + + constructor(message: String) : super( + "$message", + ) + + constructor(message: String, cause: Throwable) : super( + "$message", + cause, + ) + + constructor(cause: Throwable) : super(cause) +} \ No newline at end of file diff --git a/lib/src/test/kotlin/treeTests/RBTreeTest.kt b/lib/src/test/kotlin/treeTests/RBTreeTest.kt new file mode 100644 index 0000000..fa56cc6 --- /dev/null +++ b/lib/src/test/kotlin/treeTests/RBTreeTest.kt @@ -0,0 +1,16 @@ +package treeTests + +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import treelib.rbTree.RBTree + +@DisplayName("Test: Red-Black Tree") +class RBTreeTest { + private var rbTree = RBTree() + + @Test + fun `insert two elements`(){ + rbTree.putItem(Pair(25, 1)) + rbTree.putItem(Pair(15, 1)) + } +} \ No newline at end of file From 342e6c3e08e71b6c7d4871b105b09fcc19791b1d Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 19 Apr 2023 05:19:33 +0300 Subject: [PATCH 40/84] fix: Fix some problems after rebase onto Tests branch --- lib/build.gradle.kts | 1 + lib/src/test/kotlin/treelib/AVLTreeTest.kt | 9 +++------ lib/src/test/kotlin/treelib/BINTreeTest.kt | 11 ++++------- lib/src/test/kotlin/treelib/RBTreeTest.kt | 9 +++------ lib/src/test/kotlin/utils/TreeWrapper.kt | 10 ++++------ lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt | 3 ++- 6 files changed, 17 insertions(+), 26 deletions(-) diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index db61e37..127daa0 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -30,6 +30,7 @@ dependencies { testImplementation("io.mockk:mockk:1.13.4") testImplementation("org.jetbrains.kotlin:kotlin-test-junit5:1.8.10") + testImplementation("org.junit.jupiter:junit-jupiter-params:5.9.2") testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.2") implementation(kotlin("stdlib-jdk8")) diff --git a/lib/src/test/kotlin/treelib/AVLTreeTest.kt b/lib/src/test/kotlin/treelib/AVLTreeTest.kt index 5531d35..5915d99 100644 --- a/lib/src/test/kotlin/treelib/AVLTreeTest.kt +++ b/lib/src/test/kotlin/treelib/AVLTreeTest.kt @@ -2,10 +2,7 @@ package treelib import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.ValueSource -import treelib.avlTree.AVLNode -import treelib.avlTree.AVLStateContainer -import treelib.avlTree.AVLStruct -import treelib.avlTree.AVLTree +import treelib.avlTree.* import treelib.singleObjects.Container import utils.TreeStructWrapper import utils.TreeWrapper @@ -15,9 +12,9 @@ import kotlin.test.assertEquals class AVLTreeTest { private val tree = AVLTree() private val treeW = - TreeWrapper>, AVLStateContainer>, AVLStruct>, AVLTree>() + TreeWrapper>, AVLVertex>, AVLStateContainer>, AVLStruct>, AVLTree>() private val treeSW = - TreeStructWrapper, AVLNode>, AVLStateContainer>, AVLStruct>>() + TreeStructWrapper, AVLNode>, AVLVertex>, AVLStateContainer>, AVLStruct>>() @ParameterizedTest diff --git a/lib/src/test/kotlin/treelib/BINTreeTest.kt b/lib/src/test/kotlin/treelib/BINTreeTest.kt index 172c545..5157c95 100644 --- a/lib/src/test/kotlin/treelib/BINTreeTest.kt +++ b/lib/src/test/kotlin/treelib/BINTreeTest.kt @@ -3,21 +3,18 @@ package treelib import org.junit.jupiter.api.Test import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.ValueSource -import treelib.binTree.BINNode -import treelib.binTree.BINStateContainer -import treelib.binTree.BINStruct -import treelib.binTree.BINTree -import utils.TreeWrapper +import treelib.binTree.* import treelib.singleObjects.Container import utils.TreeStructWrapper +import utils.TreeWrapper import kotlin.test.assertEquals class BINTreeTest { private val tree = BINTree() private val treeW = - TreeWrapper>, BINStateContainer>, BINStruct>, BINTree>() + TreeWrapper>, BINVertex>, BINStateContainer>, BINStruct>, BINTree>() private val treeSW = - TreeStructWrapper, BINNode>, BINStateContainer>, BINStruct>>() + TreeStructWrapper, BINNode>, BINVertex>, BINStateContainer>, BINStruct>>() // line - 0.6, branch - 0.5, methods = 0.9 diff --git a/lib/src/test/kotlin/treelib/RBTreeTest.kt b/lib/src/test/kotlin/treelib/RBTreeTest.kt index 5a3ceee..cd7ce2a 100644 --- a/lib/src/test/kotlin/treelib/RBTreeTest.kt +++ b/lib/src/test/kotlin/treelib/RBTreeTest.kt @@ -2,10 +2,7 @@ package treelib import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.ValueSource -import treelib.rbTree.RBNode -import treelib.rbTree.RBStateContainer -import treelib.rbTree.RBStruct -import treelib.rbTree.RBTree +import treelib.rbTree.* import treelib.singleObjects.Container import treelib.singleObjects.Markers import utils.TreeStructWrapper @@ -15,9 +12,9 @@ import kotlin.test.assertEquals class RBTreeTest { private val tree = RBTree() private val treeW = - TreeWrapper>, RBStateContainer>, RBStruct>, RBTree>() + TreeWrapper>, RBVertex>, RBStateContainer>, RBStruct>, RBTree>() private val treeSW = - TreeStructWrapper, RBNode>, RBStateContainer>, RBStruct>>() + TreeStructWrapper, RBNode>, RBVertex>, RBStateContainer>, RBStruct>>() @ParameterizedTest diff --git a/lib/src/test/kotlin/utils/TreeWrapper.kt b/lib/src/test/kotlin/utils/TreeWrapper.kt index 5ca8ea7..47858d9 100644 --- a/lib/src/test/kotlin/utils/TreeWrapper.kt +++ b/lib/src/test/kotlin/utils/TreeWrapper.kt @@ -1,9 +1,6 @@ package utils -import treelib.abstractTree.Node -import treelib.abstractTree.StateContainer -import treelib.abstractTree.Tree -import treelib.abstractTree.TreeStruct +import treelib.abstractTree.* import treelib.singleObjects.Container @@ -11,9 +8,10 @@ class TreeWrapper < V : Comparable, Value, NodeType: Node, NodeType>, + VertexType: Vertex>, State: StateContainer, NodeType>, - TStruct: TreeStruct, NodeType, State>, - Wood : Tree> { + TStruct: TreeStruct, NodeType, State, VertexType>, + Wood : Tree> { fun getPrivateNode(tree: Wood, name: String = "treeStruct"): TStruct { val treeS = tree.javaClass.getDeclaredField(name) treeS.isAccessible = true diff --git a/lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt b/lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt index 7cbed69..17d52a2 100644 --- a/lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt +++ b/lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt @@ -3,12 +3,13 @@ package utils.fuzzers import treelib.avlTree.AVLNode import treelib.avlTree.AVLStateContainer import treelib.avlTree.AVLStruct +import treelib.avlTree.AVLVertex import utils.AVLAnalyzer class AVLStructFuzzer>( override val baseInput: Array, override val assertMethod: (input: String) -> Unit -) : TreeStructFuzzer, AVLAnalyzer, AVLStateContainer, AVLStruct>() { +) : TreeStructFuzzer, AVLVertex, AVLAnalyzer, AVLStateContainer, AVLStruct>() { override fun createTreeStruct(): AVLStruct = AVLStruct() From 947e297629fc64c3d4b8c0483467aedf4578690e Mon Sep 17 00:00:00 2001 From: Georgy S Date: Sat, 15 Apr 2023 17:42:33 +0300 Subject: [PATCH 41/84] refactor: Separate tests for TreeStructs into different files. --- lib/src/test/kotlin/treelib/AVLStructTest.kt | 18 + lib/src/test/kotlin/treelib/BINStructTest.kt | 474 ++++++++++++++++ lib/src/test/kotlin/treelib/RBStructTree.kt | 18 + .../test/kotlin/treelib/TreeStructsTest.kt | 513 ------------------ 4 files changed, 510 insertions(+), 513 deletions(-) create mode 100644 lib/src/test/kotlin/treelib/AVLStructTest.kt create mode 100644 lib/src/test/kotlin/treelib/BINStructTest.kt create mode 100644 lib/src/test/kotlin/treelib/RBStructTree.kt delete mode 100644 lib/src/test/kotlin/treelib/TreeStructsTest.kt diff --git a/lib/src/test/kotlin/treelib/AVLStructTest.kt b/lib/src/test/kotlin/treelib/AVLStructTest.kt new file mode 100644 index 0000000..00215f2 --- /dev/null +++ b/lib/src/test/kotlin/treelib/AVLStructTest.kt @@ -0,0 +1,18 @@ +package treelib + +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.DisplayName +import treelib.avlTree.AVLNode +import treelib.avlTree.AVLStateContainer +import treelib.avlTree.AVLStruct + +@DisplayName("Test: AVL Struct") +class AVLStructTest { + val treeW = TreeStructWrapper, AVLStateContainer, AVLStruct>() + var classUnderTest = AVLStruct() + + @BeforeEach + fun reInitClassUnderTest() { + classUnderTest = AVLStruct() + } +} \ No newline at end of file diff --git a/lib/src/test/kotlin/treelib/BINStructTest.kt b/lib/src/test/kotlin/treelib/BINStructTest.kt new file mode 100644 index 0000000..194096e --- /dev/null +++ b/lib/src/test/kotlin/treelib/BINStructTest.kt @@ -0,0 +1,474 @@ +package treelib + +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import treelib.binTree.BINNode +import treelib.binTree.BINStateContainer +import treelib.binTree.BINStruct +import kotlin.test.assertEquals + +@DisplayName("Test: Binary Search Tree Struct") +class BINStructTest { + val treeW = TreeStructWrapper, BINStateContainer, BINStruct>() + var classUnderTest = BINStruct() + + @BeforeEach + fun reInitClassUnderTest() { + classUnderTest = BINStruct() + } + + @Test + fun `test delete root`() { + val num = mutableListOf(5, 3, 7, 1, 9, -1, 4, 2, 0, 6) + for (i in num) { + classUnderTest.insert(i) + } + classUnderTest.delete(5) + val root = treeW.getPrivateNode(classUnderTest)?.value + + assertEquals(expected = 6, actual = root) + } + + @Test + fun `test insert`() { + val num = mutableListOf(1, 2, 3, 4, 5, 8) + for (i in num) { + classUnderTest.insert(i) + } + + val additional_num = mutableListOf(1, 2, 3, 5, 7, 8, 11) + for (i in additional_num) { + classUnderTest.insert(i) + } + + val root = treeW.getPrivateNode(classUnderTest)?.value + val node_2 = treeW.getPrivateNode(classUnderTest)?.right?.value + val node_null = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_3 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value + val node_null1 = treeW.getPrivateNode(classUnderTest)?.right?.left?.value + val node_4 = treeW.getPrivateNode(classUnderTest)?.right?.right?.right?.value + + assertEquals(expected = root, actual = 1) + assertEquals(expected = node_null, actual = null) + assertEquals(expected = node_4, actual = 4) + assertEquals(expected = node_2, actual = 2) + assertEquals(expected = node_3, actual = 3) + assertEquals(expected = node_null1, actual = null) + } + + @Test + fun `test find ordinary`() { + val num = mutableListOf(2, 3, 1, 4, 5, 10) + + assertEquals(expected = classUnderTest.find(2), actual = null) + + for (i in num) { + classUnderTest.insert(i) + } + + assertEquals(expected = classUnderTest.find(2), actual = 2) + } + + @Test + fun `test find null`() { + val num = mutableListOf(1) + classUnderTest.insert(num[0]) + + assertEquals(classUnderTest.find(2), null) + + } + + @Test + fun `test find root`() { + val num = mutableListOf(1) + classUnderTest.insert(num[0]) + + assertEquals(classUnderTest.find(1), 1) + } + + @Test + fun `test insert and delete root`() { + val num = mutableListOf(1, 2) + for (i in num) { + classUnderTest.insert(i) + } + + classUnderTest.delete(1) + + val additional_num = mutableListOf(1, 2, 11) + for (i in additional_num) { + classUnderTest.insert(i) + } + + val root = treeW.getPrivateNode(classUnderTest)?.value + val node_1 = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_11 = treeW.getPrivateNode(classUnderTest)?.right?.value + + + assertEquals(expected = root, actual = 2) + assertEquals(expected = node_1, actual = 1) + assertEquals(expected = node_11, actual = 11) + } + + @Test + fun `test delete nonexistent value right`() { + val num = mutableListOf(5, 6) + for (value in num) { + classUnderTest.insert(value) + } + classUnderTest.delete(6) + + val root = treeW.getPrivateNode(classUnderTest)?.value + val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.value + + assertEquals(expected = null, actual = node_null_left) + assertEquals(expected = null, actual = node_null_right) + assertEquals(expected = 5, actual = root) + } + + @Test + fun `test delete nonexistent value left`() { + val num = mutableListOf(6, 5) + for (value in num) { + classUnderTest.insert(value) + } + classUnderTest.delete(5) + + val root = treeW.getPrivateNode(classUnderTest)?.value + val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.value + + assertEquals(expected = null, actual = node_null_left) + assertEquals(expected = null, actual = node_null_right) + assertEquals(expected = 6, actual = root) + } + + @Test + fun `test delete no child root`() { + val num = mutableListOf(3) + for (i in num) { + classUnderTest.insert(i) + } + classUnderTest.delete(3) + + val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.value + val root = treeW.getPrivateNode(classUnderTest)?.value + + assertEquals(expected = null, actual = node_null_left) + assertEquals(expected = null, actual = node_null_right) + assertEquals(expected = null, actual = root) + } + + @Test + fun `test delete no child right`() { + val num = mutableListOf(3, 10, 15) + for (i in num) { + classUnderTest.insert(i) + } + classUnderTest.delete(15) + + val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.value + val node_null_left = treeW.getPrivateNode(classUnderTest)?.right?.left?.value + val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.right?.value + val root = treeW.getPrivateNode(classUnderTest)?.value + + + assertEquals(expected = 10, actual = node_10) + assertEquals(expected = null, actual = node_null_left) + assertEquals(expected = null, actual = node_null_right) + assertEquals(expected = 3, actual = root) + } + + @Test + fun `test delete no child left`() { + val num = mutableListOf(15, 10, 3) + for (i in num) { + classUnderTest.insert(i) + } + classUnderTest.delete(3) + + val node_10 = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.left?.value + val node_null_right = treeW.getPrivateNode(classUnderTest)?.left?.right?.value + val root = treeW.getPrivateNode(classUnderTest)?.value + + + assertEquals(expected = 10, actual = node_10) + assertEquals(expected = null, actual = node_null_left) + assertEquals(expected = null, actual = node_null_right) + assertEquals(expected = 15, actual = root) + } + + @Test + fun `test delete one child left`() { + val num = mutableListOf(3, 2, 1, 5) + for (value in num) { + classUnderTest.insert(value) + } + classUnderTest.delete(2) + + val node_1 = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.left?.value + val node_null_right = treeW.getPrivateNode(classUnderTest)?.left?.right?.value + val root = treeW.getPrivateNode(classUnderTest)?.value + + assertEquals(expected = 1, actual = node_1) + assertEquals(expected = null, actual = node_null_left) + assertEquals(expected = null, actual = node_null_right) + assertEquals(expected = 3, actual = root) + } + + @Test + fun `test delete one child right`() { + val num = mutableListOf(3, 1, 5, 6) + for (value in num) { + classUnderTest.insert(value) + } + classUnderTest.delete(5) + + val node_6 = treeW.getPrivateNode(classUnderTest)?.right?.value + val node_null_left = treeW.getPrivateNode(classUnderTest)?.right?.left?.value + val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.right?.value + val root = treeW.getPrivateNode(classUnderTest)?.value + + assertEquals(expected = 6, actual = node_6) + assertEquals(expected = null, actual = node_null_left) + assertEquals(expected = null, actual = node_null_right) + assertEquals(expected = 3, actual = root) + } + + @Test + fun `test delete one child root`() { + val num = mutableListOf(3, 6) + for (value in num) { + classUnderTest.insert(value) + } + classUnderTest.delete(3) + + val node_6 = treeW.getPrivateNode(classUnderTest)?.value + val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.value + + assertEquals(expected = 6, actual = node_6) + assertEquals(expected = null, actual = node_null_left) + assertEquals(expected = null, actual = node_null_right) + } + + @Test + fun `test delete one child with family`() { + val num = mutableListOf(10, 7, 13, 6, 3, 1, 5, 2, 4, 15) + for (value in num) { + classUnderTest.insert(value) + } + classUnderTest.delete(7) + val node_6 = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_3 = treeW.getPrivateNode(classUnderTest)?.left?.left?.value + val node_null_right = treeW.getPrivateNode(classUnderTest)?.left?.right?.value + val node_1 = treeW.getPrivateNode(classUnderTest)?.left?.left?.left?.value + val node_2 = treeW.getPrivateNode(classUnderTest)?.left?.left?.left?.right?.value + val node_5 = treeW.getPrivateNode(classUnderTest)?.left?.left?.right?.value + val node_4 = treeW.getPrivateNode(classUnderTest)?.left?.left?.right?.left?.value + val root = treeW.getPrivateNode(classUnderTest)?.value + + assertEquals(expected = 6, actual = node_6) + assertEquals(expected = 3, actual = node_3) + assertEquals(expected = null, actual = node_null_right) + assertEquals(expected = 1, actual = node_1) + assertEquals(expected = 2, actual = node_2) + assertEquals(expected = 5, actual = node_5) + assertEquals(expected = 4, actual = node_4) + assertEquals(expected = 10, actual = root) + } + + @Test + fun `test delete two child only three element`() { + val num = mutableListOf(2, 1, 3) + for (i in num) { + classUnderTest.insert(i) + } + classUnderTest.delete(2) + + val root = treeW.getPrivateNode(classUnderTest)?.value + val node_1 = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_null_left1 = treeW.getPrivateNode(classUnderTest)?.left?.left?.value + val node_null_right1 = treeW.getPrivateNode(classUnderTest)?.left?.right?.value + val node_null_right_root = treeW.getPrivateNode(classUnderTest)?.right?.value + + assertEquals(expected = root, actual = 3) + assertEquals(expected = node_1, actual = 1) + assertEquals(expected = node_null_left1, actual = null) + assertEquals(expected = node_null_right1, actual = null) + assertEquals(expected = node_null_right_root, actual = null) + } + + @Test + fun `test delete two child without family`() { + val num = mutableListOf(10, 7, 5, 4, 6) + for (i in num) { + classUnderTest.insert(i) + } + classUnderTest.delete(7) + + val root = treeW.getPrivateNode(classUnderTest)?.value + val node_5 = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_4 = treeW.getPrivateNode(classUnderTest)?.left?.left?.value + val node_6 = treeW.getPrivateNode(classUnderTest)?.left?.right?.value + val node_null_left4 = treeW.getPrivateNode(classUnderTest)?.left?.left?.left?.value + val node_null_right4 = treeW.getPrivateNode(classUnderTest)?.left?.left?.right?.value + val node_null_left6 = treeW.getPrivateNode(classUnderTest)?.left?.right?.left?.value + val node_null_right6 = treeW.getPrivateNode(classUnderTest)?.left?.right?.left?.value + + assertEquals(expected = root, actual = 10) + assertEquals(expected = node_5, actual = 5) + assertEquals(expected = node_4, actual = 4) + assertEquals(expected = node_6, actual = 6) + assertEquals(expected = node_null_left4, actual = null) + assertEquals(expected = node_null_right4, actual = null) + assertEquals(expected = node_null_left6, actual = null) + assertEquals(expected = node_null_right6, actual = null) + } + + @Test + fun `test two child double delete and delete root`() { + val num = mutableListOf(6, 8, 10, 7) + for (i in num) { + classUnderTest.insert(i) + } + + classUnderTest.delete(6) + classUnderTest.delete(7) + + val root = treeW.getPrivateNode(classUnderTest)?.value + val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.value + val node_null_right10 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value + val node_null_left10 = treeW.getPrivateNode(classUnderTest)?.right?.left?.value + + assertEquals(expected = root, actual = 8) + assertEquals(expected = node_10, actual = 10) + assertEquals(expected = node_null_left10, actual = null) + assertEquals(expected = node_null_right10, actual = null) + assertEquals(expected = node_null_left, actual = null) + } + + @Test + fun `test two child delete min element in right tree`() { + val num = mutableListOf(6, 8, 10, 7, 12, 9) + for (i in num) { + classUnderTest.insert(i) + } + + classUnderTest.delete(8) + + val root = treeW.getPrivateNode(classUnderTest)?.value + val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_9 = treeW.getPrivateNode(classUnderTest)?.right?.value + val node_7 = treeW.getPrivateNode(classUnderTest)?.right?.left?.value + val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value + val node_12 = treeW.getPrivateNode(classUnderTest)?.right?.right?.right?.value + val node_null = treeW.getPrivateNode(classUnderTest)?.right?.right?.left?.value + + assertEquals(expected = root, actual = 6) + assertEquals(expected = node_9, actual = 9) + assertEquals(expected = node_null, actual = null) + assertEquals(expected = node_null_left, actual = null) + assertEquals(expected = node_7, actual = 7) + assertEquals(expected = node_10, actual = 10) + assertEquals(expected = node_12, actual = 12) + } + + @Test + fun `test two child delete min element in right tree for root`() { + val num = mutableListOf(8, 10, 7, 12, 9) + for (i in num) { + classUnderTest.insert(i) + } + + classUnderTest.delete(8) + + val root = treeW.getPrivateNode(classUnderTest)?.value + val node_7 = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.value + val node_12 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value + val node_null = treeW.getPrivateNode(classUnderTest)?.right?.left?.value + + assertEquals(expected = root, actual = 9) + assertEquals(expected = node_null, actual = null) + assertEquals(expected = node_7, actual = 7) + assertEquals(expected = node_10, actual = 10) + assertEquals(expected = node_12, actual = 12) + } + + @Test + fun `test two child delete min element in right tree for rightmost element`() { + val num = mutableListOf(8, 10, 7, 12, 13, 14) + for (i in num) { + classUnderTest.insert(i) + } + + classUnderTest.delete(8) + + val root = treeW.getPrivateNode(classUnderTest)?.value + val node_7 = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_12 = treeW.getPrivateNode(classUnderTest)?.right?.value + val node_13 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value + val node_14 = treeW.getPrivateNode(classUnderTest)?.right?.right?.right?.value + val node_null = treeW.getPrivateNode(classUnderTest)?.right?.left?.value + + assertEquals(expected = root, actual = 10) + assertEquals(expected = node_null, actual = null) + assertEquals(expected = node_7, actual = 7) + assertEquals(expected = node_13, actual = 13) + assertEquals(expected = node_14, actual = 14) + assertEquals(expected = node_12, actual = 12) + } + + @Test + fun `test two child delete min element in right tree but in Tree`() { + val num = mutableListOf(8, 12, 15, 13, 10, 11, 9) + for (i in num) { + classUnderTest.insert(i) + } + + classUnderTest.delete(12) + + val root = treeW.getPrivateNode(classUnderTest)?.value + val node_13 = treeW.getPrivateNode(classUnderTest)?.right?.value + val node_15 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value + val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.left?.value + val node_11 = treeW.getPrivateNode(classUnderTest)?.right?.left?.right?.value + val node_9 = treeW.getPrivateNode(classUnderTest)?.right?.left?.left?.value + val node_null = treeW.getPrivateNode(classUnderTest)?.right?.right?.left?.value + + assertEquals(expected = root, actual = 8) + assertEquals(expected = node_10, actual = 10) + assertEquals(expected = node_11, actual = 11) + assertEquals(expected = node_13, actual = 13) + assertEquals(expected = node_9, actual = 9) + assertEquals(expected = node_15, actual = 15) + assertEquals(expected = node_null, actual = null) + } + + @Test + fun `test two child delete min element in right tree for leftmost element`() { + val num = mutableListOf(8, 10, 7, 6) + for (i in num) { + classUnderTest.insert(i) + } + + classUnderTest.delete(8) + + val root = treeW.getPrivateNode(classUnderTest)?.value + val node_7 = treeW.getPrivateNode(classUnderTest)?.left?.value + val node_6 = treeW.getPrivateNode(classUnderTest)?.left?.left?.value + val node_null = treeW.getPrivateNode(classUnderTest)?.right?.value + + assertEquals(expected = root, actual = 10) + assertEquals(expected = node_null, actual = null) + assertEquals(expected = node_7, actual = 7) + assertEquals(expected = node_6, actual = 6) + } +} \ No newline at end of file diff --git a/lib/src/test/kotlin/treelib/RBStructTree.kt b/lib/src/test/kotlin/treelib/RBStructTree.kt new file mode 100644 index 0000000..c1e040b --- /dev/null +++ b/lib/src/test/kotlin/treelib/RBStructTree.kt @@ -0,0 +1,18 @@ +package treelib + +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.DisplayName +import treelib.rbTree.RBNode +import treelib.rbTree.RBStateContainer +import treelib.rbTree.RBStruct + +@DisplayName("Test: Red-Black Tree Struct") +class RBStructTree { + val treeW = TreeStructWrapper, RBStateContainer, RBStruct>() + var classUnderTest = RBStruct() + + @BeforeEach + fun reInitClassUnderTest() { + classUnderTest = RBStruct() + } +} \ No newline at end of file diff --git a/lib/src/test/kotlin/treelib/TreeStructsTest.kt b/lib/src/test/kotlin/treelib/TreeStructsTest.kt deleted file mode 100644 index a79b9ef..0000000 --- a/lib/src/test/kotlin/treelib/TreeStructsTest.kt +++ /dev/null @@ -1,513 +0,0 @@ -package treelib - -import org.junit.jupiter.api.* -import kotlin.test.assertEquals - -/* BINStruct */ -import treelib.binTree.BINNode -import treelib.binTree.BINStruct - -/* AVLStruct */ -import treelib.avlTree.AVLNode -import treelib.avlTree.AVLStateContainer -import treelib.avlTree.AVLStruct -import treelib.binTree.BINStateContainer - -/* RBStruct */ -import treelib.rbTree.RBNode -import treelib.rbTree.RBStateContainer -import treelib.rbTree.RBStruct - -@DisplayName("Test group: Structs testing") -class TreeStructsTest { - //TESTS ONLY WITH Comparable = INT, otherwise - errors - @Nested - @DisplayName("Test: Binary Search Tree Struct") - inner class BINStructTest { - val treeW = TreeStructWrapper, BINStateContainer, BINStruct>() - var classUnderTest = BINStruct() - - @BeforeEach - fun reInitClassUnderTest() { - classUnderTest = BINStruct() - } - @Test - fun `test delete root`() { - val num = mutableListOf(5, 3, 7, 1, 9, -1, 4 ,2, 0, 6) - for (i in num) { - classUnderTest.insert(i) - } - classUnderTest.delete(5) - val root = treeW.getPrivateNode(classUnderTest)?.value - - assertEquals(expected = 6, actual = root) - } - - @Test - fun `test insert`() { - val num = mutableListOf(1, 2, 3, 4, 5, 8) - for (i in num) { - classUnderTest.insert(i) - } - - val additional_num = mutableListOf(1, 2, 3, 5, 7, 8, 11) - for (i in additional_num) { - classUnderTest.insert(i) - } - - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_2 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_null = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_3 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val node_null1 = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - val node_4 = treeW.getPrivateNode(classUnderTest)?.right?.right?.right?.value - - assertEquals(expected = root, actual = 1) - assertEquals(expected = node_null, actual = null) - assertEquals(expected = node_4, actual = 4) - assertEquals(expected = node_2, actual = 2) - assertEquals(expected = node_3, actual = 3) - assertEquals(expected = node_null1, actual = null) - } - - @Test - fun `test find ordinary`() { - val num = mutableListOf(2, 3, 1, 4, 5 ,10) - - assertEquals(expected = classUnderTest.find(2), actual = null) - - for (i in num) { - classUnderTest.insert(i) - } - - assertEquals(expected = classUnderTest.find(2), actual = 2) - } - - @Test - fun `test find null`() { - val num = mutableListOf(1) - classUnderTest.insert(num[0]) - - assertEquals(classUnderTest.find(2), null) - - } - - @Test - fun `test find root`() { - val num = mutableListOf(1) - classUnderTest.insert(num[0]) - - assertEquals(classUnderTest.find(1), 1) - } - - @Test - fun `test insert and delete root`() { - val num = mutableListOf(1, 2) - for (i in num) { - classUnderTest.insert(i) - } - - classUnderTest.delete(1) - - val additional_num = mutableListOf(1, 2, 11) - for (i in additional_num) { - classUnderTest.insert(i) - } - - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_1 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_11 = treeW.getPrivateNode(classUnderTest)?.right?.value - - - assertEquals(expected = root, actual = 2) - assertEquals(expected = node_1, actual = 1) - assertEquals(expected = node_11, actual = 11) - } - - @Test - fun `test delete nonexistent value right`() { - val num = mutableListOf(5, 6) - for (value in num) { - classUnderTest.insert(value) - } - classUnderTest.delete(6) - - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.value - - assertEquals(expected = null, actual = node_null_left) - assertEquals(expected = null, actual = node_null_right) - assertEquals(expected = 5, actual = root) - } - - @Test - fun `test delete nonexistent value left`() { - val num = mutableListOf(6, 5) - for (value in num) { - classUnderTest.insert(value) - } - classUnderTest.delete(5) - - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.value - - assertEquals(expected = null, actual = node_null_left) - assertEquals(expected = null, actual = node_null_right) - assertEquals(expected = 6, actual = root) - } - - @Test - fun `test delete no child root`(){ - val num = mutableListOf(3) - for (i in num) { - classUnderTest.insert(i) - } - classUnderTest.delete(3) - - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.value - val root = treeW.getPrivateNode(classUnderTest)?.value - - assertEquals(expected = null, actual = node_null_left) - assertEquals(expected = null, actual = node_null_right) - assertEquals(expected = null, actual = root) - } - - @Test - fun `test delete no child right`(){ - val num = mutableListOf(3, 10, 15) - for (i in num) { - classUnderTest.insert(i) - } - classUnderTest.delete(15) - - val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val root = treeW.getPrivateNode(classUnderTest)?.value - - - assertEquals(expected = 10, actual = node_10) - assertEquals(expected = null, actual = node_null_left) - assertEquals(expected = null, actual = node_null_right) - assertEquals(expected = 3, actual = root) - } - - @Test - fun `test delete no child left`(){ - val num = mutableListOf(15, 10, 3) - for (i in num) { - classUnderTest.insert(i) - } - classUnderTest.delete(3) - - val node_10 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.left?.right?.value - val root = treeW.getPrivateNode(classUnderTest)?.value - - - assertEquals(expected = 10, actual = node_10) - assertEquals(expected = null, actual = node_null_left) - assertEquals(expected = null, actual = node_null_right) - assertEquals(expected = 15, actual = root) - } - - @Test - fun `test delete one child left`(){ - val num = mutableListOf(3, 2, 1, 5) - for (value in num) { - classUnderTest.insert(value) - } - classUnderTest.delete(2) - - val node_1 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.left?.right?.value - val root = treeW.getPrivateNode(classUnderTest)?.value - - assertEquals(expected = 1 , actual = node_1) - assertEquals(expected = null , actual = node_null_left) - assertEquals(expected = null , actual = node_null_right) - assertEquals(expected = 3, actual = root) - } - - @Test - fun `test delete one child right`(){ - val num = mutableListOf(3, 1, 5, 6) - for (value in num) { - classUnderTest.insert(value) - } - classUnderTest.delete(5) - - val node_6 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val root = treeW.getPrivateNode(classUnderTest)?.value - - assertEquals(expected = 6 , actual = node_6) - assertEquals(expected = null , actual = node_null_left) - assertEquals(expected = null , actual = node_null_right) - assertEquals(expected = 3, actual = root) - } - - @Test - fun `test delete one child root`() { - val num = mutableListOf(3, 6) - for (value in num) { - classUnderTest.insert(value) - } - classUnderTest.delete(3) - - val node_6 = treeW.getPrivateNode(classUnderTest)?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.value - - assertEquals(expected = 6 , actual = node_6) - assertEquals(expected = null , actual = node_null_left) - assertEquals(expected = null , actual = node_null_right) - } - - @Test - fun `test delete one child with family`() { - val num = mutableListOf(10, 7, 13, 6, 3, 1, 5, 2, 4, 15) - for (value in num) { - classUnderTest.insert(value) - } - classUnderTest.delete(7) - val node_6 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_3 = treeW.getPrivateNode(classUnderTest)?.left?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.left?.right?.value - val node_1 = treeW.getPrivateNode(classUnderTest)?.left?.left?.left?.value - val node_2 = treeW.getPrivateNode(classUnderTest)?.left?.left?.left?.right?.value - val node_5 = treeW.getPrivateNode(classUnderTest)?.left?.left?.right?.value - val node_4 = treeW.getPrivateNode(classUnderTest)?.left?.left?.right?.left?.value - val root = treeW.getPrivateNode(classUnderTest)?.value - - assertEquals(expected = 6 , actual = node_6) - assertEquals(expected = 3 , actual = node_3) - assertEquals(expected = null , actual = node_null_right) - assertEquals(expected = 1 , actual = node_1) - assertEquals(expected = 2 , actual = node_2) - assertEquals(expected = 5 , actual = node_5) - assertEquals(expected = 4 , actual = node_4) - assertEquals(expected = 10, actual = root) - } - - @Test - fun `test delete two child only three element`() { - val num = mutableListOf(2, 1 ,3) - for (i in num) { - classUnderTest.insert(i) - } - classUnderTest.delete(2) - - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_1 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_left1 = treeW.getPrivateNode(classUnderTest)?.left?.left?.value - val node_null_right1 = treeW.getPrivateNode(classUnderTest)?.left?.right?.value - val node_null_right_root = treeW.getPrivateNode(classUnderTest)?.right?.value - - assertEquals(expected = root, actual = 3) - assertEquals(expected = node_1, actual = 1) - assertEquals(expected = node_null_left1, actual = null) - assertEquals(expected = node_null_right1, actual = null) - assertEquals(expected = node_null_right_root, actual = null) - } - - @Test - fun `test delete two child without family`() { - val num = mutableListOf(10, 7, 5, 4, 6) - for (i in num) { - classUnderTest.insert(i) - } - classUnderTest.delete(7) - - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_5 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_4 = treeW.getPrivateNode(classUnderTest)?.left?.left?.value - val node_6 = treeW.getPrivateNode(classUnderTest)?.left?.right?.value - val node_null_left4 = treeW.getPrivateNode(classUnderTest)?.left?.left?.left?.value - val node_null_right4 = treeW.getPrivateNode(classUnderTest)?.left?.left?.right?.value - val node_null_left6 = treeW.getPrivateNode(classUnderTest)?.left?.right?.left?.value - val node_null_right6 = treeW.getPrivateNode(classUnderTest)?.left?.right?.left?.value - - assertEquals(expected = root, actual = 10) - assertEquals(expected = node_5, actual = 5) - assertEquals(expected = node_4, actual = 4) - assertEquals(expected = node_6, actual = 6) - assertEquals(expected = node_null_left4, actual = null) - assertEquals(expected = node_null_right4, actual = null) - assertEquals(expected = node_null_left6, actual = null) - assertEquals(expected = node_null_right6, actual = null) - } - - @Test - fun `test two child double delete and delete root`() { - val num = mutableListOf(6, 8, 10, 7) - for (i in num) { - classUnderTest.insert(i) - } - - classUnderTest.delete(6) - classUnderTest.delete(7) - - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_null_right10 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val node_null_left10 = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - - assertEquals(expected = root, actual = 8) - assertEquals(expected = node_10, actual = 10) - assertEquals(expected = node_null_left10, actual = null) - assertEquals(expected = node_null_right10, actual = null) - assertEquals(expected = node_null_left, actual = null) - } - - @Test - fun `test two child delete min element in right tree`() { - val num = mutableListOf(6, 8, 10, 7, 12, 9) - for (i in num) { - classUnderTest.insert(i) - } - - classUnderTest.delete(8) - - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_9 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_7 = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val node_12 = treeW.getPrivateNode(classUnderTest)?.right?.right?.right?.value - val node_null = treeW.getPrivateNode(classUnderTest)?.right?.right?.left?.value - - assertEquals(expected = root, actual = 6) - assertEquals(expected = node_9, actual = 9) - assertEquals(expected = node_null, actual = null) - assertEquals(expected = node_null_left, actual = null) - assertEquals(expected = node_7, actual = 7) - assertEquals(expected = node_10, actual = 10) - assertEquals(expected = node_12, actual = 12) - } - - @Test - fun `test two child delete min element in right tree for root`() { - val num = mutableListOf(8, 10, 7, 12, 9) - for (i in num) { - classUnderTest.insert(i) - } - - classUnderTest.delete(8) - - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_7 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_12 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val node_null = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - - assertEquals(expected = root, actual = 9) - assertEquals(expected = node_null, actual = null) - assertEquals(expected = node_7, actual = 7) - assertEquals(expected = node_10, actual = 10) - assertEquals(expected = node_12, actual = 12) - } - - @Test - fun `test two child delete min element in right tree for rightmost element`() { - val num = mutableListOf(8, 10, 7, 12, 13, 14) - for (i in num) { - classUnderTest.insert(i) - } - - classUnderTest.delete(8) - - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_7 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_12 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_13 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val node_14 = treeW.getPrivateNode(classUnderTest)?.right?.right?.right?.value - val node_null = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - - assertEquals(expected = root, actual = 10) - assertEquals(expected = node_null, actual = null) - assertEquals(expected = node_7, actual = 7) - assertEquals(expected = node_13, actual = 13) - assertEquals(expected = node_14, actual = 14) - assertEquals(expected = node_12, actual = 12) - } - - @Test - fun `test two child delete min element in right tree but in Tree`() { - val num = mutableListOf(8, 12, 15, 13, 10 , 11, 9) - for (i in num) { - classUnderTest.insert(i) - } - - classUnderTest.delete(12) - - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_13 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_15 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - val node_11 = treeW.getPrivateNode(classUnderTest)?.right?.left?.right?.value - val node_9 = treeW.getPrivateNode(classUnderTest)?.right?.left?.left?.value - val node_null = treeW.getPrivateNode(classUnderTest)?.right?.right?.left?.value - - assertEquals(expected = root, actual = 8) - assertEquals(expected = node_10, actual = 10) - assertEquals(expected = node_11, actual = 11) - assertEquals(expected = node_13, actual = 13) - assertEquals(expected = node_9, actual = 9) - assertEquals(expected = node_15, actual = 15) - assertEquals(expected = node_null, actual = null) - } - - @Test - fun `test two child delete min element in right tree for leftmost element`() { - val num = mutableListOf(8, 10, 7, 6) - for (i in num) { - classUnderTest.insert(i) - } - - classUnderTest.delete(8) - - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_7 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_6 = treeW.getPrivateNode(classUnderTest)?.left?.left?.value - val node_null = treeW.getPrivateNode(classUnderTest)?.right?.value - - assertEquals(expected = root, actual = 10) - assertEquals(expected = node_null, actual = null) - assertEquals(expected = node_7, actual = 7) - assertEquals(expected = node_6, actual = 6) - } - - } - - @Nested - @DisplayName("Test: AVL Struct") - inner class AVLStructTest { - val treeW = TreeStructWrapper, AVLStateContainer, AVLStruct>() - var classUnderTest = AVLStruct() - - @BeforeEach - fun reInitClassUnderTest() { - classUnderTest = AVLStruct() - } - } - - @Nested - @DisplayName("Test: Red-Black Tree Struct") - inner class RBStructTree { - val treeW = TreeStructWrapper, RBStateContainer,RBStruct>() - var classUnderTest = RBStruct() - - @BeforeEach - fun reInitClassUnderTest() { - classUnderTest = RBStruct() - } - } -} From 4803d92925a4c235464c2712fb43ae913d9e6dd3 Mon Sep 17 00:00:00 2001 From: Georgy S Date: Sat, 15 Apr 2023 23:28:10 +0300 Subject: [PATCH 42/84] fix: Fix bugs in RBStruct; write base tests for RBStruct. --- .../kotlin/treelib/abstractTree/TreeStruct.kt | 6 +- .../main/kotlin/treelib/rbTree/RBStruct.kt | 15 ++- lib/src/test/kotlin/treelib/RBStructTest.kt | 103 ++++++++++++++++++ lib/src/test/kotlin/treelib/RBStructTree.kt | 18 --- 4 files changed, 120 insertions(+), 22 deletions(-) create mode 100644 lib/src/test/kotlin/treelib/RBStructTest.kt delete mode 100644 lib/src/test/kotlin/treelib/RBStructTree.kt diff --git a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt index 2f21c10..422177e 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt @@ -220,7 +220,11 @@ abstract class TreeStruct, NodeType : Node> : BalancedTreeStruct, RBStateContainer, RBBalancer>() { @@ -17,12 +20,12 @@ class RBStruct> : override fun generateStateInsert( insertNode: RBNode?, contentNode: RBNode?, - ): RBStateContainer = RBStateContainer(contentNode) + ): RBStateContainer = RBStateContainer(insertNode) override fun generateStateFind( findNode: RBNode?, contentNode: RBNode?, - ): RBStateContainer = RBStateContainer(contentNode) + ): RBStateContainer = RBStateContainer(findNode) override fun connectUnlinkedSubTreeWithParent( node: RBNode, @@ -45,6 +48,7 @@ class RBStruct> : } } else root?.let { root = childForLink + if (childForLink != null) childForLink.parent = null } } @@ -53,7 +57,12 @@ class RBStruct> : override fun createNode(item: Pack): RBNode = RBNode(item) override fun linkNewNode(node: RBNode, parent: RBNode?): RBNode { - if (parent == null) root = node + if (parent == null) { + root = node + root?.let { + it.color = Markers.BLACK + } ?: throw MultithreadingException(ImpossibleCaseException()) + } else { if (node.value > parent.value) parent.right = node else parent.left = node diff --git a/lib/src/test/kotlin/treelib/RBStructTest.kt b/lib/src/test/kotlin/treelib/RBStructTest.kt new file mode 100644 index 0000000..807a1d6 --- /dev/null +++ b/lib/src/test/kotlin/treelib/RBStructTest.kt @@ -0,0 +1,103 @@ +package treelib + +import org.junit.jupiter.api.* +import treelib.rbTree.RBNode +import treelib.rbTree.RBStateContainer +import treelib.rbTree.RBStruct +import treelib.singleObjects.Markers +import kotlin.test.assertEquals + +@DisplayName("Test: Red-Black Tree Struct") +class RBStructTest { + val treeW = TreeStructWrapper, RBStateContainer, RBStruct>() + var classUnderTest = RBStruct() + + @BeforeEach + fun reInitClassUnderTest() { + classUnderTest = RBStruct() + } + + @Test + fun `base test on creation root`() { + classUnderTest.insert(6) + val root = treeW.getPrivateNode(classUnderTest) + assertAll( + { assertEquals(root?.value, 6) }, + { assertEquals(root?.color, Markers.BLACK) }, + ) + } + + @Test + fun `base test on creation root with left`() { + classUnderTest.insert(6) + classUnderTest.insert(3) + val root = treeW.getPrivateNode(classUnderTest) + assertAll( + { assertEquals(root?.left?.value, 3) }, + { assertEquals(root?.left?.color, Markers.RED) }, + ) + } + + @Test + fun `base test on creation root with right`() { + classUnderTest.insert(6) + classUnderTest.insert(8) + val root = treeW.getPrivateNode(classUnderTest) + assertAll( + { assertEquals(root?.right?.value, 8) }, + { assertEquals(root?.right?.color, Markers.RED) }, + ) + } + + @Test + fun `base test on creation children`() { + classUnderTest.insert(6) + classUnderTest.insert(8) + classUnderTest.insert(3) + val root = treeW.getPrivateNode(classUnderTest) + assertAll( + { assertEquals(root?.right?.value, 8) }, + { assertEquals(root?.left?.value, 3) }, + { assertEquals(root?.right?.color, Markers.RED) }, + { assertEquals(root?.left?.color, Markers.RED) }, + ) + } + + @Test + fun `base test delete root (left & right children)`() { + classUnderTest.insert(6) + classUnderTest.insert(8) + classUnderTest.insert(3) + classUnderTest.delete(6) + val root = treeW.getPrivateNode(classUnderTest) + assertAll( + { assertEquals(root?.value, 8) }, + { assertEquals(root?.color, Markers.BLACK) }, + ) + } + + @Test + fun `base test delete root (right child)`() { + classUnderTest.insert(6) + classUnderTest.insert(8) + classUnderTest.delete(6) + val root = treeW.getPrivateNode(classUnderTest) + assertAll( + { assertEquals(8, root?.value) }, + { assertEquals(Markers.BLACK, root?.color) }, + ) + } + + @Test + fun `base test delete root (left child)`() { + classUnderTest.insert(6) + classUnderTest.insert(3) + classUnderTest.delete(6) + val root = treeW.getPrivateNode(classUnderTest) + assertAll( + { assertEquals(3, root?.value) }, + { assertEquals(Markers.BLACK, root?.color) }, + ) + } + +} \ No newline at end of file diff --git a/lib/src/test/kotlin/treelib/RBStructTree.kt b/lib/src/test/kotlin/treelib/RBStructTree.kt deleted file mode 100644 index c1e040b..0000000 --- a/lib/src/test/kotlin/treelib/RBStructTree.kt +++ /dev/null @@ -1,18 +0,0 @@ -package treelib - -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.DisplayName -import treelib.rbTree.RBNode -import treelib.rbTree.RBStateContainer -import treelib.rbTree.RBStruct - -@DisplayName("Test: Red-Black Tree Struct") -class RBStructTree { - val treeW = TreeStructWrapper, RBStateContainer, RBStruct>() - var classUnderTest = RBStruct() - - @BeforeEach - fun reInitClassUnderTest() { - classUnderTest = RBStruct() - } -} \ No newline at end of file From 5075e51cc02b6e2a0ca61d7f5260b941e918a5ad Mon Sep 17 00:00:00 2001 From: Georgy S Date: Sun, 16 Apr 2023 14:50:38 +0300 Subject: [PATCH 43/84] feat: Add RBAnalyzer class for testing invariant of a RBStruct. --- .../kotlin/treelib/abstractTree/TreeStruct.kt | 6 +- lib/src/test/kotlin/treelib/AVLStructTest.kt | 1 + lib/src/test/kotlin/treelib/BINStructTest.kt | 1 + lib/src/test/kotlin/treelib/RBStructTest.kt | 11 ++- lib/src/test/kotlin/utils/Analyzer.kt | 10 +++ lib/src/test/kotlin/utils/RBAnalyzer.kt | 85 +++++++++++++++++++ .../{treelib => utils}/TreeStructWrapper.kt | 2 +- 7 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 lib/src/test/kotlin/utils/Analyzer.kt create mode 100644 lib/src/test/kotlin/utils/RBAnalyzer.kt rename lib/src/test/kotlin/{treelib => utils}/TreeStructWrapper.kt (98%) diff --git a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt index 422177e..898a40e 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt @@ -6,7 +6,11 @@ import treelib.singleObjects.exceptions.MultithreadingException import treelib.singleObjects.exceptions.NonExistentValueException -abstract class TreeStruct, NodeType : Node, State : StateContainer> { +abstract class TreeStruct< + Pack : Comparable, + NodeType : Node, + State : StateContainer + > { protected abstract var root: NodeType? diff --git a/lib/src/test/kotlin/treelib/AVLStructTest.kt b/lib/src/test/kotlin/treelib/AVLStructTest.kt index 00215f2..23237a8 100644 --- a/lib/src/test/kotlin/treelib/AVLStructTest.kt +++ b/lib/src/test/kotlin/treelib/AVLStructTest.kt @@ -5,6 +5,7 @@ import org.junit.jupiter.api.DisplayName import treelib.avlTree.AVLNode import treelib.avlTree.AVLStateContainer import treelib.avlTree.AVLStruct +import utils.TreeStructWrapper @DisplayName("Test: AVL Struct") class AVLStructTest { diff --git a/lib/src/test/kotlin/treelib/BINStructTest.kt b/lib/src/test/kotlin/treelib/BINStructTest.kt index 194096e..38b5a71 100644 --- a/lib/src/test/kotlin/treelib/BINStructTest.kt +++ b/lib/src/test/kotlin/treelib/BINStructTest.kt @@ -6,6 +6,7 @@ import org.junit.jupiter.api.Test import treelib.binTree.BINNode import treelib.binTree.BINStateContainer import treelib.binTree.BINStruct +import utils.TreeStructWrapper import kotlin.test.assertEquals @DisplayName("Test: Binary Search Tree Struct") diff --git a/lib/src/test/kotlin/treelib/RBStructTest.kt b/lib/src/test/kotlin/treelib/RBStructTest.kt index 807a1d6..da9e9c5 100644 --- a/lib/src/test/kotlin/treelib/RBStructTest.kt +++ b/lib/src/test/kotlin/treelib/RBStructTest.kt @@ -5,12 +5,18 @@ import treelib.rbTree.RBNode import treelib.rbTree.RBStateContainer import treelib.rbTree.RBStruct import treelib.singleObjects.Markers +import utils.RBAnalyzer +import utils.TreeStructWrapper import kotlin.test.assertEquals @DisplayName("Test: Red-Black Tree Struct") class RBStructTest { - val treeW = TreeStructWrapper, RBStateContainer, RBStruct>() - var classUnderTest = RBStruct() + private val treeW = TreeStructWrapper, RBStateContainer, RBStruct>() + private var classUnderTest = RBStruct() + + private fun testAssert(msg: String): Nothing = fail(msg) + + private val analyzer = RBAnalyzer(::testAssert) @BeforeEach fun reInitClassUnderTest() { @@ -99,5 +105,4 @@ class RBStructTest { { assertEquals(Markers.BLACK, root?.color) }, ) } - } \ No newline at end of file diff --git a/lib/src/test/kotlin/utils/Analyzer.kt b/lib/src/test/kotlin/utils/Analyzer.kt new file mode 100644 index 0000000..5a342f9 --- /dev/null +++ b/lib/src/test/kotlin/utils/Analyzer.kt @@ -0,0 +1,10 @@ +package utils + +import treelib.abstractTree.Node + +interface Analyzer< + Pack : Comparable, + NodeType : Node, + > { + fun checkTree(root: NodeType) +} \ No newline at end of file diff --git a/lib/src/test/kotlin/utils/RBAnalyzer.kt b/lib/src/test/kotlin/utils/RBAnalyzer.kt new file mode 100644 index 0000000..1932026 --- /dev/null +++ b/lib/src/test/kotlin/utils/RBAnalyzer.kt @@ -0,0 +1,85 @@ +package utils + +import treelib.rbTree.RBNode +import treelib.singleObjects.Markers +import treelib.singleObjects.exceptions.BugInImplementException + +class RBAnalyzer>( + val assertMethod: (input: String) -> Unit = { + throw BugInImplementException(it) + } +) : Analyzer> { + /** Magic number for error := -9999999 -> just an impossible value **/ + private val errorMagicNumber = -9999999 + + override fun checkTree(root: RBNode) { + if (root.color != Markers.BLACK) assertMethod("The root isn't black!!!") + checkInvariant(root) + } + + private fun checkInvariant(node: RBNode): Int { + var leftBlackCount = 0 + var rightBlackCount = 0 + + if ((node.right == null) && (node.left == null)) { + if (node.color == Markers.RED) return 0 + else return 1 + } + node.right?.let { + when { + it.value == node.value -> { + assertMethod("parent.value == RightChild.value => [${node.value} == ${it.value}]") + return@checkInvariant errorMagicNumber + } + + it.value < node.value -> { + assertMethod("parent.value > RightChild.value => [${node.value} > ${it.value}]") + return@checkInvariant errorMagicNumber + } + + (it.color == Markers.RED) && (node.color == Markers.RED) -> { + assertMethod("parent.color == RED == RightChild.color => [parent - ${node.value} RightChild - ${it.value}]") + return@checkInvariant errorMagicNumber + } + + else -> {} + } + } + + node.left?.let { + when { + it.value == node.value -> { + assertMethod("parent.value == LeftChild.value => [${node.value} == ${it.value}]") + return@checkInvariant errorMagicNumber + } + + it.value > node.value -> { + assertMethod("parent.value < LeftChild.value => [${node.value} < ${it.value}]") + return@checkInvariant errorMagicNumber + } + + (it.color == Markers.RED) && (node.color == Markers.RED) -> { + assertMethod("parent.color == RED == LeftChild.color => [parent - ${node.value} LeftChild - ${it.value}]") + return@checkInvariant errorMagicNumber + } + + else -> {} + } + } + + leftBlackCount = node.left?.let { return@let checkInvariant(it) } ?: 0 + rightBlackCount = node.right?.let { return@let checkInvariant(it) } ?: 0 + + if (leftBlackCount < 0 || rightBlackCount < 0) return errorMagicNumber + + if (leftBlackCount != rightBlackCount) { + assertMethod( + "Number of black nodes does not match in children: parent.value - ${node.value} =>[left - $leftBlackCount] != [right - $rightBlackCount]" + ) + return errorMagicNumber + } + + if(node.color == Markers.BLACK) return leftBlackCount + 1 + else return rightBlackCount + } +} \ No newline at end of file diff --git a/lib/src/test/kotlin/treelib/TreeStructWrapper.kt b/lib/src/test/kotlin/utils/TreeStructWrapper.kt similarity index 98% rename from lib/src/test/kotlin/treelib/TreeStructWrapper.kt rename to lib/src/test/kotlin/utils/TreeStructWrapper.kt index 88870ec..1bdb93e 100644 --- a/lib/src/test/kotlin/treelib/TreeStructWrapper.kt +++ b/lib/src/test/kotlin/utils/TreeStructWrapper.kt @@ -1,4 +1,4 @@ -package treelib +package utils import treelib.abstractTree.Node import treelib.abstractTree.StateContainer From b728bdde1d440435336cd1a7441cb975d715f6b1 Mon Sep 17 00:00:00 2001 From: Georgy S Date: Sun, 16 Apr 2023 15:36:48 +0300 Subject: [PATCH 44/84] refactor: Rename variables in test Classes. --- lib/src/test/kotlin/treelib/AVLStructTest.kt | 4 +- lib/src/test/kotlin/treelib/RBStructTest.kt | 54 ++++++++++---------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/lib/src/test/kotlin/treelib/AVLStructTest.kt b/lib/src/test/kotlin/treelib/AVLStructTest.kt index 23237a8..25ce4cb 100644 --- a/lib/src/test/kotlin/treelib/AVLStructTest.kt +++ b/lib/src/test/kotlin/treelib/AVLStructTest.kt @@ -10,10 +10,10 @@ import utils.TreeStructWrapper @DisplayName("Test: AVL Struct") class AVLStructTest { val treeW = TreeStructWrapper, AVLStateContainer, AVLStruct>() - var classUnderTest = AVLStruct() + var treeStruct = AVLStruct() @BeforeEach fun reInitClassUnderTest() { - classUnderTest = AVLStruct() + treeStruct = AVLStruct() } } \ No newline at end of file diff --git a/lib/src/test/kotlin/treelib/RBStructTest.kt b/lib/src/test/kotlin/treelib/RBStructTest.kt index da9e9c5..5995dd4 100644 --- a/lib/src/test/kotlin/treelib/RBStructTest.kt +++ b/lib/src/test/kotlin/treelib/RBStructTest.kt @@ -12,7 +12,7 @@ import kotlin.test.assertEquals @DisplayName("Test: Red-Black Tree Struct") class RBStructTest { private val treeW = TreeStructWrapper, RBStateContainer, RBStruct>() - private var classUnderTest = RBStruct() + private var treeStruct = RBStruct() private fun testAssert(msg: String): Nothing = fail(msg) @@ -20,13 +20,13 @@ class RBStructTest { @BeforeEach fun reInitClassUnderTest() { - classUnderTest = RBStruct() + treeStruct = RBStruct() } @Test fun `base test on creation root`() { - classUnderTest.insert(6) - val root = treeW.getPrivateNode(classUnderTest) + treeStruct.insert(6) + val root = treeW.getPrivateNode(treeStruct) assertAll( { assertEquals(root?.value, 6) }, { assertEquals(root?.color, Markers.BLACK) }, @@ -35,9 +35,9 @@ class RBStructTest { @Test fun `base test on creation root with left`() { - classUnderTest.insert(6) - classUnderTest.insert(3) - val root = treeW.getPrivateNode(classUnderTest) + treeStruct.insert(6) + treeStruct.insert(3) + val root = treeW.getPrivateNode(treeStruct) assertAll( { assertEquals(root?.left?.value, 3) }, { assertEquals(root?.left?.color, Markers.RED) }, @@ -46,9 +46,9 @@ class RBStructTest { @Test fun `base test on creation root with right`() { - classUnderTest.insert(6) - classUnderTest.insert(8) - val root = treeW.getPrivateNode(classUnderTest) + treeStruct.insert(6) + treeStruct.insert(8) + val root = treeW.getPrivateNode(treeStruct) assertAll( { assertEquals(root?.right?.value, 8) }, { assertEquals(root?.right?.color, Markers.RED) }, @@ -57,10 +57,10 @@ class RBStructTest { @Test fun `base test on creation children`() { - classUnderTest.insert(6) - classUnderTest.insert(8) - classUnderTest.insert(3) - val root = treeW.getPrivateNode(classUnderTest) + treeStruct.insert(6) + treeStruct.insert(8) + treeStruct.insert(3) + val root = treeW.getPrivateNode(treeStruct) assertAll( { assertEquals(root?.right?.value, 8) }, { assertEquals(root?.left?.value, 3) }, @@ -71,11 +71,11 @@ class RBStructTest { @Test fun `base test delete root (left & right children)`() { - classUnderTest.insert(6) - classUnderTest.insert(8) - classUnderTest.insert(3) - classUnderTest.delete(6) - val root = treeW.getPrivateNode(classUnderTest) + treeStruct.insert(6) + treeStruct.insert(8) + treeStruct.insert(3) + treeStruct.delete(6) + val root = treeW.getPrivateNode(treeStruct) assertAll( { assertEquals(root?.value, 8) }, { assertEquals(root?.color, Markers.BLACK) }, @@ -84,10 +84,10 @@ class RBStructTest { @Test fun `base test delete root (right child)`() { - classUnderTest.insert(6) - classUnderTest.insert(8) - classUnderTest.delete(6) - val root = treeW.getPrivateNode(classUnderTest) + treeStruct.insert(6) + treeStruct.insert(8) + treeStruct.delete(6) + val root = treeW.getPrivateNode(treeStruct) assertAll( { assertEquals(8, root?.value) }, { assertEquals(Markers.BLACK, root?.color) }, @@ -96,10 +96,10 @@ class RBStructTest { @Test fun `base test delete root (left child)`() { - classUnderTest.insert(6) - classUnderTest.insert(3) - classUnderTest.delete(6) - val root = treeW.getPrivateNode(classUnderTest) + treeStruct.insert(6) + treeStruct.insert(3) + treeStruct.delete(6) + val root = treeW.getPrivateNode(treeStruct) assertAll( { assertEquals(3, root?.value) }, { assertEquals(Markers.BLACK, root?.color) }, From 10385faae248adabf1e09bdf42b38dedbf761a5e Mon Sep 17 00:00:00 2001 From: Georgy S Date: Sun, 16 Apr 2023 15:37:20 +0300 Subject: [PATCH 45/84] feat: Add BINAnalyzer class for testing invariant of the BINStruct. --- lib/src/test/kotlin/treelib/BINStructTest.kt | 307 ++++++++++--------- lib/src/test/kotlin/utils/BINAnalyzer.kt | 52 ++++ 2 files changed, 215 insertions(+), 144 deletions(-) create mode 100644 lib/src/test/kotlin/utils/BINAnalyzer.kt diff --git a/lib/src/test/kotlin/treelib/BINStructTest.kt b/lib/src/test/kotlin/treelib/BINStructTest.kt index 38b5a71..952a6fa 100644 --- a/lib/src/test/kotlin/treelib/BINStructTest.kt +++ b/lib/src/test/kotlin/treelib/BINStructTest.kt @@ -3,30 +3,36 @@ package treelib import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test +import org.junit.jupiter.api.fail import treelib.binTree.BINNode import treelib.binTree.BINStateContainer import treelib.binTree.BINStruct +import utils.BINAnalyzer import utils.TreeStructWrapper import kotlin.test.assertEquals @DisplayName("Test: Binary Search Tree Struct") class BINStructTest { val treeW = TreeStructWrapper, BINStateContainer, BINStruct>() - var classUnderTest = BINStruct() + var treeStruct = BINStruct() + + private fun testAssert(msg: String): Nothing = fail(msg) + + private val analyzer = BINAnalyzer(::testAssert) @BeforeEach fun reInitClassUnderTest() { - classUnderTest = BINStruct() + treeStruct = BINStruct() } @Test fun `test delete root`() { val num = mutableListOf(5, 3, 7, 1, 9, -1, 4, 2, 0, 6) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(5) - val root = treeW.getPrivateNode(classUnderTest)?.value + treeStruct.delete(5) + val root = treeW.getPrivateNode(treeStruct)?.value assertEquals(expected = 6, actual = root) } @@ -35,20 +41,20 @@ class BINStructTest { fun `test insert`() { val num = mutableListOf(1, 2, 3, 4, 5, 8) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } val additional_num = mutableListOf(1, 2, 3, 5, 7, 8, 11) for (i in additional_num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_2 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_null = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_3 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val node_null1 = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - val node_4 = treeW.getPrivateNode(classUnderTest)?.right?.right?.right?.value + val root = treeW.getPrivateNode(treeStruct)?.value + val node_2 = treeW.getPrivateNode(treeStruct)?.right?.value + val node_null = treeW.getPrivateNode(treeStruct)?.left?.value + val node_3 = treeW.getPrivateNode(treeStruct)?.right?.right?.value + val node_null1 = treeW.getPrivateNode(treeStruct)?.right?.left?.value + val node_4 = treeW.getPrivateNode(treeStruct)?.right?.right?.right?.value assertEquals(expected = root, actual = 1) assertEquals(expected = node_null, actual = null) @@ -62,49 +68,49 @@ class BINStructTest { fun `test find ordinary`() { val num = mutableListOf(2, 3, 1, 4, 5, 10) - assertEquals(expected = classUnderTest.find(2), actual = null) + assertEquals(expected = treeStruct.find(2), actual = null) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - assertEquals(expected = classUnderTest.find(2), actual = 2) + assertEquals(expected = treeStruct.find(2), actual = 2) } @Test fun `test find null`() { val num = mutableListOf(1) - classUnderTest.insert(num[0]) + treeStruct.insert(num[0]) - assertEquals(classUnderTest.find(2), null) + assertEquals(treeStruct.find(2), null) } @Test fun `test find root`() { val num = mutableListOf(1) - classUnderTest.insert(num[0]) + treeStruct.insert(num[0]) - assertEquals(classUnderTest.find(1), 1) + assertEquals(treeStruct.find(1), 1) } @Test fun `test insert and delete root`() { val num = mutableListOf(1, 2) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(1) + treeStruct.delete(1) val additional_num = mutableListOf(1, 2, 11) for (i in additional_num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_1 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_11 = treeW.getPrivateNode(classUnderTest)?.right?.value + val root = treeW.getPrivateNode(treeStruct)?.value + val node_1 = treeW.getPrivateNode(treeStruct)?.left?.value + val node_11 = treeW.getPrivateNode(treeStruct)?.right?.value assertEquals(expected = root, actual = 2) @@ -116,13 +122,13 @@ class BINStructTest { fun `test delete nonexistent value right`() { val num = mutableListOf(5, 6) for (value in num) { - classUnderTest.insert(value) + treeStruct.insert(value) } - classUnderTest.delete(6) + treeStruct.delete(6) - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.value + val root = treeW.getPrivateNode(treeStruct)?.value + val node_null_left = treeW.getPrivateNode(treeStruct)?.left?.value + val node_null_right = treeW.getPrivateNode(treeStruct)?.right?.value assertEquals(expected = null, actual = node_null_left) assertEquals(expected = null, actual = node_null_right) @@ -133,13 +139,13 @@ class BINStructTest { fun `test delete nonexistent value left`() { val num = mutableListOf(6, 5) for (value in num) { - classUnderTest.insert(value) + treeStruct.insert(value) } - classUnderTest.delete(5) + treeStruct.delete(5) - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.value + val root = treeW.getPrivateNode(treeStruct)?.value + val node_null_left = treeW.getPrivateNode(treeStruct)?.left?.value + val node_null_right = treeW.getPrivateNode(treeStruct)?.right?.value assertEquals(expected = null, actual = node_null_left) assertEquals(expected = null, actual = node_null_right) @@ -150,13 +156,13 @@ class BINStructTest { fun `test delete no child root`() { val num = mutableListOf(3) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(3) + treeStruct.delete(3) - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.value - val root = treeW.getPrivateNode(classUnderTest)?.value + val node_null_left = treeW.getPrivateNode(treeStruct)?.left?.value + val node_null_right = treeW.getPrivateNode(treeStruct)?.right?.value + val root = treeW.getPrivateNode(treeStruct)?.value assertEquals(expected = null, actual = node_null_left) assertEquals(expected = null, actual = node_null_right) @@ -167,14 +173,14 @@ class BINStructTest { fun `test delete no child right`() { val num = mutableListOf(3, 10, 15) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(15) + treeStruct.delete(15) - val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val root = treeW.getPrivateNode(classUnderTest)?.value + val node_10 = treeW.getPrivateNode(treeStruct)?.right?.value + val node_null_left = treeW.getPrivateNode(treeStruct)?.right?.left?.value + val node_null_right = treeW.getPrivateNode(treeStruct)?.right?.right?.value + val root = treeW.getPrivateNode(treeStruct)?.value assertEquals(expected = 10, actual = node_10) @@ -187,14 +193,14 @@ class BINStructTest { fun `test delete no child left`() { val num = mutableListOf(15, 10, 3) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(3) + treeStruct.delete(3) - val node_10 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.left?.right?.value - val root = treeW.getPrivateNode(classUnderTest)?.value + val node_10 = treeW.getPrivateNode(treeStruct)?.left?.value + val node_null_left = treeW.getPrivateNode(treeStruct)?.left?.left?.value + val node_null_right = treeW.getPrivateNode(treeStruct)?.left?.right?.value + val root = treeW.getPrivateNode(treeStruct)?.value assertEquals(expected = 10, actual = node_10) @@ -207,14 +213,14 @@ class BINStructTest { fun `test delete one child left`() { val num = mutableListOf(3, 2, 1, 5) for (value in num) { - classUnderTest.insert(value) + treeStruct.insert(value) } - classUnderTest.delete(2) + treeStruct.delete(2) - val node_1 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.left?.right?.value - val root = treeW.getPrivateNode(classUnderTest)?.value + val node_1 = treeW.getPrivateNode(treeStruct)?.left?.value + val node_null_left = treeW.getPrivateNode(treeStruct)?.left?.left?.value + val node_null_right = treeW.getPrivateNode(treeStruct)?.left?.right?.value + val root = treeW.getPrivateNode(treeStruct)?.value assertEquals(expected = 1, actual = node_1) assertEquals(expected = null, actual = node_null_left) @@ -226,14 +232,14 @@ class BINStructTest { fun `test delete one child right`() { val num = mutableListOf(3, 1, 5, 6) for (value in num) { - classUnderTest.insert(value) + treeStruct.insert(value) } - classUnderTest.delete(5) + treeStruct.delete(5) - val node_6 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val root = treeW.getPrivateNode(classUnderTest)?.value + val node_6 = treeW.getPrivateNode(treeStruct)?.right?.value + val node_null_left = treeW.getPrivateNode(treeStruct)?.right?.left?.value + val node_null_right = treeW.getPrivateNode(treeStruct)?.right?.right?.value + val root = treeW.getPrivateNode(treeStruct)?.value assertEquals(expected = 6, actual = node_6) assertEquals(expected = null, actual = node_null_left) @@ -245,13 +251,13 @@ class BINStructTest { fun `test delete one child root`() { val num = mutableListOf(3, 6) for (value in num) { - classUnderTest.insert(value) + treeStruct.insert(value) } - classUnderTest.delete(3) + treeStruct.delete(3) - val node_6 = treeW.getPrivateNode(classUnderTest)?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.right?.value + val node_6 = treeW.getPrivateNode(treeStruct)?.value + val node_null_left = treeW.getPrivateNode(treeStruct)?.left?.value + val node_null_right = treeW.getPrivateNode(treeStruct)?.right?.value assertEquals(expected = 6, actual = node_6) assertEquals(expected = null, actual = node_null_left) @@ -262,17 +268,17 @@ class BINStructTest { fun `test delete one child with family`() { val num = mutableListOf(10, 7, 13, 6, 3, 1, 5, 2, 4, 15) for (value in num) { - classUnderTest.insert(value) + treeStruct.insert(value) } - classUnderTest.delete(7) - val node_6 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_3 = treeW.getPrivateNode(classUnderTest)?.left?.left?.value - val node_null_right = treeW.getPrivateNode(classUnderTest)?.left?.right?.value - val node_1 = treeW.getPrivateNode(classUnderTest)?.left?.left?.left?.value - val node_2 = treeW.getPrivateNode(classUnderTest)?.left?.left?.left?.right?.value - val node_5 = treeW.getPrivateNode(classUnderTest)?.left?.left?.right?.value - val node_4 = treeW.getPrivateNode(classUnderTest)?.left?.left?.right?.left?.value - val root = treeW.getPrivateNode(classUnderTest)?.value + treeStruct.delete(7) + val node_6 = treeW.getPrivateNode(treeStruct)?.left?.value + val node_3 = treeW.getPrivateNode(treeStruct)?.left?.left?.value + val node_null_right = treeW.getPrivateNode(treeStruct)?.left?.right?.value + val node_1 = treeW.getPrivateNode(treeStruct)?.left?.left?.left?.value + val node_2 = treeW.getPrivateNode(treeStruct)?.left?.left?.left?.right?.value + val node_5 = treeW.getPrivateNode(treeStruct)?.left?.left?.right?.value + val node_4 = treeW.getPrivateNode(treeStruct)?.left?.left?.right?.left?.value + val root = treeW.getPrivateNode(treeStruct)?.value assertEquals(expected = 6, actual = node_6) assertEquals(expected = 3, actual = node_3) @@ -288,15 +294,15 @@ class BINStructTest { fun `test delete two child only three element`() { val num = mutableListOf(2, 1, 3) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(2) + treeStruct.delete(2) - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_1 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_null_left1 = treeW.getPrivateNode(classUnderTest)?.left?.left?.value - val node_null_right1 = treeW.getPrivateNode(classUnderTest)?.left?.right?.value - val node_null_right_root = treeW.getPrivateNode(classUnderTest)?.right?.value + val root = treeW.getPrivateNode(treeStruct)?.value + val node_1 = treeW.getPrivateNode(treeStruct)?.left?.value + val node_null_left1 = treeW.getPrivateNode(treeStruct)?.left?.left?.value + val node_null_right1 = treeW.getPrivateNode(treeStruct)?.left?.right?.value + val node_null_right_root = treeW.getPrivateNode(treeStruct)?.right?.value assertEquals(expected = root, actual = 3) assertEquals(expected = node_1, actual = 1) @@ -309,18 +315,18 @@ class BINStructTest { fun `test delete two child without family`() { val num = mutableListOf(10, 7, 5, 4, 6) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(7) + treeStruct.delete(7) - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_5 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_4 = treeW.getPrivateNode(classUnderTest)?.left?.left?.value - val node_6 = treeW.getPrivateNode(classUnderTest)?.left?.right?.value - val node_null_left4 = treeW.getPrivateNode(classUnderTest)?.left?.left?.left?.value - val node_null_right4 = treeW.getPrivateNode(classUnderTest)?.left?.left?.right?.value - val node_null_left6 = treeW.getPrivateNode(classUnderTest)?.left?.right?.left?.value - val node_null_right6 = treeW.getPrivateNode(classUnderTest)?.left?.right?.left?.value + val root = treeW.getPrivateNode(treeStruct)?.value + val node_5 = treeW.getPrivateNode(treeStruct)?.left?.value + val node_4 = treeW.getPrivateNode(treeStruct)?.left?.left?.value + val node_6 = treeW.getPrivateNode(treeStruct)?.left?.right?.value + val node_null_left4 = treeW.getPrivateNode(treeStruct)?.left?.left?.left?.value + val node_null_right4 = treeW.getPrivateNode(treeStruct)?.left?.left?.right?.value + val node_null_left6 = treeW.getPrivateNode(treeStruct)?.left?.right?.left?.value + val node_null_right6 = treeW.getPrivateNode(treeStruct)?.left?.right?.left?.value assertEquals(expected = root, actual = 10) assertEquals(expected = node_5, actual = 5) @@ -336,17 +342,17 @@ class BINStructTest { fun `test two child double delete and delete root`() { val num = mutableListOf(6, 8, 10, 7) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(6) - classUnderTest.delete(7) + treeStruct.delete(6) + treeStruct.delete(7) - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_null_right10 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val node_null_left10 = treeW.getPrivateNode(classUnderTest)?.right?.left?.value + val root = treeW.getPrivateNode(treeStruct)?.value + val node_null_left = treeW.getPrivateNode(treeStruct)?.left?.value + val node_10 = treeW.getPrivateNode(treeStruct)?.right?.value + val node_null_right10 = treeW.getPrivateNode(treeStruct)?.right?.right?.value + val node_null_left10 = treeW.getPrivateNode(treeStruct)?.right?.left?.value assertEquals(expected = root, actual = 8) assertEquals(expected = node_10, actual = 10) @@ -359,18 +365,18 @@ class BINStructTest { fun `test two child delete min element in right tree`() { val num = mutableListOf(6, 8, 10, 7, 12, 9) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(8) + treeStruct.delete(8) - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_null_left = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_9 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_7 = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val node_12 = treeW.getPrivateNode(classUnderTest)?.right?.right?.right?.value - val node_null = treeW.getPrivateNode(classUnderTest)?.right?.right?.left?.value + val root = treeW.getPrivateNode(treeStruct)?.value + val node_null_left = treeW.getPrivateNode(treeStruct)?.left?.value + val node_9 = treeW.getPrivateNode(treeStruct)?.right?.value + val node_7 = treeW.getPrivateNode(treeStruct)?.right?.left?.value + val node_10 = treeW.getPrivateNode(treeStruct)?.right?.right?.value + val node_12 = treeW.getPrivateNode(treeStruct)?.right?.right?.right?.value + val node_null = treeW.getPrivateNode(treeStruct)?.right?.right?.left?.value assertEquals(expected = root, actual = 6) assertEquals(expected = node_9, actual = 9) @@ -385,16 +391,16 @@ class BINStructTest { fun `test two child delete min element in right tree for root`() { val num = mutableListOf(8, 10, 7, 12, 9) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(8) + treeStruct.delete(8) - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_7 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_12 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val node_null = treeW.getPrivateNode(classUnderTest)?.right?.left?.value + val root = treeW.getPrivateNode(treeStruct)?.value + val node_7 = treeW.getPrivateNode(treeStruct)?.left?.value + val node_10 = treeW.getPrivateNode(treeStruct)?.right?.value + val node_12 = treeW.getPrivateNode(treeStruct)?.right?.right?.value + val node_null = treeW.getPrivateNode(treeStruct)?.right?.left?.value assertEquals(expected = root, actual = 9) assertEquals(expected = node_null, actual = null) @@ -407,17 +413,17 @@ class BINStructTest { fun `test two child delete min element in right tree for rightmost element`() { val num = mutableListOf(8, 10, 7, 12, 13, 14) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(8) + treeStruct.delete(8) - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_7 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_12 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_13 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val node_14 = treeW.getPrivateNode(classUnderTest)?.right?.right?.right?.value - val node_null = treeW.getPrivateNode(classUnderTest)?.right?.left?.value + val root = treeW.getPrivateNode(treeStruct)?.value + val node_7 = treeW.getPrivateNode(treeStruct)?.left?.value + val node_12 = treeW.getPrivateNode(treeStruct)?.right?.value + val node_13 = treeW.getPrivateNode(treeStruct)?.right?.right?.value + val node_14 = treeW.getPrivateNode(treeStruct)?.right?.right?.right?.value + val node_null = treeW.getPrivateNode(treeStruct)?.right?.left?.value assertEquals(expected = root, actual = 10) assertEquals(expected = node_null, actual = null) @@ -431,18 +437,18 @@ class BINStructTest { fun `test two child delete min element in right tree but in Tree`() { val num = mutableListOf(8, 12, 15, 13, 10, 11, 9) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(12) + treeStruct.delete(12) - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_13 = treeW.getPrivateNode(classUnderTest)?.right?.value - val node_15 = treeW.getPrivateNode(classUnderTest)?.right?.right?.value - val node_10 = treeW.getPrivateNode(classUnderTest)?.right?.left?.value - val node_11 = treeW.getPrivateNode(classUnderTest)?.right?.left?.right?.value - val node_9 = treeW.getPrivateNode(classUnderTest)?.right?.left?.left?.value - val node_null = treeW.getPrivateNode(classUnderTest)?.right?.right?.left?.value + val root = treeW.getPrivateNode(treeStruct)?.value + val node_13 = treeW.getPrivateNode(treeStruct)?.right?.value + val node_15 = treeW.getPrivateNode(treeStruct)?.right?.right?.value + val node_10 = treeW.getPrivateNode(treeStruct)?.right?.left?.value + val node_11 = treeW.getPrivateNode(treeStruct)?.right?.left?.right?.value + val node_9 = treeW.getPrivateNode(treeStruct)?.right?.left?.left?.value + val node_null = treeW.getPrivateNode(treeStruct)?.right?.right?.left?.value assertEquals(expected = root, actual = 8) assertEquals(expected = node_10, actual = 10) @@ -457,19 +463,32 @@ class BINStructTest { fun `test two child delete min element in right tree for leftmost element`() { val num = mutableListOf(8, 10, 7, 6) for (i in num) { - classUnderTest.insert(i) + treeStruct.insert(i) } - classUnderTest.delete(8) + treeStruct.delete(8) - val root = treeW.getPrivateNode(classUnderTest)?.value - val node_7 = treeW.getPrivateNode(classUnderTest)?.left?.value - val node_6 = treeW.getPrivateNode(classUnderTest)?.left?.left?.value - val node_null = treeW.getPrivateNode(classUnderTest)?.right?.value + val root = treeW.getPrivateNode(treeStruct)?.value + val node_7 = treeW.getPrivateNode(treeStruct)?.left?.value + val node_6 = treeW.getPrivateNode(treeStruct)?.left?.left?.value + val node_null = treeW.getPrivateNode(treeStruct)?.right?.value assertEquals(expected = root, actual = 10) assertEquals(expected = node_null, actual = null) assertEquals(expected = node_7, actual = 7) assertEquals(expected = node_6, actual = 6) } + + @Test + fun `test analyzer`(){ + val num = mutableListOf(6, 8, 10, 7, 12, 9) + for (i in num) { + treeStruct.insert(i) + } + + treeStruct.delete(8) + + val root = treeW.getPrivateNode(treeStruct) + root?.let { analyzer.checkTree(root) } ?: Exception("CHzh") + } } \ No newline at end of file diff --git a/lib/src/test/kotlin/utils/BINAnalyzer.kt b/lib/src/test/kotlin/utils/BINAnalyzer.kt new file mode 100644 index 0000000..0584b70 --- /dev/null +++ b/lib/src/test/kotlin/utils/BINAnalyzer.kt @@ -0,0 +1,52 @@ +package utils + +import treelib.binTree.BINNode +import treelib.singleObjects.exceptions.BugInImplementException + +class BINAnalyzer>( + val assertMethod: (input: String) -> Unit = { + throw BugInImplementException(it) + } +) : Analyzer> { + + override fun checkTree(root: BINNode) { + checkInvariant(root) + } + + private tailrec fun checkInvariant(node: BINNode) { + if ((node.left == null) && (node.right == null)) return + + node.right?.let { + when { + it.value == node.value -> { + assertMethod("parent.value == RightChild.value => [${node.value} == ${it.value}]") + return@checkInvariant + } + + it.value < node.value -> { + assertMethod("parent.value > RightChild.value => [${node.value} > ${it.value}]") + return@checkInvariant + } + + else -> {} + } + } + + node.left?.let { + when { + it.value == node.value -> { + assertMethod("parent.value == LeftChild.value => [${node.value} == ${it.value}]") + return@checkInvariant + } + + it.value > node.value -> { + assertMethod("parent.value < LeftChild.value => [${node.value} < ${it.value}]") + return@checkInvariant + } + + else -> {} + } + } + } + +} \ No newline at end of file From ebf90632ceb510f377db65806c02e44fa4bbbe7e Mon Sep 17 00:00:00 2001 From: Georgy S Date: Sun, 16 Apr 2023 19:07:21 +0300 Subject: [PATCH 46/84] fix: Rewrite interface Analyzer. --- lib/src/test/kotlin/utils/Analyzer.kt | 11 +++++++++-- lib/src/test/kotlin/utils/BINAnalyzer.kt | 14 +++++++------- lib/src/test/kotlin/utils/RBAnalyzer.kt | 20 ++++++++++---------- 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/lib/src/test/kotlin/utils/Analyzer.kt b/lib/src/test/kotlin/utils/Analyzer.kt index 5a342f9..6131d02 100644 --- a/lib/src/test/kotlin/utils/Analyzer.kt +++ b/lib/src/test/kotlin/utils/Analyzer.kt @@ -2,9 +2,16 @@ package utils import treelib.abstractTree.Node -interface Analyzer< +abstract class Analyzer< Pack : Comparable, NodeType : Node, > { - fun checkTree(root: NodeType) + + var message: String = "" + + protected abstract val assertMethod: (input: String) -> Unit + + protected fun wrappedAssertMethod(input: String) = assertMethod("$message$input") + + abstract fun checkTree(root: NodeType) } \ No newline at end of file diff --git a/lib/src/test/kotlin/utils/BINAnalyzer.kt b/lib/src/test/kotlin/utils/BINAnalyzer.kt index 0584b70..43dc5f5 100644 --- a/lib/src/test/kotlin/utils/BINAnalyzer.kt +++ b/lib/src/test/kotlin/utils/BINAnalyzer.kt @@ -4,27 +4,27 @@ import treelib.binTree.BINNode import treelib.singleObjects.exceptions.BugInImplementException class BINAnalyzer>( - val assertMethod: (input: String) -> Unit = { + override val assertMethod: (input: String) -> Unit = { throw BugInImplementException(it) } -) : Analyzer> { +) : Analyzer>() { override fun checkTree(root: BINNode) { checkInvariant(root) } - private tailrec fun checkInvariant(node: BINNode) { + private fun checkInvariant(node: BINNode) { if ((node.left == null) && (node.right == null)) return node.right?.let { when { it.value == node.value -> { - assertMethod("parent.value == RightChild.value => [${node.value} == ${it.value}]") + wrappedAssertMethod("parent.value == RightChild.value => [${node.value} == ${it.value}]") return@checkInvariant } it.value < node.value -> { - assertMethod("parent.value > RightChild.value => [${node.value} > ${it.value}]") + wrappedAssertMethod("parent.value > RightChild.value => [${node.value} > ${it.value}]") return@checkInvariant } @@ -35,12 +35,12 @@ class BINAnalyzer>( node.left?.let { when { it.value == node.value -> { - assertMethod("parent.value == LeftChild.value => [${node.value} == ${it.value}]") + wrappedAssertMethod("parent.value == LeftChild.value => [${node.value} == ${it.value}]") return@checkInvariant } it.value > node.value -> { - assertMethod("parent.value < LeftChild.value => [${node.value} < ${it.value}]") + wrappedAssertMethod("parent.value < LeftChild.value => [${node.value} < ${it.value}]") return@checkInvariant } diff --git a/lib/src/test/kotlin/utils/RBAnalyzer.kt b/lib/src/test/kotlin/utils/RBAnalyzer.kt index 1932026..1b04aff 100644 --- a/lib/src/test/kotlin/utils/RBAnalyzer.kt +++ b/lib/src/test/kotlin/utils/RBAnalyzer.kt @@ -5,15 +5,15 @@ import treelib.singleObjects.Markers import treelib.singleObjects.exceptions.BugInImplementException class RBAnalyzer>( - val assertMethod: (input: String) -> Unit = { + override val assertMethod: (input: String) -> Unit = { throw BugInImplementException(it) } -) : Analyzer> { +) : Analyzer>() { /** Magic number for error := -9999999 -> just an impossible value **/ private val errorMagicNumber = -9999999 override fun checkTree(root: RBNode) { - if (root.color != Markers.BLACK) assertMethod("The root isn't black!!!") + if (root.color != Markers.BLACK) wrappedAssertMethod("The root isn't black!!!") checkInvariant(root) } @@ -28,17 +28,17 @@ class RBAnalyzer>( node.right?.let { when { it.value == node.value -> { - assertMethod("parent.value == RightChild.value => [${node.value} == ${it.value}]") + wrappedAssertMethod("parent.value == RightChild.value => [${node.value} == ${it.value}]") return@checkInvariant errorMagicNumber } it.value < node.value -> { - assertMethod("parent.value > RightChild.value => [${node.value} > ${it.value}]") + wrappedAssertMethod("parent.value > RightChild.value => [${node.value} > ${it.value}]") return@checkInvariant errorMagicNumber } (it.color == Markers.RED) && (node.color == Markers.RED) -> { - assertMethod("parent.color == RED == RightChild.color => [parent - ${node.value} RightChild - ${it.value}]") + wrappedAssertMethod("parent.color == RED == RightChild.color => [parent - ${node.value} RightChild - ${it.value}]") return@checkInvariant errorMagicNumber } @@ -49,17 +49,17 @@ class RBAnalyzer>( node.left?.let { when { it.value == node.value -> { - assertMethod("parent.value == LeftChild.value => [${node.value} == ${it.value}]") + wrappedAssertMethod("parent.value == LeftChild.value => [${node.value} == ${it.value}]") return@checkInvariant errorMagicNumber } it.value > node.value -> { - assertMethod("parent.value < LeftChild.value => [${node.value} < ${it.value}]") + wrappedAssertMethod("parent.value < LeftChild.value => [${node.value} < ${it.value}]") return@checkInvariant errorMagicNumber } (it.color == Markers.RED) && (node.color == Markers.RED) -> { - assertMethod("parent.color == RED == LeftChild.color => [parent - ${node.value} LeftChild - ${it.value}]") + wrappedAssertMethod("parent.color == RED == LeftChild.color => [parent - ${node.value} LeftChild - ${it.value}]") return@checkInvariant errorMagicNumber } @@ -73,7 +73,7 @@ class RBAnalyzer>( if (leftBlackCount < 0 || rightBlackCount < 0) return errorMagicNumber if (leftBlackCount != rightBlackCount) { - assertMethod( + wrappedAssertMethod( "Number of black nodes does not match in children: parent.value - ${node.value} =>[left - $leftBlackCount] != [right - $rightBlackCount]" ) return errorMagicNumber From 47de4ab7ab167ed8c95e59d5a605ab650548d2a3 Mon Sep 17 00:00:00 2001 From: Aleksandr Date: Sun, 16 Apr 2023 22:26:04 +0300 Subject: [PATCH 47/84] feat: added tests for the invariant --- .../kotlin/treelib/abstractTree/TreeStruct.kt | 2 +- lib/src/test/kotlin/treelib/AVLStructTest.kt | 70 ++++++++++++++++++- 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt index 898a40e..ebdb05c 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt @@ -136,7 +136,7 @@ abstract class TreeStruct< if (root == null) return generateStateFind(null) while (true) { - if (obj == currentNode?.value) return generateStateFind(currentNode) + if (obj == currentNode?.value) return generateStateFind(currentNode, currentNode) else { currentNode?.let { if (obj > it.value) currentNode = it.right diff --git a/lib/src/test/kotlin/treelib/AVLStructTest.kt b/lib/src/test/kotlin/treelib/AVLStructTest.kt index 25ce4cb..347892c 100644 --- a/lib/src/test/kotlin/treelib/AVLStructTest.kt +++ b/lib/src/test/kotlin/treelib/AVLStructTest.kt @@ -2,18 +2,84 @@ package treelib import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.fail import treelib.avlTree.AVLNode import treelib.avlTree.AVLStateContainer import treelib.avlTree.AVLStruct +import utils.AVLAnalyzer import utils.TreeStructWrapper @DisplayName("Test: AVL Struct") class AVLStructTest { - val treeW = TreeStructWrapper, AVLStateContainer, AVLStruct>() - var treeStruct = AVLStruct() + private val treeW = TreeStructWrapper, AVLStateContainer, AVLStruct>() + private val treeH = AVLAnalyzer(::testAssert) + private var treeStruct = AVLStruct() + private fun testAssert(msg: String): Nothing = fail(msg) @BeforeEach fun reInitClassUnderTest() { treeStruct = AVLStruct() } + + @Test + fun `test one root`() { + val num = mutableListOf(1) + for (i in num) { + treeStruct.insert(i) + } + treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + } + + @Test + fun `test height 3`() { + val num = mutableListOf(3, 2, 1, 4) + for (i in num) { + treeStruct.insert(i) + } + treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + } + + @Test + fun `test height 3 with delete root`() { + val num = mutableListOf(3, 2, 1, 4) + for (i in num) { + treeStruct.insert(i) + } + treeStruct.delete(2) + treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + } + + @Test + fun `test 100000 arguments`() { + for (i in 1..100000) { + treeStruct.insert(i) + } + treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + } + + @Test + fun `test 100000 arguments and delete`() { + for (i in 1..100000) { + treeStruct.insert(i) + } + treeStruct.delete(5000) + treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + } + + @Test + fun `test two arguments`() { + treeStruct.insert(2) + treeStruct.insert(3) + treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + } + + @Test + fun `test many arguments`() { + val num = mutableListOf(3, 2, 1, 4, 2343, 123213, 3213, 657, 534, 12432, 5676756, 321, 5436546, 5435) + for (i in num) { + treeStruct.insert(i) + } + treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + } } \ No newline at end of file From fb955245def9c6ce60b8215d8a041475ed6b7a6d Mon Sep 17 00:00:00 2001 From: Aleksandr Date: Sun, 16 Apr 2023 22:26:39 +0300 Subject: [PATCH 48/84] feat: Added invariant analyzer. --- lib/src/test/kotlin/utils/AVLAnalyzer.kt | 42 ++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 lib/src/test/kotlin/utils/AVLAnalyzer.kt diff --git a/lib/src/test/kotlin/utils/AVLAnalyzer.kt b/lib/src/test/kotlin/utils/AVLAnalyzer.kt new file mode 100644 index 0000000..b8a9ac4 --- /dev/null +++ b/lib/src/test/kotlin/utils/AVLAnalyzer.kt @@ -0,0 +1,42 @@ +package utils + +import treelib.avlTree.AVLNode +import kotlin.math.abs +import kotlin.math.max + + + +class AVLAnalyzer>(override val assertMethod: (input: String) -> Unit) : Analyzer>() { + private var heightL = 0 + private var heightR = 0 + private var heightMax = 0 + private var mainRight: AVLNode? = null + + override fun checkTree(root: AVLNode) { + mainRight = root.right + descent(root, 0) + heightR = heightMax + if (abs(heightR - heightL) > 1) { + wrappedAssertMethod("the invariant is not observed") + } + } + + private fun descent(node: AVLNode, height: Int) { + heightMax = max(heightMax, height) + val left = node.left + val right = node.right + + if (left != null) { + descent(left, height + 1) + } + + if (right == mainRight && heightR == 0) { + heightL = heightMax + heightMax = 0 + } + + if (right != null) { + descent(right, height + 1) + } + } +} From 07afaa2f25cd8ac8e41895241779ed054c6b2b58 Mon Sep 17 00:00:00 2001 From: Georgy S Date: Mon, 17 Apr 2023 14:07:00 +0300 Subject: [PATCH 49/84] feat: Add fuzzers with partial functionality. --- .../kotlin/utils/fuzzers/AVLStructFuzzer.kt | 7 + .../kotlin/utils/fuzzers/BINStructFuzzer.kt | 16 +++ .../kotlin/utils/fuzzers/RBStructFuzzer.kt | 16 +++ .../kotlin/utils/fuzzers/TreeStructFuzzer.kt | 128 ++++++++++++++++++ 4 files changed, 167 insertions(+) create mode 100644 lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt create mode 100644 lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt create mode 100644 lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt create mode 100644 lib/src/test/kotlin/utils/fuzzers/TreeStructFuzzer.kt diff --git a/lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt b/lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt new file mode 100644 index 0000000..01d49c5 --- /dev/null +++ b/lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt @@ -0,0 +1,7 @@ +package utils.fuzzers + +import treelib.avlTree.AVLNode + +class AVLStructFuzzer>(){ +// TODO +} \ No newline at end of file diff --git a/lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt b/lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt new file mode 100644 index 0000000..5ce3959 --- /dev/null +++ b/lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt @@ -0,0 +1,16 @@ +package utils.fuzzers + +import treelib.binTree.BINNode +import treelib.binTree.BINStateContainer +import treelib.binTree.BINStruct +import utils.BINAnalyzer + +class BINStructFuzzer>( + override val baseInput: Array, + override val assertMethod: (input: String) -> Unit +): TreeStructFuzzer, BINAnalyzer, BINStateContainer, BINStruct>() { + + override fun createTreeStruct(): BINStruct = BINStruct() + + override fun createAnalyzer(): BINAnalyzer = BINAnalyzer(assertMethod) +} \ No newline at end of file diff --git a/lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt b/lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt new file mode 100644 index 0000000..6b59799 --- /dev/null +++ b/lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt @@ -0,0 +1,16 @@ +package utils.fuzzers + +import treelib.rbTree.RBNode +import treelib.rbTree.RBStateContainer +import treelib.rbTree.RBStruct +import utils.RBAnalyzer + +class RBStructFuzzer>( + override val baseInput: Array, + override val assertMethod: (input: String) -> Unit +): TreeStructFuzzer, RBAnalyzer, RBStateContainer, RBStruct>() { + + override fun createTreeStruct(): RBStruct = RBStruct() + + override fun createAnalyzer(): RBAnalyzer = RBAnalyzer(assertMethod) +} \ No newline at end of file diff --git a/lib/src/test/kotlin/utils/fuzzers/TreeStructFuzzer.kt b/lib/src/test/kotlin/utils/fuzzers/TreeStructFuzzer.kt new file mode 100644 index 0000000..a5390b9 --- /dev/null +++ b/lib/src/test/kotlin/utils/fuzzers/TreeStructFuzzer.kt @@ -0,0 +1,128 @@ +package utils.fuzzers + +import treelib.abstractTree.Node +import treelib.abstractTree.StateContainer +import treelib.abstractTree.TreeStruct +import kotlin.random.Random +import utils.Analyzer +import treelib.singleObjects.exceptions.* +import kotlin.random.nextInt +import utils.TreeStructWrapper +import java.io.File +import java.time.Instant + +abstract class TreeStructFuzzer< + Pack : Comparable, + NodeType : Node, + AnalyzerType : Analyzer, + State : StateContainer, + TreeStructType : TreeStruct, + > { + abstract val baseInput: Array + + protected abstract val assertMethod: (input: String) -> Unit + + private var saveFlag: Boolean = false + + private var dirPath: String? = null + + protected val treeWrapper = TreeStructWrapper() + + protected abstract fun createTreeStruct(): TreeStructType + + protected abstract fun createAnalyzer(): AnalyzerType + + /** + * testNumbers - How many times fuzzer would be run + * inputSize - How many elements from baseInput would be used + * **/ + fun fuzzInvariantInsert(testNumbers: Int, inputSize: Int? = null) { + val dataSize: Int = checkCorrectInput(testNumbers, inputSize) + + for (iterations in 0 until testNumbers) { + val treeStruct = createTreeStruct() + println(dataSize) + val testSetIndexes = getInputSetIndexes(dataSize) + val testID = "${Instant.now().toEpochMilli() + iterations}-insert" + val analyzer = createAnalyzer() + + analyzer.message = "$testID: " + + if (saveFlag) saveCurrentTestSet(testID, testSetIndexes) + + try { + for (index in testSetIndexes) { + treeStruct.insert(baseInput[index]) + } + } catch (ex: Exception) { + exceptionsCatch(ex) + } + + val root = treeWrapper.getPrivateNode(treeStruct, "root") + // todo: probably won't work with junit.fail() + root?.let { analyzer.checkTree(it) } ?: assertMethod("The root was not created in the test $testID") + } + } + + fun fuzzInvariantDelete(testNumbers: Int, inputSize: Int? = null) { + val dataSize: Int = checkCorrectInput(testNumbers, inputSize) + TODO("DON'T IMPLEMENTED YET") + } + + fun fuzzInvariant(testNumbers: Int, inputSize: Int? = null) { + val dataSize: Int = checkCorrectInput(testNumbers, inputSize) + TODO("DON'T IMPLEMENTED YET") + } + + private fun checkCorrectInput(testNumbers: Int, inputSize: Int?): Int { + val dataSize: Int + + if (inputSize == null) dataSize = baseInput.size + else dataSize = inputSize + + if (dataSize > baseInput.size) throw BugInImplementException("inputSize > size of the baseInput") + return dataSize + } + + private fun getInputSetIndexes(inputSize: Int): List { + return generateSequence { Random.nextInt(baseInput.indices) }.distinct().take(inputSize).toList() + } + + private fun exceptionsCatch(ex: Exception) { + when (ex) { + is BugInImplementException, + is IllegalBaseNodeException, + is IllegalNodeStateException, + is ImpossibleCaseException, + is MultithreadingException, + is NonExistentValueException, + -> {/*TODO: Implement */ + } + + else -> throw ex + } + } + + fun saveNextTestSets(dirName: String) { + dirPath = dirName + val file = File("./$dirPath") + file.mkdir() + if (file.isDirectory) saveFlag = true + } + + fun dontSaveNextTestSets() { + saveFlag = false + } + + private fun saveCurrentTestSet(testId: String, testSet: List) { + val file = File("./$dirPath/$testId.txt") + file.createNewFile() +// println("./$dirPath/$testId.txt") + for (index in testSet) { +// print("${baseInput[index]} ") + file.appendText("${baseInput[index]} \n") + } +// println() + } + +} \ No newline at end of file From a7b8400edd68056bb81097fd98e26640245ffbb2 Mon Sep 17 00:00:00 2001 From: Georgy S Date: Mon, 17 Apr 2023 14:13:04 +0300 Subject: [PATCH 50/84] fix: Fix bug in AVLStruct.find method. --- .../kotlin/treelib/abstractTree/TreeStruct.kt | 6 +++--- lib/src/test/kotlin/treelib/RBStructTest.kt | 21 +++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt index ebdb05c..d2fe865 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt @@ -133,7 +133,7 @@ abstract class TreeStruct< protected fun findItem(obj: Pack): State { var currentNode = root - if (root == null) return generateStateFind(null) + if (root == null) return generateStateFind(null, null) while (true) { if (obj == currentNode?.value) return generateStateFind(currentNode, currentNode) @@ -141,7 +141,7 @@ abstract class TreeStruct< currentNode?.let { if (obj > it.value) currentNode = it.right else currentNode = it.left - } ?: return generateStateFind(null) + } ?: return generateStateFind(null, null) } } } @@ -166,7 +166,7 @@ abstract class TreeStruct< } updateNode.value = item - return generateStateInsert(null) + return generateStateInsert(null, null) } protected abstract fun generateStateDelete( diff --git a/lib/src/test/kotlin/treelib/RBStructTest.kt b/lib/src/test/kotlin/treelib/RBStructTest.kt index 5995dd4..606ca40 100644 --- a/lib/src/test/kotlin/treelib/RBStructTest.kt +++ b/lib/src/test/kotlin/treelib/RBStructTest.kt @@ -7,6 +7,7 @@ import treelib.rbTree.RBStruct import treelib.singleObjects.Markers import utils.RBAnalyzer import utils.TreeStructWrapper +import utils.fuzzers.RBStructFuzzer import kotlin.test.assertEquals @DisplayName("Test: Red-Black Tree Struct") @@ -30,6 +31,7 @@ class RBStructTest { assertAll( { assertEquals(root?.value, 6) }, { assertEquals(root?.color, Markers.BLACK) }, + { analyzer.checkTree(root!!) } ) } @@ -41,6 +43,7 @@ class RBStructTest { assertAll( { assertEquals(root?.left?.value, 3) }, { assertEquals(root?.left?.color, Markers.RED) }, + { analyzer.checkTree(root!!) } ) } @@ -52,6 +55,7 @@ class RBStructTest { assertAll( { assertEquals(root?.right?.value, 8) }, { assertEquals(root?.right?.color, Markers.RED) }, + { analyzer.checkTree(root!!) } ) } @@ -66,6 +70,7 @@ class RBStructTest { { assertEquals(root?.left?.value, 3) }, { assertEquals(root?.right?.color, Markers.RED) }, { assertEquals(root?.left?.color, Markers.RED) }, + { analyzer.checkTree(root!!) } ) } @@ -79,6 +84,7 @@ class RBStructTest { assertAll( { assertEquals(root?.value, 8) }, { assertEquals(root?.color, Markers.BLACK) }, + { analyzer.checkTree(root!!) } ) } @@ -91,6 +97,7 @@ class RBStructTest { assertAll( { assertEquals(8, root?.value) }, { assertEquals(Markers.BLACK, root?.color) }, + { analyzer.checkTree(root!!) } ) } @@ -103,6 +110,20 @@ class RBStructTest { assertAll( { assertEquals(3, root?.value) }, { assertEquals(Markers.BLACK, root?.color) }, + { analyzer.checkTree(root!!) } ) } + + @Test + fun `fazzer test`() { + val fazzer = RBStructFuzzer(arrayOf(1, 2, 3, 4, 5, 6, 7,8,9,20,100,123,234,556,345677,88765,43,364,23456,2754), ::testAssert) + fazzer.saveNextTestSets("TEST_TEST") + + assertAll( + { + fazzer.fuzzInvariantInsert(15, 10) + } + ) + } + } \ No newline at end of file From 3a5c9fd11933a935a2b4009d39a393d7273da151 Mon Sep 17 00:00:00 2001 From: Georgy S Date: Mon, 17 Apr 2023 20:53:59 +0300 Subject: [PATCH 51/84] fix: Fix bug in TreeStruct.insert() method (test: after insert of two containers). --- lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt index d2fe865..5b96f98 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt @@ -141,7 +141,8 @@ abstract class TreeStruct< currentNode?.let { if (obj > it.value) currentNode = it.right else currentNode = it.left - } ?: return generateStateFind(null, null) + } + if (currentNode == null) return generateStateFind(null, null) } } } @@ -162,7 +163,8 @@ abstract class TreeStruct< linkNewNode(currentNode, parentNode) - return generateStateInsert(currentNode, parentNode) + if (parentNode == null) return generateStateInsert(currentNode, currentNode) + else return generateStateInsert(currentNode, parentNode) } updateNode.value = item From dbe672ac208b97998019e462221fd7aef73f13ef Mon Sep 17 00:00:00 2001 From: Georgy S Date: Mon, 17 Apr 2023 20:56:33 +0300 Subject: [PATCH 52/84] feat: Implement partial functionality of AVLStructFuzzer. --- lib/src/test/kotlin/utils/AVLAnalyzer.kt | 2 -- .../test/kotlin/utils/fuzzers/AVLStructFuzzer.kt | 13 +++++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/src/test/kotlin/utils/AVLAnalyzer.kt b/lib/src/test/kotlin/utils/AVLAnalyzer.kt index b8a9ac4..15e7825 100644 --- a/lib/src/test/kotlin/utils/AVLAnalyzer.kt +++ b/lib/src/test/kotlin/utils/AVLAnalyzer.kt @@ -4,8 +4,6 @@ import treelib.avlTree.AVLNode import kotlin.math.abs import kotlin.math.max - - class AVLAnalyzer>(override val assertMethod: (input: String) -> Unit) : Analyzer>() { private var heightL = 0 private var heightR = 0 diff --git a/lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt b/lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt index 01d49c5..7cbed69 100644 --- a/lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt +++ b/lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt @@ -1,7 +1,16 @@ package utils.fuzzers import treelib.avlTree.AVLNode +import treelib.avlTree.AVLStateContainer +import treelib.avlTree.AVLStruct +import utils.AVLAnalyzer -class AVLStructFuzzer>(){ -// TODO +class AVLStructFuzzer>( + override val baseInput: Array, + override val assertMethod: (input: String) -> Unit +) : TreeStructFuzzer, AVLAnalyzer, AVLStateContainer, AVLStruct>() { + + override fun createTreeStruct(): AVLStruct = AVLStruct() + + override fun createAnalyzer(): AVLAnalyzer = AVLAnalyzer(assertMethod) } \ No newline at end of file From d5de9e37c655fffcdf4164d13065b46ff97bd8ed Mon Sep 17 00:00:00 2001 From: Aleksandr Date: Wed, 19 Apr 2023 01:59:08 +0300 Subject: [PATCH 53/84] feat:add TreeWrapper and BINTreeTest --- lib/build.gradle.kts | 2 + lib/src/test/kotlin/treelib/BINTreeTest.kt | 86 ++++++++++++++++++++++ lib/src/test/kotlin/utils/TreeWrapper.kt | 24 ++++++ 3 files changed, 112 insertions(+) create mode 100644 lib/src/test/kotlin/treelib/BINTreeTest.kt create mode 100644 lib/src/test/kotlin/utils/TreeWrapper.kt diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 3782254..9a5b1b8 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -21,6 +21,7 @@ repositories { } dependencies { + testImplementation("org.junit.jupiter:junit-jupiter-params:5.9.2") testImplementation("io.mockk:mockk:1.13.4") testImplementation("org.jetbrains.kotlin:kotlin-test-junit5:1.8.10") testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.2") @@ -31,6 +32,7 @@ dependencies { implementation("org.xerial", "sqlite-jdbc", sqliteJdbcVersion) } + tasks.test { finalizedBy(tasks.jacocoTestReport) useJUnitPlatform() diff --git a/lib/src/test/kotlin/treelib/BINTreeTest.kt b/lib/src/test/kotlin/treelib/BINTreeTest.kt new file mode 100644 index 0000000..172c545 --- /dev/null +++ b/lib/src/test/kotlin/treelib/BINTreeTest.kt @@ -0,0 +1,86 @@ +package treelib + +import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource +import treelib.binTree.BINNode +import treelib.binTree.BINStateContainer +import treelib.binTree.BINStruct +import treelib.binTree.BINTree +import utils.TreeWrapper +import treelib.singleObjects.Container +import utils.TreeStructWrapper +import kotlin.test.assertEquals + +class BINTreeTest { + private val tree = BINTree() + private val treeW = + TreeWrapper>, BINStateContainer>, BINStruct>, BINTree>() + private val treeSW = + TreeStructWrapper, BINNode>, BINStateContainer>, BINStruct>>() + + +// line - 0.6, branch - 0.5, methods = 0.9 + @ParameterizedTest + @ValueSource(ints = [1, 2, 0, 6, 4]) + fun `test putItem`(str: Int) { + tree.putItem((Pair(str, 1))) + } + + @ParameterizedTest + @ValueSource(strings = ["1 2 3 4", "5 6 7 8 9"]) + fun `test putItems`(str: String) { + val numbers = str.split(" ").map{ it.toInt() }.toMutableList() + val num = mutableListOf>() + for (i in numbers) { + num.add(Pair(i, 1)) + } + tree.putItems(num) + assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, actual = numbers[0]) + assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.right?.value?.key, actual = numbers[1]) + } + + @Test + fun `test getItem`() { + val num = mutableListOf(Pair(1, 1), Pair(2, 1), Pair(5, 1), Pair(4, 1), Pair(3, 5)) + tree.putItems(num) + val temp = tree.getItem(3) + + assertEquals( + expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.right?.right?.left?.left?.value?.value, + actual = temp + ) + } + + @ParameterizedTest + @ValueSource(strings = ["5 2 3", "5 6 7", "5 6 13", "5 6 1", "192 5 6"]) + fun `test putItems and delete`(str: String) { + val numbers = str.split(" ").map{ it.toInt() }.toMutableList() + val num = mutableListOf>() + for (i in numbers) { + num.add(Pair(i, 1)) + } + tree.putItems(num) + tree.deleteItem(numbers[2]) + + assertEquals(expected = tree.getItem(numbers[2]), actual = null) + assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, actual = numbers[0]) + } + + @ParameterizedTest + @ValueSource(strings = ["5 2 3 9", "5 6 7 1", "5 6 13 4", "5 6 1", "192 5 6 222"]) + fun `test putItems and delete root`(str: String) { + val numbers = str.split(" ").map{ it.toInt() }.toMutableList() + val num = mutableListOf>() + for (i in numbers) { + num.add(Pair(i, 1)) + } + tree.putItems(num) + val root = numbers[0] + numbers.sort() + val index = numbers.indexOf(root) + tree.deleteItem(root) + + assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, actual = numbers[index + 1]) + } +} \ No newline at end of file diff --git a/lib/src/test/kotlin/utils/TreeWrapper.kt b/lib/src/test/kotlin/utils/TreeWrapper.kt new file mode 100644 index 0000000..5ca8ea7 --- /dev/null +++ b/lib/src/test/kotlin/utils/TreeWrapper.kt @@ -0,0 +1,24 @@ +package utils + +import treelib.abstractTree.Node +import treelib.abstractTree.StateContainer +import treelib.abstractTree.Tree +import treelib.abstractTree.TreeStruct +import treelib.singleObjects.Container + + +class TreeWrapper < + V : Comparable, + Value, + NodeType: Node, NodeType>, + State: StateContainer, NodeType>, + TStruct: TreeStruct, NodeType, State>, + Wood : Tree> { + fun getPrivateNode(tree: Wood, name: String = "treeStruct"): TStruct { + val treeS = tree.javaClass.getDeclaredField(name) + treeS.isAccessible = true + val treeStruct = treeS.get(tree) + + return treeStruct as TStruct + } +} \ No newline at end of file From 00353821ddec40a94459a5bcaa887ac849b36281 Mon Sep 17 00:00:00 2001 From: Aleksandr Date: Wed, 19 Apr 2023 03:15:39 +0300 Subject: [PATCH 54/84] fix: delete !! --- lib/src/test/kotlin/treelib/AVLStructTest.kt | 35 ++++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/lib/src/test/kotlin/treelib/AVLStructTest.kt b/lib/src/test/kotlin/treelib/AVLStructTest.kt index 347892c..1e522fe 100644 --- a/lib/src/test/kotlin/treelib/AVLStructTest.kt +++ b/lib/src/test/kotlin/treelib/AVLStructTest.kt @@ -28,7 +28,10 @@ class AVLStructTest { for (i in num) { treeStruct.insert(i) } - treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + val node = treeW.getPrivateNode(treeStruct) + if (node != null) { + treeW.getPrivateNode(treeStruct)?.let { treeH.checkTree(it) } + } } @Test @@ -37,7 +40,10 @@ class AVLStructTest { for (i in num) { treeStruct.insert(i) } - treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + val node = treeW.getPrivateNode(treeStruct) + if (node != null) { + treeW.getPrivateNode(treeStruct)?.let { treeH.checkTree(it) } + } } @Test @@ -47,7 +53,10 @@ class AVLStructTest { treeStruct.insert(i) } treeStruct.delete(2) - treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + val node = treeW.getPrivateNode(treeStruct) + if (node != null) { + treeW.getPrivateNode(treeStruct)?.let { treeH.checkTree(it) } + } } @Test @@ -55,7 +64,10 @@ class AVLStructTest { for (i in 1..100000) { treeStruct.insert(i) } - treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + val node = treeW.getPrivateNode(treeStruct) + if (node != null) { + treeW.getPrivateNode(treeStruct)?.let { treeH.checkTree(it) } + } } @Test @@ -64,14 +76,20 @@ class AVLStructTest { treeStruct.insert(i) } treeStruct.delete(5000) - treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + val node = treeW.getPrivateNode(treeStruct) + if (node != null) { + treeW.getPrivateNode(treeStruct)?.let { treeH.checkTree(it) } + } } @Test fun `test two arguments`() { treeStruct.insert(2) treeStruct.insert(3) - treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + val node = treeW.getPrivateNode(treeStruct) + if (node != null) { + treeW.getPrivateNode(treeStruct)?.let { treeH.checkTree(it) } + } } @Test @@ -80,6 +98,9 @@ class AVLStructTest { for (i in num) { treeStruct.insert(i) } - treeH.checkTree(treeW.getPrivateNode(treeStruct)!!) + val node = treeW.getPrivateNode(treeStruct) + if (node != null) { + treeW.getPrivateNode(treeStruct)?.let { treeH.checkTree(it) } + } } } \ No newline at end of file From 1bdaf192bdffc9d06520053b103be8bda9920d8d Mon Sep 17 00:00:00 2001 From: Aleksandr Date: Wed, 19 Apr 2023 03:29:17 +0300 Subject: [PATCH 55/84] feat: AVLTreeTest --- lib/src/test/kotlin/treelib/AVLTreeTest.kt | 76 ++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 lib/src/test/kotlin/treelib/AVLTreeTest.kt diff --git a/lib/src/test/kotlin/treelib/AVLTreeTest.kt b/lib/src/test/kotlin/treelib/AVLTreeTest.kt new file mode 100644 index 0000000..5531d35 --- /dev/null +++ b/lib/src/test/kotlin/treelib/AVLTreeTest.kt @@ -0,0 +1,76 @@ +package treelib + +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource +import treelib.avlTree.AVLNode +import treelib.avlTree.AVLStateContainer +import treelib.avlTree.AVLStruct +import treelib.avlTree.AVLTree +import treelib.singleObjects.Container +import utils.TreeStructWrapper +import utils.TreeWrapper +import kotlin.test.assertEquals + + +class AVLTreeTest { + private val tree = AVLTree() + private val treeW = + TreeWrapper>, AVLStateContainer>, AVLStruct>, AVLTree>() + private val treeSW = + TreeStructWrapper, AVLNode>, AVLStateContainer>, AVLStruct>>() + + + @ParameterizedTest + @ValueSource(strings = ["5 3 8 9", "1 2 3 4", "4 3 5 2", "4 3 2 1", "2 3 1 4"]) + fun `test check root`(str: String) { + val numbers = str.split(" ").map{ it.toInt() }.toMutableList() + val num = mutableListOf>() + for (i in numbers) { + num.add(Pair(i, 1)) + } + tree.putItems(num) + + numbers.sort() + val root = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key + if (root == numbers[1]) { + assertEquals(expected = root, actual = numbers[1]) + } + else { + assertEquals(expected = root, actual = numbers[2]) + } + } + + @ParameterizedTest + @ValueSource(strings = ["1 1000", "1 10000", "1 100000", "1 1000000"]) + fun `test add many args and delete root`(str: String) { + val numbers = str.split(" ").map{ it.toInt() }.toMutableList() + for (i in numbers[0] .. numbers[1]) { + tree.putItem(Pair(i, i)) + } + val root = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key + if (root != null) { + treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.let { tree.deleteItem(it.key) } + } + + when (numbers[1]) { + 1000 -> assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, actual = 513) + 10000 -> assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, actual = 4097) + 100000 -> assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, actual = 65537) + else -> assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, actual = 524289) + } + } + + @ParameterizedTest + @ValueSource(strings = ["5", "0"]) + fun `test delete root one arg`(str: String) { + val numbers = str.split(" ").map{ it.toInt() }.toMutableList() + val num = mutableListOf>() + for (i in numbers) { + num.add(Pair(i, 1)) + } + tree.putItems(num) + tree.deleteItem(numbers[0]) + + assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, actual = null) + } +} \ No newline at end of file From d8ecce0e2a1bcd168715f2d69d49fe1122f9145a Mon Sep 17 00:00:00 2001 From: Aleksandr Date: Wed, 19 Apr 2023 04:26:57 +0300 Subject: [PATCH 56/84] feat: RBTreeTest --- lib/src/test/kotlin/treelib/RBTreeTest.kt | 58 +++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 lib/src/test/kotlin/treelib/RBTreeTest.kt diff --git a/lib/src/test/kotlin/treelib/RBTreeTest.kt b/lib/src/test/kotlin/treelib/RBTreeTest.kt new file mode 100644 index 0000000..5a3ceee --- /dev/null +++ b/lib/src/test/kotlin/treelib/RBTreeTest.kt @@ -0,0 +1,58 @@ +package treelib + +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource +import treelib.rbTree.RBNode +import treelib.rbTree.RBStateContainer +import treelib.rbTree.RBStruct +import treelib.rbTree.RBTree +import treelib.singleObjects.Container +import treelib.singleObjects.Markers +import utils.TreeStructWrapper +import utils.TreeWrapper +import kotlin.test.assertEquals + +class RBTreeTest { + private val tree = RBTree() + private val treeW = + TreeWrapper>, RBStateContainer>, RBStruct>, RBTree>() + private val treeSW = + TreeStructWrapper, RBNode>, RBStateContainer>, RBStruct>>() + + + @ParameterizedTest + @ValueSource(strings = ["1 2 3 4 6 5", "5 3 8 6 9 11 13", "10 11 15 12 17 18"]) + fun `test change color delete root`(str: String) { + val numbers = str.split(" ").map { it.toInt() }.toMutableList() + val num = mutableListOf>() + for (i in numbers) { + num.add(Pair(i, i)) + } + + tree.putItems(num) + + val rootR = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.right?.color + assertEquals(expected = rootR, actual = Markers.RED) + val root = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key + if (root != null) { + treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.let { tree.deleteItem(it.key) } + } + assertEquals(expected = rootR, actual = Markers.RED) + } + + @ParameterizedTest + @ValueSource(strings = ["1 2 5", "1 11 13", "10 11 18"]) + fun `test check color`(str: String) { + val numbers = str.split(" ").map { it.toInt() }.toMutableList() + val num = mutableListOf>() + for (i in numbers) { + num.add(Pair(i, i)) + } + + tree.putItems(num) + + assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.right?.color, actual = Markers.RED) + assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.left?.color, actual = Markers.RED) + assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.color, actual = Markers.BLACK) + } +} \ No newline at end of file From ac0b6426599cd0cdd8e7c0ce9dd734053217339a Mon Sep 17 00:00:00 2001 From: Artem Date: Sat, 15 Apr 2023 15:27:37 +0300 Subject: [PATCH 57/84] fix: Partially change exceptions --- .../kotlin/treelib/avlTree/AVLBalancer.kt | 25 ++++----- .../main/kotlin/treelib/rbTree/RBBalancer.kt | 55 +++++++++---------- 2 files changed, 37 insertions(+), 43 deletions(-) diff --git a/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt b/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt index 703ea69..5f80a87 100644 --- a/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt +++ b/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt @@ -1,11 +1,8 @@ package treelib.avlTree import treelib.abstractTree.balanced.BalancerNoParent -import treelib.singleObjects.exceptions.IllegalBaseNodeException -import treelib.singleObjects.exceptions.IllegalNodeStateException -class AVLBalancer>(private var root: AVLNode?) : - BalancerNoParent, AVLStateContainer>() { +class AVLBalancer>(private var root: AVLNode?): BalancerNoParent, AVLStateContainer>() { private fun updateBalance(node: AVLNode?): Int { return (getHeight(node?.left) - getHeight(node?.right)).toInt() } @@ -16,19 +13,18 @@ class AVLBalancer>(private var root: AVLNode?) : private fun updateHeight(currentNode: AVLNode?) { if (currentNode != null) - currentNode.height = maxOf(getHeight(currentNode.left), getHeight(currentNode.right)) + 1u + currentNode.height = maxOf(getHeight(currentNode.left), getHeight(currentNode.right))+1u } - override fun balance(state: AVLStateContainer): AVLNode { - val node = state.contentNode - root = state.root - return balance(root, node?.value ?: throw IllegalBaseNodeException()) + override fun balance(stateContainer: AVLStateContainer): AVLNode { + val node = stateContainer.contentNode ?: throw IllegalStateException("") // IllegalBaseNodeException("A non-existent node (null) was passed to the method") + root = stateContainer.root + return balance(root, node.value) } - - // В баланс передаем родителя ноды, которую будем удалять + /*** In the method we pass the parent of the removed/inserted node ***/ private fun balance(currentNode: AVLNode?, value: Pack): AVLNode { if (currentNode == null) { - throw IllegalBaseNodeException() + throw NullPointerException() } when { currentNode.value < value -> currentNode.right = balance(currentNode.right, value) @@ -38,7 +34,7 @@ class AVLBalancer>(private var root: AVLNode?) : val balance = updateBalance(currentNode) if (balance == -2) { if (updateBalance(currentNode.right) == 1) { - currentNode.right = currentNode.right?.let { rightRotate(it) } ?: throw IllegalNodeStateException() + currentNode.right = currentNode.right?.let { rightRotate(it) } ?: throw NullPointerException() // IllegalNodeStateException() updateHeight(currentNode.right?.right) } val balancedNode = leftRotate(currentNode) @@ -48,7 +44,7 @@ class AVLBalancer>(private var root: AVLNode?) : } if (balance == 2) { if (updateBalance(currentNode.left) == -1) { - currentNode.left = currentNode.left?.let { leftRotate(it) } ?: throw IllegalNodeStateException() + currentNode.left = currentNode.left?.let { leftRotate(it) } ?: throw NullPointerException() // IllegalNodeStateException("There is no node required by the condition of the algorithm") updateHeight(currentNode.left?.left) } val balanceNode = rightRotate(currentNode) @@ -58,4 +54,5 @@ class AVLBalancer>(private var root: AVLNode?) : } return currentNode } + } diff --git a/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt b/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt index fe73c5b..67e5427 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt @@ -2,9 +2,6 @@ package treelib.rbTree import treelib.abstractTree.balanced.BalancerParent import treelib.singleObjects.Markers -import treelib.singleObjects.exceptions.IllegalBaseNodeException -import treelib.singleObjects.exceptions.IllegalNodeStateException -import treelib.singleObjects.exceptions.ImpossibleCaseException class RBBalancer>(private var root: RBNode?): BalancerParent, RBStateContainer>() { @@ -30,7 +27,7 @@ class RBBalancer>(private var root: RBNode?): Balan private fun getRoot(node: RBNode): RBNode { var currentNode = node while (currentNode.parent != null) - currentNode = currentNode.parent ?: throw IllegalNodeStateException() + currentNode = currentNode.parent ?: throw NullPointerException() root = currentNode root?.color = Markers.BLACK return currentNode @@ -38,12 +35,13 @@ class RBBalancer>(private var root: RBNode?): Balan private fun nodeIsLeaf(node: RBNode?): Boolean { if (node == null) - throw IllegalBaseNodeException() + throw NullPointerException() return node.right == null && node.left == null } - override fun balance(state: RBStateContainer): RBNode { - val node = state.contentNode ?: throw IllegalBaseNodeException() + override fun balance(stateContainer: RBStateContainer): RBNode { + val node = stateContainer.contentNode ?: + throw IllegalStateException() //IllegalBaseNodeException("A non-existent node (null) was passed to the method") val uncle = getUncle(node) when { /** node insertion case **/ @@ -58,14 +56,14 @@ class RBBalancer>(private var root: RBNode?): Balan return getRoot(currentNode) } - var parent = currentNode.parent ?: throw IllegalNodeStateException() + var parent = currentNode.parent ?: throw IllegalStateException() // в данном случае родитель не может быть null when (parent) { parent.parent?.left -> { if (currentNode == parent.right) { leftRotate(parent) currentNode = parent } - parent = currentNode.parent?.parent ?: throw IllegalNodeStateException() + parent = currentNode.parent?.parent ?: throw IllegalStateException() // IllegalNodeStateException() currentNode = rightRotate(parent) currentNode.color = Markers.BLACK currentNode.right?.color = Markers.RED @@ -76,17 +74,17 @@ class RBBalancer>(private var root: RBNode?): Balan rightRotate(parent) currentNode = parent } - parent = currentNode.parent?.parent ?: throw IllegalNodeStateException() + parent = currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() currentNode = leftRotate(parent) currentNode.color = Markers.BLACK currentNode.right?.color = Markers.RED currentNode.left?.color = Markers.RED } - else -> throw IllegalNodeStateException() + else -> throw IllegalStateException() // невозможное условие выполнения } if (currentNode.parent == null) root = currentNode - return root ?: throw IllegalNodeStateException() + return root ?: throw NullPointerException() } /** node removal cases **/ node.color == Markers.RED && (node.right != null || node.left != null) -> @@ -116,12 +114,11 @@ class RBBalancer>(private var root: RBNode?): Balan firstCase(node, null) } - - else -> throw IllegalNodeStateException() + else -> throw IllegalStateException() } } } - throw ImpossibleCaseException() + throw IllegalStateException() } private fun afterInsert(node: RBNode): RBNode { @@ -130,7 +127,7 @@ class RBBalancer>(private var root: RBNode?): Balan val uncle = getUncle(currentNode) if (uncle?.color == Markers.RED) { currentNode.parent?.color = Markers.BLACK - currentNode = currentNode.parent?.parent ?: throw IllegalNodeStateException() + currentNode = currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() currentNode.color = Markers.RED uncle.color = Markers.BLACK } @@ -145,7 +142,7 @@ class RBBalancer>(private var root: RBNode?): Balan /** black node removal case **/ private fun firstCase(parent: RBNode?, node: RBNode?): RBNode { return when { - parent == null && node == null -> throw IllegalBaseNodeException() + parent == null && node == null -> throw NullPointerException() parent != null -> { when (parent.color) { Markers.RED -> secondCase(parent, node) @@ -154,13 +151,13 @@ class RBBalancer>(private var root: RBNode?): Balan getRoot(parent) } - else -> getRoot(node ?: throw IllegalBaseNodeException()) + else -> getRoot(node ?: throw NullPointerException() /* IllegalNodeStateException() */) } } /** parent is red **/ private fun secondCase(parent: RBNode, node: RBNode?) { - var brother = getBrother(parent, node) ?: throw IllegalBaseNodeException() + var brother = getBrother(parent, node) ?: throw NullPointerException() // IllegalNodeStateException() if (brother.color == Markers.RED) throw NullPointerException() @@ -187,7 +184,7 @@ class RBBalancer>(private var root: RBNode?): Balan brother.color = Markers.RED } else { - throw NullPointerException() + throw IllegalStateException() } } parent.right -> @@ -206,17 +203,17 @@ class RBBalancer>(private var root: RBNode?): Balan brother.right?.color = Markers.BLACK } else { - throw NullPointerException() + throw IllegalStateException() } } - else -> throw NullPointerException() + else -> throw IllegalStateException() } } /** parent is black **/ private fun thirdCase(parent: RBNode, node: RBNode?) { - val brother = getBrother(parent, node) ?: throw NullPointerException() + val brother = getBrother(parent, node) ?: throw NullPointerException() // IllegalNodeStateException() when (brother.color) { Markers.RED -> thirdCaseSubFirst(brother, parent) Markers.BLACK -> thirdCaseSubSecond(brother, parent) @@ -228,7 +225,7 @@ class RBBalancer>(private var root: RBNode?): Balan when (brother) { brother.parent?.left -> { - var rightBrotherSon = brother.right ?: throw NullPointerException() + var rightBrotherSon = brother.right ?: throw NullPointerException() // IllegalNodeStateException() if (rightBrotherSon.right?.color != Markers.RED && rightBrotherSon.left?.color != Markers.RED) { rightBrotherSon.color = Markers.RED @@ -244,7 +241,7 @@ class RBBalancer>(private var root: RBNode?): Balan rightBrotherSon.color = Markers.RED leftRotate(rightBrotherSon) - rightBrotherSon = rightBrotherSon.parent ?: throw NullPointerException() + rightBrotherSon = rightBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() rightBrotherSon.color = Markers.BLACK } @@ -260,14 +257,14 @@ class RBBalancer>(private var root: RBNode?): Balan if (leftBrotherSon.right?.color != Markers.RED && leftBrotherSon.left?.color != Markers.RED) { leftBrotherSon.color = Markers.RED brother.color = Markers.BLACK - leftRotate(brother.parent ?: throw NullPointerException()) + leftRotate(brother.parent ?: throw NullPointerException()) // IllegalNodeStateException() return } if (leftBrotherSon.left?.color == Markers.RED) { rightRotate(leftBrotherSon) leftBrotherSon.color = Markers.RED - leftBrotherSon = leftBrotherSon.parent ?: throw NullPointerException() + leftBrotherSon = leftBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() leftBrotherSon.color = Markers.BLACK } @@ -277,7 +274,7 @@ class RBBalancer>(private var root: RBNode?): Balan leftRotate(parent) } } - else -> throw NullPointerException() + else -> throw IllegalStateException() } } @@ -315,7 +312,7 @@ class RBBalancer>(private var root: RBNode?): Balan } } - else -> throw NullPointerException() + else -> throw IllegalStateException() } } From b1b4f1da9c220c83bd561c7b62282b1b22963704 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 17 Apr 2023 14:37:18 +0300 Subject: [PATCH 58/84] feat: Implement neo4j database sketch --- lib/build.gradle.kts | 16 ++- lib/src/main/kotlin/CONTAINER.conf | 3 + lib/src/main/kotlin/DataBase.kt | 172 ++++++++++++++++++++++++ lib/src/main/kotlin/testNeo4j.sh | 15 +++ lib/src/main/kotlin/treelib/DBNodeRB.kt | 14 ++ settings.gradle.kts | 2 +- 6 files changed, 215 insertions(+), 7 deletions(-) create mode 100644 lib/src/main/kotlin/CONTAINER.conf create mode 100644 lib/src/main/kotlin/DataBase.kt create mode 100644 lib/src/main/kotlin/testNeo4j.sh create mode 100644 lib/src/main/kotlin/treelib/DBNodeRB.kt diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 9a5b1b8..0dfd5f1 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -1,5 +1,4 @@ val sqliteJdbcVersion: String by project - plugins { java kotlin("jvm") version "1.8.10" @@ -21,15 +20,20 @@ repositories { } dependencies { - testImplementation("org.junit.jupiter:junit-jupiter-params:5.9.2") - testImplementation("io.mockk:mockk:1.13.4") - testImplementation("org.jetbrains.kotlin:kotlin-test-junit5:1.8.10") - testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.2") api("org.apache.commons:commons-math3:3.6.1") implementation("com.google.guava:guava:31.1-jre") - // JDBC Sqlite + val neo4jCore = "4.0.5" + implementation("org.neo4j", "neo4j-ogm-core", neo4jCore) + implementation("org.neo4j", "neo4j-ogm-bolt-driver", neo4jCore) + + // JDBC Sqlite implementation("org.xerial", "sqlite-jdbc", sqliteJdbcVersion) + + testImplementation("io.mockk:mockk:1.13.4") + testImplementation("org.jetbrains.kotlin:kotlin-test-junit5:1.8.10") + testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.2") + implementation(kotlin("stdlib-jdk8")) } diff --git a/lib/src/main/kotlin/CONTAINER.conf b/lib/src/main/kotlin/CONTAINER.conf new file mode 100644 index 0000000..9b9fb0a --- /dev/null +++ b/lib/src/main/kotlin/CONTAINER.conf @@ -0,0 +1,3 @@ +CONTAINER_NAME=neo4j-db +PASSWORD="test-neo4j" +VOLUMEDIR="/volume" \ No newline at end of file diff --git a/lib/src/main/kotlin/DataBase.kt b/lib/src/main/kotlin/DataBase.kt new file mode 100644 index 0000000..ddc72a3 --- /dev/null +++ b/lib/src/main/kotlin/DataBase.kt @@ -0,0 +1,172 @@ + +import org.neo4j.driver.AuthTokens +import org.neo4j.driver.Driver +import org.neo4j.driver.GraphDatabase +import org.neo4j.driver.exceptions.SessionExpiredException +import treelib.DBNodeRB +import treelib.singleObjects.Markers +import java.io.Closeable +import java.io.IOException +import java.util.* + +class Neo4jRepository: Closeable { + + private var driver: Driver? = null + + fun open(uri: String, username: String, password: String) { + try { + driver = GraphDatabase.driver(uri, AuthTokens.basic(username, password)) + } catch(ex: IllegalArgumentException) { + throw IOException() + } catch(ex: SessionExpiredException) { + throw IOException() + } + + } + + // я наверное смогу получить рут, используя фильтр что-то вроде: на данный узел не указывает ни один другой узел с отношением [left_child] / [right_child] + + fun , V> saveChanges(preOrder: Array>, inOrder: Array>) { + + /*** сюда по ощущениям лучше всего добавлять именно то поддерево исходного дерева, которое было изменено ***/ + val session = driver?.session() ?: throw IOException() + + var inOrderIndex = 0 + var preOrderIndex = 0 + val set = HashSet>() + val stack = LinkedList>() + + while (preOrderIndex in preOrder.indices) { + do { + val currentNode = preOrder[preOrderIndex] + if (preOrderIndex == 0) { + session.executeWrite { tx -> + tx.run( + "MERGE(:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY})", + mutableMapOf( + "nodeValue" to currentNode.value, + "nodeKey" to currentNode.key, + "nodeColor" to currentNode.color.toString(), + "nodeX" to currentNode.x, + "nodeY" to currentNode.y + ) + ) + } + } + if (!stack.isEmpty()) { + if ( set.contains( stack.peek() ) ) { + set.remove(stack.peek()) + val parentNode = stack.pop() + session.executeWrite {tx -> + tx.run("MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + + "MERGE (parent)-[:RIGHT_SON]->(son)", + mutableMapOf( + "parentNodeValue" to parentNode.value, + "parentNodeKey" to parentNode.key, + "parentNodeColor" to parentNode.color.toString(), + "parentNodeX" to parentNode.x, + "parentNodeY" to parentNode.y, + "nodeValue" to currentNode.value, + "nodeKey" to currentNode.key, + "nodeColor" to currentNode.color.toString(), + "nodeX" to currentNode.x, + "nodeY" to currentNode.y + ) + ) + } + } + else { + val parentNode = stack.peek() + session.executeWrite {tx -> + tx.run("MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + + "MERGE (parent)-[:LEFT_SON]->(son)", + mutableMapOf( + "parentNodeValue" to parentNode.value, + "parentNodeKey" to parentNode.key, + "parentNodeColor" to parentNode.color.toString(), + "parentNodeX" to parentNode.x, + "parentNodeY" to parentNode.y, + "nodeValue" to currentNode.value, + "nodeKey" to currentNode.key, + "nodeColor" to currentNode.color.toString(), + "nodeX" to currentNode.x, + "nodeY" to currentNode.y + ) + ) + } + } + } + stack.push(currentNode) + } while (preOrder[preOrderIndex++] != inOrder[inOrderIndex] && preOrderIndex < preOrder.size) + + var currentNode: DBNodeRB? = null + + while(!stack.isEmpty() && inOrderIndex < inOrder.size && stack.peek().key == inOrder[inOrderIndex].key) { + currentNode = stack.pop() + ++inOrderIndex + } + + if (currentNode != null) { + set.add(currentNode) + stack.push(currentNode) + } + + } + + session.close() + } + + // Это скорее всего будем запускать при открытии приложения, нужно будет сразу восстановить дерево + + fun exportRBtree() { + + val session = driver?.session() ?: throw IOException() + var preOrder: List>> = listOf() + var inOrder: List>> = listOf() + + session.executeRead {tx -> + preOrder = tx.run("MATCH (node: Node) " + + "RETURN node.value, node.key, node.color, node.x, node.y ").list() + .map{ DBNodeRB( + value = it.values().get(0).toString(), + key = it.values().get(1).toString(), + color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, + x = it.values().get(3).toString().toDouble(), + y = it.values().get(4).toString().toDouble()) + } + + inOrder = tx.run("MATCH (node: Node) " + + "RETURN node.value, node.key, node.color, node.x, node.y " + + "ORDER BY node.key").list() + .map{ DBNodeRB( + value = it.values().get(0).toString(), + key = it.values().get(1).toString(), + color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, + x = it.values().get(3).toString().toDouble(), + y = it.values().get(4).toString().toDouble()) + } + } + + session.close() + + } + + override fun close() { + driver?.close() + } +} + +// neo4j-admin, backup, restore +/* +у меня есть вершины и ребра между ними, надо уметь сохранять дерево в базе, но как? +вопрос: когда заносить изменения в бд и как это реализовывать? +надо еще подумать над оптимизацией, те чтобы не пересобирать дерево в бд каждый раз, когда мы добавили за сессию всего один узел + +root = tx.run("MATCH (parent: Node)-->(son: Node) " + + "WHERE NOT ()-->(parent) " + + "RETURN parent.value, parent.key, parent.color, parent.x, parent.y").list().map {it.values()}.get(0) + */ diff --git a/lib/src/main/kotlin/testNeo4j.sh b/lib/src/main/kotlin/testNeo4j.sh new file mode 100644 index 0000000..97ad8db --- /dev/null +++ b/lib/src/main/kotlin/testNeo4j.sh @@ -0,0 +1,15 @@ + +BASEDIR=$(realpath "$(dirname "$0")") + +. "${BASEDIR}/CONTAINER.conf" + +docker run \ + --rm \ + --name "CONTAINER_NAME" \ + --volume=$HOME/neo4j/data:/data \ + --volume=$HOME/neo4j/logs:/logs \ + --publish=7474:7474 --publish=7687:7687 \ + --env NEO4J_AUTH=neo4j/"$PASSWORD" \ + neo4j:latest \ + +#docker stop neo4j:latest diff --git a/lib/src/main/kotlin/treelib/DBNodeRB.kt b/lib/src/main/kotlin/treelib/DBNodeRB.kt new file mode 100644 index 0000000..d048930 --- /dev/null +++ b/lib/src/main/kotlin/treelib/DBNodeRB.kt @@ -0,0 +1,14 @@ +package treelib + +import treelib.singleObjects.Markers + + +class DBNodeRB, V>(val value: V, + val key: K, + val color: Markers = Markers.RED, + val x: Double = 0.0, + val y: Double = 0.0) { + + + +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 21643d4..26b0762 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -7,5 +7,5 @@ * in the user manual at https://docs.gradle.org/8.0/userguide/multi_project_builds.html */ -rootProject.name = "TreeLib" +rootProject.name = "treelib" include("lib") From 45159c3e1663edfa45c5f4b70d9e3da0bddb11d7 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 17 Apr 2023 19:32:32 +0300 Subject: [PATCH 59/84] feat: Implement initialize tree from DB --- lib/src/main/kotlin/Controller.kt | 50 +++++++++++++++++ lib/src/main/kotlin/DataBase.kt | 55 +++++++++---------- lib/src/main/kotlin/treelib/DBNodeRB.kt | 9 +-- lib/src/main/kotlin/treelib/Main.kt | 39 +++++++++++++ .../main/kotlin/treelib/abstractTree/Tree.kt | 12 ++-- 5 files changed, 124 insertions(+), 41 deletions(-) create mode 100644 lib/src/main/kotlin/Controller.kt create mode 100644 lib/src/main/kotlin/treelib/Main.kt diff --git a/lib/src/main/kotlin/Controller.kt b/lib/src/main/kotlin/Controller.kt new file mode 100644 index 0000000..cc4e699 --- /dev/null +++ b/lib/src/main/kotlin/Controller.kt @@ -0,0 +1,50 @@ +import treelib.DBNodeRB +import treelib.rbTree.RBStruct +import treelib.rbTree.RBTree +import treelib.singleObjects.Container + +class Controller { + + fun initTree() { + val neo4jDB = Neo4jRepository() + neo4jDB.open("bolt://localhost:7687", "neo4j", "test-neo4j") + /*** orders.first = preOrder, orders.second = inOrder ***/ + val orders: Pair>>>, List>>>> = + neo4jDB.exportRBtree() + + val RBtree = RBStruct>>() + RBtree.restoreTreeFromDatabase(orders.first, orders.second) + } + + fun saveTree() { + val tree = RBTree() + tree.putItem(Pair(25, 1)) + tree.putItem(Pair(15, 1)) + tree.putItem(Pair(50, 1)) + tree.putItem(Pair(10, 1)) + tree.putItem(Pair(22, 1)) + tree.putItem(Pair(35, 1)) + tree.putItem(Pair(70, 1)) + tree.putItem(Pair(4, 1)) + tree.putItem(Pair(12, 1)) + tree.putItem(Pair(18, 1)) + tree.putItem(Pair(24, 1)) + tree.putItem(Pair(31, 1)) + tree.putItem(Pair(44, 1)) + tree.putItem(Pair(66, 1)) + tree.putItem(Pair(90, 1)) + + val neo4jDB = Neo4jRepository() + neo4jDB.open("bolt://localhost:7687", "neo4j", "test-neo4j") + + val preOrder = tree.preOrder().map { DBNodeRB(it.value, it.color) } + val inOrder = tree.inOrder().map { DBNodeRB(it.value, it.color) } + + neo4jDB.saveChanges(preOrder.toTypedArray(), inOrder.toTypedArray()) + + neo4jDB.close() + + + } + +} \ No newline at end of file diff --git a/lib/src/main/kotlin/DataBase.kt b/lib/src/main/kotlin/DataBase.kt index ddc72a3..3e94aac 100644 --- a/lib/src/main/kotlin/DataBase.kt +++ b/lib/src/main/kotlin/DataBase.kt @@ -4,6 +4,7 @@ import org.neo4j.driver.Driver import org.neo4j.driver.GraphDatabase import org.neo4j.driver.exceptions.SessionExpiredException import treelib.DBNodeRB +import treelib.singleObjects.Container import treelib.singleObjects.Markers import java.io.Closeable import java.io.IOException @@ -21,31 +22,29 @@ class Neo4jRepository: Closeable { } catch(ex: SessionExpiredException) { throw IOException() } - } - // я наверное смогу получить рут, используя фильтр что-то вроде: на данный узел не указывает ни один другой узел с отношением [left_child] / [right_child] - - fun , V> saveChanges(preOrder: Array>, inOrder: Array>) { + fun > saveChanges(preOrder: Array>, inOrder: Array>) { /*** сюда по ощущениям лучше всего добавлять именно то поддерево исходного дерева, которое было изменено ***/ val session = driver?.session() ?: throw IOException() var inOrderIndex = 0 var preOrderIndex = 0 - val set = HashSet>() - val stack = LinkedList>() + val set = HashSet>() + val stack = LinkedList>() while (preOrderIndex in preOrder.indices) { do { val currentNode = preOrder[preOrderIndex] + currentNode.value as Container<*, *> if (preOrderIndex == 0) { session.executeWrite { tx -> tx.run( "MERGE(:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY})", mutableMapOf( - "nodeValue" to currentNode.value, - "nodeKey" to currentNode.key, + "nodeValue" to currentNode.value.pair.second, + "nodeKey" to currentNode.value.pair.first, "nodeColor" to currentNode.color.toString(), "nodeX" to currentNode.x, "nodeY" to currentNode.y @@ -57,19 +56,20 @@ class Neo4jRepository: Closeable { if ( set.contains( stack.peek() ) ) { set.remove(stack.peek()) val parentNode = stack.pop() + parentNode.value as Container<*, *> session.executeWrite {tx -> tx.run("MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + "MERGE (parent)-[:RIGHT_SON]->(son)", mutableMapOf( - "parentNodeValue" to parentNode.value, - "parentNodeKey" to parentNode.key, + "parentNodeValue" to parentNode.value.pair.second, + "parentNodeKey" to parentNode.value.pair.first, "parentNodeColor" to parentNode.color.toString(), "parentNodeX" to parentNode.x, "parentNodeY" to parentNode.y, - "nodeValue" to currentNode.value, - "nodeKey" to currentNode.key, + "nodeValue" to currentNode.value.pair.second, + "nodeKey" to currentNode.value.pair.first, "nodeColor" to currentNode.color.toString(), "nodeX" to currentNode.x, "nodeY" to currentNode.y @@ -79,19 +79,20 @@ class Neo4jRepository: Closeable { } else { val parentNode = stack.peek() + parentNode.value as Container<*, *> session.executeWrite {tx -> tx.run("MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + "MERGE (parent)-[:LEFT_SON]->(son)", mutableMapOf( - "parentNodeValue" to parentNode.value, - "parentNodeKey" to parentNode.key, + "parentNodeValue" to parentNode.value.pair.second, + "parentNodeKey" to parentNode.value.pair.first, "parentNodeColor" to parentNode.color.toString(), "parentNodeX" to parentNode.x, "parentNodeY" to parentNode.y, - "nodeValue" to currentNode.value, - "nodeKey" to currentNode.key, + "nodeValue" to currentNode.value.pair.second, + "nodeKey" to currentNode.value.pair.first, "nodeColor" to currentNode.color.toString(), "nodeX" to currentNode.x, "nodeY" to currentNode.y @@ -103,9 +104,9 @@ class Neo4jRepository: Closeable { stack.push(currentNode) } while (preOrder[preOrderIndex++] != inOrder[inOrderIndex] && preOrderIndex < preOrder.size) - var currentNode: DBNodeRB? = null + var currentNode: DBNodeRB? = null - while(!stack.isEmpty() && inOrderIndex < inOrder.size && stack.peek().key == inOrder[inOrderIndex].key) { + while(!stack.isEmpty() && inOrderIndex < inOrder.size && stack.peek().value == inOrder[inOrderIndex].value) { currentNode = stack.pop() ++inOrderIndex } @@ -120,20 +121,17 @@ class Neo4jRepository: Closeable { session.close() } - // Это скорее всего будем запускать при открытии приложения, нужно будет сразу восстановить дерево - - fun exportRBtree() { + fun exportRBtree(): Pair>>>, List>>>>{ val session = driver?.session() ?: throw IOException() - var preOrder: List>> = listOf() - var inOrder: List>> = listOf() + var preOrder: List>>> = listOf() + var inOrder: List>>> = listOf() session.executeRead {tx -> preOrder = tx.run("MATCH (node: Node) " + "RETURN node.value, node.key, node.color, node.x, node.y ").list() .map{ DBNodeRB( - value = it.values().get(0).toString(), - key = it.values().get(1).toString(), + value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, x = it.values().get(3).toString().toDouble(), y = it.values().get(4).toString().toDouble()) @@ -143,16 +141,17 @@ class Neo4jRepository: Closeable { "RETURN node.value, node.key, node.color, node.x, node.y " + "ORDER BY node.key").list() .map{ DBNodeRB( - value = it.values().get(0).toString(), - key = it.values().get(1).toString(), + value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, x = it.values().get(3).toString().toDouble(), y = it.values().get(4).toString().toDouble()) } } - + session.close() + return Pair(preOrder, inOrder) + } override fun close() { diff --git a/lib/src/main/kotlin/treelib/DBNodeRB.kt b/lib/src/main/kotlin/treelib/DBNodeRB.kt index d048930..b28228f 100644 --- a/lib/src/main/kotlin/treelib/DBNodeRB.kt +++ b/lib/src/main/kotlin/treelib/DBNodeRB.kt @@ -3,12 +3,7 @@ package treelib import treelib.singleObjects.Markers -class DBNodeRB, V>(val value: V, - val key: K, +class DBNodeRB>(val value: Pack, val color: Markers = Markers.RED, val x: Double = 0.0, - val y: Double = 0.0) { - - - -} + val y: Double = 0.0) diff --git a/lib/src/main/kotlin/treelib/Main.kt b/lib/src/main/kotlin/treelib/Main.kt new file mode 100644 index 0000000..0aeb3e0 --- /dev/null +++ b/lib/src/main/kotlin/treelib/Main.kt @@ -0,0 +1,39 @@ +package treelib + +import Controller + + +fun main() { + // 25, 15, 10, 4, 12, 22, 18, 24, 50, 35, 31, 44, 70, 66, 90 + // 4, 10, 12, 15, 18, 22, 24, 25, 31, 35, 44, 50, 66, 70, 90 + + /* + + val neo4jRep = Neo4jRepository() + val a1 = DBNodeRB(Container(Pair(1, 25))) + val a2 = DBNodeRB(Container(Pair(1, 15))) + val a3 = DBNodeRB(Container(Pair(1, 10))) + val a4 = DBNodeRB(Container(Pair(1, 4))) + val a5 = DBNodeRB(Container(Pair(1, 12))) + val a6 = DBNodeRB(Container(Pair(1, 22))) + val a7 = DBNodeRB(Container(Pair(1, 18))) + val a8 = DBNodeRB(Container(Pair(1, 24))) + val a9 = DBNodeRB(Container(Pair(1, 50))) + val a10 = DBNodeRB(Container(Pair(1, 35))) + val a11 = DBNodeRB(Container(Pair(1, 31))) + val a12 = DBNodeRB(Container(Pair(1, 44))) + val a13 = DBNodeRB(Container(Pair(1, 70))) + val a14 = DBNodeRB(Container(Pair(1, 66))) + val a15 = DBNodeRB(Container(Pair(1, 90))) + val preArr = arrayOf(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) + val inArr = arrayOf(a4, a3, a5, a2, a7, a6, a8, a1, a11, a10, a12, a9, a14, a13, a15) + neo4jRep.open("bolt://localhost:7687", "neo4j", "test-neo4j") + neo4jRep.saveChanges(preArr, inArr) + */ + val controller = Controller() + controller.saveTree() + + //neo4jRep.exportRBtree() + + //neo4jRep.close() +} \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/abstractTree/Tree.kt b/lib/src/main/kotlin/treelib/abstractTree/Tree.kt index b64cca1..1607caa 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/Tree.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/Tree.kt @@ -33,15 +33,15 @@ abstract class Tree< treeStruct.delete(wrapForFind(key)) } - private fun createPoorList(info: List>): List> { - val returnInfo = mutableListOf>() - for (element in info) returnInfo.add(element.pair) + private fun createPoorList(info: List): List { + val returnInfo = mutableListOf() + for (element in info) returnInfo.add(element) return returnInfo } - fun inOrder(): List> = createPoorList(treeStruct.inOrder()) + fun inOrder(): List = createPoorList(treeStruct.inOrder()) - fun preOrder(): List> = createPoorList(treeStruct.preOrder()) + fun preOrder(): List = createPoorList(treeStruct.preOrder()) - fun postOrder(): List> = createPoorList(treeStruct.postOrder()) + fun postOrder(): List = createPoorList(treeStruct.postOrder()) } From 5f07feaee390805c32f9750f4225e3721ce2c4e7 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 17 Apr 2023 20:21:27 +0300 Subject: [PATCH 60/84] fix: Fix adding to database (neo4j) --- lib/src/main/kotlin/DataBase.kt | 82 ++++++++++-------- lib/src/main/kotlin/treelib/DBNodeRB.kt | 10 ++- .../kotlin/treelib/avlTree/AVLBalancer.kt | 15 ++-- .../main/kotlin/treelib/rbTree/RBBalancer.kt | 85 ++++++++++--------- .../main/kotlin/treelib/rbTree/RBStruct.kt | 63 ++++++++++++-- 5 files changed, 161 insertions(+), 94 deletions(-) diff --git a/lib/src/main/kotlin/DataBase.kt b/lib/src/main/kotlin/DataBase.kt index 3e94aac..e7ca4c6 100644 --- a/lib/src/main/kotlin/DataBase.kt +++ b/lib/src/main/kotlin/DataBase.kt @@ -1,4 +1,3 @@ - import org.neo4j.driver.AuthTokens import org.neo4j.driver.Driver import org.neo4j.driver.GraphDatabase @@ -10,21 +9,21 @@ import java.io.Closeable import java.io.IOException import java.util.* -class Neo4jRepository: Closeable { +class Neo4jRepository : Closeable { private var driver: Driver? = null fun open(uri: String, username: String, password: String) { try { driver = GraphDatabase.driver(uri, AuthTokens.basic(username, password)) - } catch(ex: IllegalArgumentException) { - throw IOException() - } catch(ex: SessionExpiredException) { + } catch (ex: IllegalArgumentException) { + throw IOException() + } catch (ex: SessionExpiredException) { throw IOException() } } - fun > saveChanges(preOrder: Array>, inOrder: Array>) { + fun > saveChanges(preOrder: Array>, inOrder: Array>) { /*** сюда по ощущениям лучше всего добавлять именно то поддерево исходного дерева, которое было изменено ***/ val session = driver?.session() ?: throw IOException() @@ -53,15 +52,16 @@ class Neo4jRepository: Closeable { } } if (!stack.isEmpty()) { - if ( set.contains( stack.peek() ) ) { + if (set.contains(stack.peek())) { set.remove(stack.peek()) val parentNode = stack.pop() parentNode.value as Container<*, *> - session.executeWrite {tx -> - tx.run("MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + - "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + - "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + - "MERGE (parent)-[:RIGHT_SON]->(son)", + session.executeWrite { tx -> + tx.run( + "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + + "MERGE (parent)-[:RIGHT_SON]->(son)", mutableMapOf( "parentNodeValue" to parentNode.value.pair.second, "parentNodeKey" to parentNode.value.pair.first, @@ -76,15 +76,15 @@ class Neo4jRepository: Closeable { ) ) } - } - else { + } else { val parentNode = stack.peek() parentNode.value as Container<*, *> - session.executeWrite {tx -> - tx.run("MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + - "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + - "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + - "MERGE (parent)-[:LEFT_SON]->(son)", + session.executeWrite { tx -> + tx.run( + "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + + "MERGE (parent)-[:LEFT_SON]->(son)", mutableMapOf( "parentNodeValue" to parentNode.value.pair.second, "parentNodeKey" to parentNode.value.pair.first, @@ -106,7 +106,7 @@ class Neo4jRepository: Closeable { var currentNode: DBNodeRB? = null - while(!stack.isEmpty() && inOrderIndex < inOrder.size && stack.peek().value == inOrder[inOrderIndex].value) { + while (!stack.isEmpty() && inOrderIndex < inOrder.size && stack.peek().value == inOrder[inOrderIndex].value) { currentNode = stack.pop() ++inOrderIndex } @@ -121,30 +121,38 @@ class Neo4jRepository: Closeable { session.close() } - fun exportRBtree(): Pair>>>, List>>>>{ + fun exportRBtree(): Pair>>>, List>>>> { val session = driver?.session() ?: throw IOException() var preOrder: List>>> = listOf() var inOrder: List>>> = listOf() - session.executeRead {tx -> - preOrder = tx.run("MATCH (node: Node) " + - "RETURN node.value, node.key, node.color, node.x, node.y ").list() - .map{ DBNodeRB( - value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), - color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, - x = it.values().get(3).toString().toDouble(), - y = it.values().get(4).toString().toDouble()) + session.executeRead { tx -> + preOrder = tx.run( + "MATCH (node: Node) " + + "RETURN node.value, node.key, node.color, node.x, node.y " + ).list() + .map { + DBNodeRB( + value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), + color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, + x = it.values().get(3).toString().toDouble(), + y = it.values().get(4).toString().toDouble() + ) } - inOrder = tx.run("MATCH (node: Node) " + - "RETURN node.value, node.key, node.color, node.x, node.y " + - "ORDER BY node.key").list() - .map{ DBNodeRB( - value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), - color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, - x = it.values().get(3).toString().toDouble(), - y = it.values().get(4).toString().toDouble()) + inOrder = tx.run( + "MATCH (node: Node) " + + "RETURN node.value, node.key, node.color, node.x, node.y " + + "ORDER BY node.key" + ).list() + .map { + DBNodeRB( + value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), + color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, + x = it.values().get(3).toString().toDouble(), + y = it.values().get(4).toString().toDouble() + ) } } diff --git a/lib/src/main/kotlin/treelib/DBNodeRB.kt b/lib/src/main/kotlin/treelib/DBNodeRB.kt index b28228f..cf067e1 100644 --- a/lib/src/main/kotlin/treelib/DBNodeRB.kt +++ b/lib/src/main/kotlin/treelib/DBNodeRB.kt @@ -3,7 +3,9 @@ package treelib import treelib.singleObjects.Markers -class DBNodeRB>(val value: Pack, - val color: Markers = Markers.RED, - val x: Double = 0.0, - val y: Double = 0.0) +class DBNodeRB>( + val value: Pack, + val color: Markers = Markers.RED, + val x: Double = 0.0, + val y: Double = 0.0 +) diff --git a/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt b/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt index 5f80a87..1a3afb9 100644 --- a/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt +++ b/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt @@ -2,7 +2,8 @@ package treelib.avlTree import treelib.abstractTree.balanced.BalancerNoParent -class AVLBalancer>(private var root: AVLNode?): BalancerNoParent, AVLStateContainer>() { +class AVLBalancer>(private var root: AVLNode?) : + BalancerNoParent, AVLStateContainer>() { private fun updateBalance(node: AVLNode?): Int { return (getHeight(node?.left) - getHeight(node?.right)).toInt() } @@ -13,14 +14,16 @@ class AVLBalancer>(private var root: AVLNode?): Bal private fun updateHeight(currentNode: AVLNode?) { if (currentNode != null) - currentNode.height = maxOf(getHeight(currentNode.left), getHeight(currentNode.right))+1u + currentNode.height = maxOf(getHeight(currentNode.left), getHeight(currentNode.right)) + 1u } override fun balance(stateContainer: AVLStateContainer): AVLNode { - val node = stateContainer.contentNode ?: throw IllegalStateException("") // IllegalBaseNodeException("A non-existent node (null) was passed to the method") + val node = stateContainer.contentNode + ?: throw IllegalStateException("") // IllegalBaseNodeException("A non-existent node (null) was passed to the method") root = stateContainer.root return balance(root, node.value) } + /*** In the method we pass the parent of the removed/inserted node ***/ private fun balance(currentNode: AVLNode?, value: Pack): AVLNode { if (currentNode == null) { @@ -34,7 +37,8 @@ class AVLBalancer>(private var root: AVLNode?): Bal val balance = updateBalance(currentNode) if (balance == -2) { if (updateBalance(currentNode.right) == 1) { - currentNode.right = currentNode.right?.let { rightRotate(it) } ?: throw NullPointerException() // IllegalNodeStateException() + currentNode.right = currentNode.right?.let { rightRotate(it) } + ?: throw NullPointerException() // IllegalNodeStateException() updateHeight(currentNode.right?.right) } val balancedNode = leftRotate(currentNode) @@ -44,7 +48,8 @@ class AVLBalancer>(private var root: AVLNode?): Bal } if (balance == 2) { if (updateBalance(currentNode.left) == -1) { - currentNode.left = currentNode.left?.let { leftRotate(it) } ?: throw NullPointerException() // IllegalNodeStateException("There is no node required by the condition of the algorithm") + currentNode.left = currentNode.left?.let { leftRotate(it) } + ?: throw NullPointerException() // IllegalNodeStateException("There is no node required by the condition of the algorithm") updateHeight(currentNode.left?.left) } val balanceNode = rightRotate(currentNode) diff --git a/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt b/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt index 67e5427..211e007 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt @@ -3,7 +3,8 @@ package treelib.rbTree import treelib.abstractTree.balanced.BalancerParent import treelib.singleObjects.Markers -class RBBalancer>(private var root: RBNode?): BalancerParent, RBStateContainer>() { +class RBBalancer>(private var root: RBNode?) : + BalancerParent, RBStateContainer>() { init { root?.color = Markers.BLACK @@ -39,14 +40,13 @@ class RBBalancer>(private var root: RBNode?): Balan return node.right == null && node.left == null } - override fun balance(stateContainer: RBStateContainer): RBNode { - val node = stateContainer.contentNode ?: - throw IllegalStateException() //IllegalBaseNodeException("A non-existent node (null) was passed to the method") + override fun balance(stateContainer: RBStateContainer): RBNode { + val node = stateContainer.contentNode + ?: throw IllegalStateException() //IllegalBaseNodeException("A non-existent node (null) was passed to the method") val uncle = getUncle(node) when { /** node insertion case **/ - node.color == Markers.RED && node.right == null && node.left == null-> - { + node.color == Markers.RED && node.right == null && node.left == null -> { var currentNode = node if (currentNode.parent?.color == Markers.RED && uncle?.color == Markers.RED) { @@ -56,30 +56,35 @@ class RBBalancer>(private var root: RBNode?): Balan return getRoot(currentNode) } - var parent = currentNode.parent ?: throw IllegalStateException() // в данном случае родитель не может быть null + var parent = + currentNode.parent ?: throw IllegalStateException() // в данном случае родитель не может быть null when (parent) { parent.parent?.left -> { if (currentNode == parent.right) { leftRotate(parent) currentNode = parent } - parent = currentNode.parent?.parent ?: throw IllegalStateException() // IllegalNodeStateException() + parent = + currentNode.parent?.parent ?: throw IllegalStateException() // IllegalNodeStateException() currentNode = rightRotate(parent) currentNode.color = Markers.BLACK currentNode.right?.color = Markers.RED currentNode.left?.color = Markers.RED } + parent.parent?.right -> { if (currentNode == parent.left) { rightRotate(parent) currentNode = parent } - parent = currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() + parent = + currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() currentNode = leftRotate(parent) currentNode.color = Markers.BLACK currentNode.right?.color = Markers.RED currentNode.left?.color = Markers.RED } + else -> throw IllegalStateException() // невозможное условие выполнения } if (currentNode.parent == null) @@ -87,21 +92,21 @@ class RBBalancer>(private var root: RBNode?): Balan return root ?: throw NullPointerException() } /** node removal cases **/ - node.color == Markers.RED && (node.right != null || node.left != null) -> - { + node.color == Markers.RED && (node.right != null || node.left != null) -> { when { /** black leaf removal case **/ node.right?.color == Markers.BLACK -> { return firstCase(node, node.left) } + node.left?.color == Markers.BLACK -> { return firstCase(node, node.right) } } } - node.color == Markers.BLACK -> - { + + node.color == Markers.BLACK -> { return when { /** red leaf removal case **/ (node.left == null && node.right == null) || @@ -110,10 +115,11 @@ class RBBalancer>(private var root: RBNode?): Balan getRoot(node) } /** black leaf removal case **/ - node.left == null || node.right == null-> { + node.left == null || node.right == null -> { firstCase(node, null) } + else -> throw IllegalStateException() } } @@ -130,8 +136,7 @@ class RBBalancer>(private var root: RBNode?): Balan currentNode = currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() currentNode.color = Markers.RED uncle.color = Markers.BLACK - } - else if(uncle != null){ + } else if (uncle != null) { return currentNode } } @@ -168,45 +173,41 @@ class RBBalancer>(private var root: RBNode?): Balan } when (node) { - parent.left -> - { + parent.left -> { if (brother.right?.color == Markers.RED) { leftRotate(parent) brother.left?.color = Markers.RED brother.right?.color = Markers.RED brother.color = Markers.BLACK - } - else if (brother.left?.color == Markers.RED) { + } else if (brother.left?.color == Markers.RED) { brother = rightRotate(brother) leftRotate(parent) brother.left?.color = Markers.BLACK brother.left?.color = Markers.BLACK brother.color = Markers.RED - } - else { + } else { throw IllegalStateException() } } - parent.right -> - { + + parent.right -> { if (brother.left?.color == Markers.RED) { rightRotate(parent) brother.color = Markers.BLACK brother.left?.color = Markers.RED brother.right?.color = Markers.RED - } - else if (brother.right?.color == Markers.RED) { + } else if (brother.right?.color == Markers.RED) { brother = leftRotate(brother) rightRotate(parent) brother.color = Markers.RED brother.left?.color = Markers.BLACK brother.right?.color = Markers.BLACK - } - else { + } else { throw IllegalStateException() } } + else -> throw IllegalStateException() } } @@ -223,8 +224,7 @@ class RBBalancer>(private var root: RBNode?): Balan /** black parent and red brother **/ private fun thirdCaseSubFirst(brother: RBNode, parent: RBNode) { when (brother) { - brother.parent?.left -> - { + brother.parent?.left -> { var rightBrotherSon = brother.right ?: throw NullPointerException() // IllegalNodeStateException() if (rightBrotherSon.right?.color != Markers.RED && rightBrotherSon.left?.color != Markers.RED) { @@ -241,7 +241,8 @@ class RBBalancer>(private var root: RBNode?): Balan rightBrotherSon.color = Markers.RED leftRotate(rightBrotherSon) - rightBrotherSon = rightBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() + rightBrotherSon = + rightBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() rightBrotherSon.color = Markers.BLACK } @@ -251,8 +252,8 @@ class RBBalancer>(private var root: RBNode?): Balan rightRotate(parent) } } - brother.parent?.right -> - { + + brother.parent?.right -> { var leftBrotherSon = brother.left ?: throw NullPointerException() if (leftBrotherSon.right?.color != Markers.RED && leftBrotherSon.left?.color != Markers.RED) { leftBrotherSon.color = Markers.RED @@ -264,7 +265,8 @@ class RBBalancer>(private var root: RBNode?): Balan if (leftBrotherSon.left?.color == Markers.RED) { rightRotate(leftBrotherSon) leftBrotherSon.color = Markers.RED - leftBrotherSon = leftBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() + leftBrotherSon = + leftBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() leftBrotherSon.color = Markers.BLACK } @@ -274,6 +276,7 @@ class RBBalancer>(private var root: RBNode?): Balan leftRotate(parent) } } + else -> throw IllegalStateException() } } @@ -289,29 +292,27 @@ class RBBalancer>(private var root: RBNode?): Balan return } when { - brother.left?.color == Markers.RED -> - { + brother.left?.color == Markers.RED -> { brother.left?.color = Markers.BLACK if (brother == parent.left) { rightRotate(parent) - } - else { + } else { rightRotate(brother) leftRotate(parent) } } - brother.right?.color == Markers.RED -> - { + + brother.right?.color == Markers.RED -> { brother.right?.color = Markers.BLACK if (brother == parent.right) { leftRotate(parent) - } - else { + } else { leftRotate(brother) rightRotate(parent) } } + else -> throw IllegalStateException() } } diff --git a/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt b/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt index 67ffc27..ee6a216 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt @@ -1,9 +1,11 @@ package treelib.rbTree +import treelib.DBNodeRB import treelib.abstractTree.balanced.BalancedTreeStruct import treelib.singleObjects.Markers import treelib.singleObjects.exceptions.ImpossibleCaseException import treelib.singleObjects.exceptions.MultithreadingException +import java.util.* class RBStruct> : BalancedTreeStruct, RBStateContainer, RBBalancer>() { @@ -15,17 +17,17 @@ class RBStruct> : override fun generateStateDelete( deletedNode: RBNode?, contentNode: RBNode?, - ): RBStateContainer = RBStateContainer(contentNode) + ): RBStateContainer = RBStateContainer(contentNode) override fun generateStateInsert( insertNode: RBNode?, contentNode: RBNode?, - ): RBStateContainer = RBStateContainer(insertNode) + ): RBStateContainer = RBStateContainer(insertNode) override fun generateStateFind( findNode: RBNode?, contentNode: RBNode?, - ): RBStateContainer = RBStateContainer(findNode) + ): RBStateContainer = RBStateContainer(findNode) override fun connectUnlinkedSubTreeWithParent( node: RBNode, @@ -39,11 +41,12 @@ class RBStruct> : (node.value < parent.value) -> { parent.left = childForLink } + (node.value > parent.value) -> { parent.right = childForLink } } - if (childForLink != null){ + if (childForLink != null) { childForLink.parent = parent } } else root?.let { @@ -62,12 +65,60 @@ class RBStruct> : root?.let { it.color = Markers.BLACK } ?: throw MultithreadingException(ImpossibleCaseException()) - } - else { + } else { if (node.value > parent.value) parent.right = node else parent.left = node node.parent = parent } return node } + + fun restoreTreeFromDatabase(preOrder: List>, inOrder: List>) { + var inOrderIndex = 0 + var preOrderIndex = 0 + val set = HashSet>() + val stack = LinkedList>() + + while (preOrderIndex in preOrder.indices) { + var currentNode: RBNode? + var drawNode: DBNodeRB + + do { + drawNode = preOrder[preOrderIndex] + currentNode = createRBNode(drawNode) + if (root == null) { + root = currentNode + } + if (!stack.isEmpty()) { + if (set.contains(stack.peek())) { + set.remove(stack.peek()) + stack.pop().right = currentNode + } else { + stack.peek().left = currentNode + // связь с ролитилем + } + } + stack.push(currentNode) + } while (preOrder[preOrderIndex++] != inOrder[inOrderIndex] && preOrderIndex < preOrder.size) + + currentNode = null + while (stack.isEmpty() && inOrderIndex < inOrder.size && + stack.peek().value == inOrder[inOrderIndex].value + ) { + currentNode = stack.pop() + ++inOrderIndex + } + + if (currentNode != null) { + set.add(currentNode) + stack.push(currentNode) + } + } + + } + + private fun createRBNode(drawNode: DBNodeRB): RBNode { + val node = RBNode(value = drawNode.value, color = drawNode.color) + return node + } } From 129661be4f88797a851aad0e7d226785881e40c9 Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 18 Apr 2023 21:33:22 +0300 Subject: [PATCH 61/84] fix: Fix database interaction --- lib/src/main/kotlin/Controller.kt | 35 +--- lib/src/main/kotlin/DataBase.kt | 186 ++++++++++-------- lib/src/main/kotlin/initNeo4j.sh | 0 lib/src/main/kotlin/loadNeo4j.sh | 8 + lib/src/main/kotlin/testNeo4j.sh | 13 +- lib/src/main/kotlin/treelib/Main.kt | 29 ++- .../main/kotlin/treelib/abstractTree/Tree.kt | 37 ++-- .../kotlin/treelib/abstractTree/TreeStruct.kt | 39 ++-- .../kotlin/treelib/abstractTree/Vertex.kt | 5 + .../balanced/BalancedTreeStruct.kt | 4 +- .../main/kotlin/treelib/avlTree/AVLStruct.kt | 6 +- .../main/kotlin/treelib/avlTree/AVLTree.kt | 10 +- .../main/kotlin/treelib/avlTree/AVLVertex.kt | 8 + .../main/kotlin/treelib/binTree/BINStruct.kt | 6 +- .../main/kotlin/treelib/binTree/BINTree.kt | 10 +- .../main/kotlin/treelib/binTree/BINVertex.kt | 5 + .../kotlin/treelib/rbTree/DrawRBVertex.kt | 10 + .../main/kotlin/treelib/rbTree/RBBalancer.kt | 24 +-- .../main/kotlin/treelib/rbTree/RBStruct.kt | 13 +- lib/src/main/kotlin/treelib/rbTree/RBTree.kt | 10 +- .../main/kotlin/treelib/rbTree/RBVertex.kt | 9 + 21 files changed, 292 insertions(+), 175 deletions(-) create mode 100644 lib/src/main/kotlin/initNeo4j.sh create mode 100644 lib/src/main/kotlin/loadNeo4j.sh create mode 100644 lib/src/main/kotlin/treelib/abstractTree/Vertex.kt create mode 100644 lib/src/main/kotlin/treelib/avlTree/AVLVertex.kt create mode 100644 lib/src/main/kotlin/treelib/binTree/BINVertex.kt create mode 100644 lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt create mode 100644 lib/src/main/kotlin/treelib/rbTree/RBVertex.kt diff --git a/lib/src/main/kotlin/Controller.kt b/lib/src/main/kotlin/Controller.kt index cc4e699..a59a3b0 100644 --- a/lib/src/main/kotlin/Controller.kt +++ b/lib/src/main/kotlin/Controller.kt @@ -1,6 +1,6 @@ -import treelib.DBNodeRB + +import treelib.rbTree.DrawRBVertex import treelib.rbTree.RBStruct -import treelib.rbTree.RBTree import treelib.singleObjects.Container class Controller { @@ -8,43 +8,28 @@ class Controller { fun initTree() { val neo4jDB = Neo4jRepository() neo4jDB.open("bolt://localhost:7687", "neo4j", "test-neo4j") + /*** orders.first = preOrder, orders.second = inOrder ***/ - val orders: Pair>>>, List>>>> = + val orders: Pair>>>, List>>>> = neo4jDB.exportRBtree() val RBtree = RBStruct>>() RBtree.restoreTreeFromDatabase(orders.first, orders.second) + neo4jDB.close() } - fun saveTree() { - val tree = RBTree() - tree.putItem(Pair(25, 1)) - tree.putItem(Pair(15, 1)) - tree.putItem(Pair(50, 1)) - tree.putItem(Pair(10, 1)) - tree.putItem(Pair(22, 1)) - tree.putItem(Pair(35, 1)) - tree.putItem(Pair(70, 1)) - tree.putItem(Pair(4, 1)) - tree.putItem(Pair(12, 1)) - tree.putItem(Pair(18, 1)) - tree.putItem(Pair(24, 1)) - tree.putItem(Pair(31, 1)) - tree.putItem(Pair(44, 1)) - tree.putItem(Pair(66, 1)) - tree.putItem(Pair(90, 1)) - + fun > saveTree(tree: RBStruct) { val neo4jDB = Neo4jRepository() neo4jDB.open("bolt://localhost:7687", "neo4j", "test-neo4j") - val preOrder = tree.preOrder().map { DBNodeRB(it.value, it.color) } - val inOrder = tree.inOrder().map { DBNodeRB(it.value, it.color) } + // вот тут плохо, потому что тут надо получать не base nodes, а для рисовалки - neo4jDB.saveChanges(preOrder.toTypedArray(), inOrder.toTypedArray()) + val preOrder = tree.preOrder().map { DrawRBVertex(it.value, it.color) } + val inOrder = tree.inOrder().map { DrawRBVertex(it.value, it.color) } + neo4jDB.saveChanges(preOrder.toTypedArray(), inOrder.toTypedArray()) neo4jDB.close() - } } \ No newline at end of file diff --git a/lib/src/main/kotlin/DataBase.kt b/lib/src/main/kotlin/DataBase.kt index e7ca4c6..809eb64 100644 --- a/lib/src/main/kotlin/DataBase.kt +++ b/lib/src/main/kotlin/DataBase.kt @@ -1,8 +1,9 @@ import org.neo4j.driver.AuthTokens import org.neo4j.driver.Driver import org.neo4j.driver.GraphDatabase +import org.neo4j.driver.TransactionContext import org.neo4j.driver.exceptions.SessionExpiredException -import treelib.DBNodeRB +import treelib.rbTree.DrawRBVertex import treelib.singleObjects.Container import treelib.singleObjects.Markers import java.io.Closeable @@ -23,88 +24,50 @@ class Neo4jRepository : Closeable { } } - fun > saveChanges(preOrder: Array>, inOrder: Array>) { + fun > saveChanges(preOrder: Array>, inOrder: Array>) { /*** сюда по ощущениям лучше всего добавлять именно то поддерево исходного дерева, которое было изменено ***/ val session = driver?.session() ?: throw IOException() var inOrderIndex = 0 var preOrderIndex = 0 - val set = HashSet>() - val stack = LinkedList>() + val set = HashSet>() + val stack = LinkedList>() + var id = 0 while (preOrderIndex in preOrder.indices) { do { val currentNode = preOrder[preOrderIndex] - currentNode.value as Container<*, *> + //currentNode.value as Container<*, *> if (preOrderIndex == 0) { session.executeWrite { tx -> - tx.run( - "MERGE(:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY})", - mutableMapOf( - "nodeValue" to currentNode.value.pair.second, - "nodeKey" to currentNode.value.pair.first, - "nodeColor" to currentNode.color.toString(), - "nodeX" to currentNode.x, - "nodeY" to currentNode.y - ) - ) + cleanDB(tx) + createRoot(tx, currentNode, id) } + ++id } if (!stack.isEmpty()) { if (set.contains(stack.peek())) { set.remove(stack.peek()) val parentNode = stack.pop() - parentNode.value as Container<*, *> + //parentNode.value as Container<*, *> session.executeWrite { tx -> - tx.run( - "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + - "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + - "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + - "MERGE (parent)-[:RIGHT_SON]->(son)", - mutableMapOf( - "parentNodeValue" to parentNode.value.pair.second, - "parentNodeKey" to parentNode.value.pair.first, - "parentNodeColor" to parentNode.color.toString(), - "parentNodeX" to parentNode.x, - "parentNodeY" to parentNode.y, - "nodeValue" to currentNode.value.pair.second, - "nodeKey" to currentNode.value.pair.first, - "nodeColor" to currentNode.color.toString(), - "nodeX" to currentNode.x, - "nodeY" to currentNode.y - ) - ) + createRightSon(tx, parentNode, currentNode, id) } + ++id } else { val parentNode = stack.peek() parentNode.value as Container<*, *> session.executeWrite { tx -> - tx.run( - "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + - "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + - "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + - "MERGE (parent)-[:LEFT_SON]->(son)", - mutableMapOf( - "parentNodeValue" to parentNode.value.pair.second, - "parentNodeKey" to parentNode.value.pair.first, - "parentNodeColor" to parentNode.color.toString(), - "parentNodeX" to parentNode.x, - "parentNodeY" to parentNode.y, - "nodeValue" to currentNode.value.pair.second, - "nodeKey" to currentNode.value.pair.first, - "nodeColor" to currentNode.color.toString(), - "nodeX" to currentNode.x, - "nodeY" to currentNode.y - ) - ) + createLeftSon(tx, parentNode, currentNode, id) } + ++id } } stack.push(currentNode) - } while (preOrder[preOrderIndex++] != inOrder[inOrderIndex] && preOrderIndex < preOrder.size) + } while (preOrder[preOrderIndex++].value != inOrder[inOrderIndex].value && preOrderIndex < preOrder.size) - var currentNode: DBNodeRB? = null + var currentNode: DrawRBVertex? = null while (!stack.isEmpty() && inOrderIndex < inOrder.size && stack.peek().value == inOrder[inOrderIndex].value) { currentNode = stack.pop() @@ -121,23 +84,26 @@ class Neo4jRepository : Closeable { session.close() } - fun exportRBtree(): Pair>>>, List>>>> { + fun exportRBtree(): Pair>>>, List>>>> { + + /*** Вот тут короче надо обращаться к neo4j с темЮ чтобы она инициализировала себя как-то ***/ val session = driver?.session() ?: throw IOException() - var preOrder: List>>> = listOf() - var inOrder: List>>> = listOf() + var preOrder: List>>> = listOf() + var inOrder: List>>> = listOf() session.executeRead { tx -> preOrder = tx.run( "MATCH (node: Node) " + - "RETURN node.value, node.key, node.color, node.x, node.y " + "RETURN node.value, node.key, node.color, node.x, node.y " + + "ORDER BY node.id" ).list() .map { - DBNodeRB( - value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), - color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, - x = it.values().get(3).toString().toDouble(), - y = it.values().get(4).toString().toDouble() + DrawRBVertex( + value = Container(Pair(it.values()[1].toString(), it.values()[0].toString())), + color = if (it.values()[2].toString() == """RED""") Markers.RED else Markers.BLACK, + x = it.values()[3].toString().toDouble(), + y = it.values()[4].toString().toDouble() ) } @@ -147,11 +113,11 @@ class Neo4jRepository : Closeable { "ORDER BY node.key" ).list() .map { - DBNodeRB( - value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), - color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, - x = it.values().get(3).toString().toDouble(), - y = it.values().get(4).toString().toDouble() + DrawRBVertex( + value = Container(Pair(it.values()[1].toString(), it.values()[0].toString())), + color = if (it.values()[2].toString() == """RED""") Markers.RED else Markers.BLACK, + x = it.values()[3].toString().toDouble(), + y = it.values()[4].toString().toDouble() ) } } @@ -162,18 +128,80 @@ class Neo4jRepository : Closeable { } + private fun cleanDB(tx: TransactionContext) { + tx.run("MATCH (n: Node) DETACH DELETE n") + } + + private fun > createRoot(tx: TransactionContext, rootNode: DrawRBVertex, id: Int) { + rootNode.value as Container<*, *> + tx.run( + "MERGE(:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY, id: \$nodeID})", + mutableMapOf( + "nodeValue" to rootNode.value.pair.second, + "nodeKey" to rootNode.value.pair.first, + "nodeColor" to rootNode.color.toString(), + "nodeX" to rootNode.x, + "nodeY" to rootNode.y, + "nodeID" to id + ) + ) + } + + private fun > createRightSon( + tx: TransactionContext, parentNode: DrawRBVertex, + currentNode: DrawRBVertex, id: Int + ) { + parentNode.value as Container<*, *> + currentNode.value as Container<*, *> + tx.run( + "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY, id: \$nodeID}) " + + "MERGE (parent)-[:RIGHT_SON]->(son)", + mutableMapOf( + "parentNodeValue" to parentNode.value.pair.second, + "parentNodeKey" to parentNode.value.pair.first, + "parentNodeColor" to parentNode.color.toString(), + "parentNodeX" to parentNode.x, + "parentNodeY" to parentNode.y, + "nodeValue" to currentNode.value.pair.second, + "nodeKey" to currentNode.value.pair.first, + "nodeColor" to currentNode.color.toString(), + "nodeX" to currentNode.x, + "nodeY" to currentNode.y, + "nodeID" to id, + ) + ) + } + + private fun > createLeftSon( + tx: TransactionContext, parentNode: DrawRBVertex, + currentNode: DrawRBVertex, id: Int + ) { + parentNode.value as Container<*, *> + currentNode.value as Container<*, *> + tx.run( + "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY, id: \$nodeID}) " + + "MERGE (parent)-[:LEFT_SON]->(son)", + mutableMapOf( + "parentNodeValue" to parentNode.value.pair.second, + "parentNodeKey" to parentNode.value.pair.first, + "parentNodeColor" to parentNode.color.toString(), + "parentNodeX" to parentNode.x, + "parentNodeY" to parentNode.y, + "nodeValue" to currentNode.value.pair.second, + "nodeKey" to currentNode.value.pair.first, + "nodeColor" to currentNode.color.toString(), + "nodeX" to currentNode.x, + "nodeY" to currentNode.y, + "nodeID" to id, + ) + ) + } + override fun close() { driver?.close() } } - -// neo4j-admin, backup, restore -/* -у меня есть вершины и ребра между ними, надо уметь сохранять дерево в базе, но как? -вопрос: когда заносить изменения в бд и как это реализовывать? -надо еще подумать над оптимизацией, те чтобы не пересобирать дерево в бд каждый раз, когда мы добавили за сессию всего один узел - -root = tx.run("MATCH (parent: Node)-->(son: Node) " + - "WHERE NOT ()-->(parent) " + - "RETURN parent.value, parent.key, parent.color, parent.x, parent.y").list().map {it.values()}.get(0) - */ diff --git a/lib/src/main/kotlin/initNeo4j.sh b/lib/src/main/kotlin/initNeo4j.sh new file mode 100644 index 0000000..e69de29 diff --git a/lib/src/main/kotlin/loadNeo4j.sh b/lib/src/main/kotlin/loadNeo4j.sh new file mode 100644 index 0000000..d4d9fcd --- /dev/null +++ b/lib/src/main/kotlin/loadNeo4j.sh @@ -0,0 +1,8 @@ + +BASEDIR=$(realpath "$(dirname "$0")") + +. "${BASEDIR}/CONTAINER.conf" + +docker stop "$CONTAINER_NAME" + +neo4j-admin dump --database=neo4j --to=/data/backups/ \ No newline at end of file diff --git a/lib/src/main/kotlin/testNeo4j.sh b/lib/src/main/kotlin/testNeo4j.sh index 97ad8db..87b69c4 100644 --- a/lib/src/main/kotlin/testNeo4j.sh +++ b/lib/src/main/kotlin/testNeo4j.sh @@ -3,13 +3,22 @@ BASEDIR=$(realpath "$(dirname "$0")") . "${BASEDIR}/CONTAINER.conf" +# -d docker run \ - --rm \ - --name "CONTAINER_NAME" \ + -i \ + --name "$CONTAINER_NAME" \ --volume=$HOME/neo4j/data:/data \ --volume=$HOME/neo4j/logs:/logs \ --publish=7474:7474 --publish=7687:7687 \ --env NEO4J_AUTH=neo4j/"$PASSWORD" \ neo4j:latest \ +# -c /bin/bash +#neo4j-admin database dump neo4j --to-path=$HOME/neo4j/data:/data + +#docker ps -a + +#docker stop "$CONTAINER_NAME" + +#cp $HOME/neo4j/data:/data $HOME/ #docker stop neo4j:latest diff --git a/lib/src/main/kotlin/treelib/Main.kt b/lib/src/main/kotlin/treelib/Main.kt index 0aeb3e0..15e0eab 100644 --- a/lib/src/main/kotlin/treelib/Main.kt +++ b/lib/src/main/kotlin/treelib/Main.kt @@ -1,6 +1,8 @@ package treelib import Controller +import treelib.rbTree.RBStruct +import treelib.singleObjects.Container fun main() { @@ -30,10 +32,35 @@ fun main() { neo4jRep.open("bolt://localhost:7687", "neo4j", "test-neo4j") neo4jRep.saveChanges(preArr, inArr) */ + + val tree = RBStruct>() + tree.insert(Container(Pair(25 , 1))) + tree.insert(Container(Pair(15 , 1))) + tree.insert(Container(Pair(50 , 1))) + tree.insert(Container(Pair(10 , 1))) + tree.insert(Container(Pair(22 , 1))) + tree.insert(Container(Pair(35 , 1))) + tree.insert(Container(Pair(70 , 1))) + tree.insert(Container(Pair(4 , 1))) + tree.insert(Container(Pair(12 , 1))) + tree.insert(Container(Pair(18 , 1))) + tree.insert(Container(Pair(24 , 1))) + tree.insert(Container(Pair(31 , 1))) + tree.insert(Container(Pair(44 , 1))) + tree.insert(Container(Pair(66 , 1))) + tree.insert(Container(Pair(90 , 1))) val controller = Controller() - controller.saveTree() + controller.saveTree(tree) + tree.insert(Container(Pair(100, 1))) + controller.saveTree(tree) + controller.initTree() //neo4jRep.exportRBtree() //neo4jRep.close() +} + +fun test() { + val cont = Controller() + cont.initTree() } \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/abstractTree/Tree.kt b/lib/src/main/kotlin/treelib/abstractTree/Tree.kt index 1607caa..1116ad6 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/Tree.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/Tree.kt @@ -4,44 +4,47 @@ import treelib.singleObjects.Container import treelib.singleObjects.exceptions.NonExistentValueException abstract class Tree< - Key : Comparable, - Value, - NodeType : Node, NodeType>, - State : StateContainer, NodeType> + K : Comparable, + V, + NodeType : Node, NodeType>, + State : StateContainer, NodeType>, + VertexType: Vertex> > { - protected abstract val treeStruct: TreeStruct, NodeType, State> + protected abstract val treeStruct: TreeStruct, NodeType, State, VertexType> - private fun wrapForFind(key: Key) = Container(key to null) + private fun wrapForFind(key: K) = Container(key to null) - fun putItem(item: Pair) { + fun putItem(item: Pair) { treeStruct.insert(Container(item)) } - fun putItems(vararg items: Pair) { + fun putItems(vararg items: Pair) { for (element in items) putItem(element) } - fun putItems(items: Iterable>) { + fun putItems(items: Iterable>) { for (element in items) putItem(element) } - fun getItem(key: Key): Value? = treeStruct.find(wrapForFind(key))?.value + fun getItem(key: K): V? = treeStruct.find(wrapForFind(key))?.value - fun deleteItem(key: Key) { + fun deleteItem(key: K) { if (getItem(key) == null) throw NonExistentValueException() treeStruct.delete(wrapForFind(key)) } - private fun createPoorList(info: List): List { - val returnInfo = mutableListOf() - for (element in info) returnInfo.add(element) + private fun createPoorList(info: List): List> { + val returnInfo = mutableListOf>() + for (element in info) { + returnInfo.add(element.value.pair) + } return returnInfo } - fun inOrder(): List = createPoorList(treeStruct.inOrder()) + fun inOrder(): List> = createPoorList(treeStruct.inOrder()) - fun preOrder(): List = createPoorList(treeStruct.preOrder()) + fun preOrder(): List> = createPoorList(treeStruct.preOrder()) - fun postOrder(): List = createPoorList(treeStruct.postOrder()) + fun postOrder(): List> = createPoorList(treeStruct.postOrder()) } diff --git a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt index 5b96f98..c91c6ed 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt @@ -9,7 +9,8 @@ import treelib.singleObjects.exceptions.NonExistentValueException abstract class TreeStruct< Pack : Comparable, NodeType : Node, - State : StateContainer + State : StateContainer, + VertexType: Vertex > { protected abstract var root: NodeType? @@ -163,8 +164,8 @@ abstract class TreeStruct< linkNewNode(currentNode, parentNode) - if (parentNode == null) return generateStateInsert(currentNode, currentNode) - else return generateStateInsert(currentNode, parentNode) + if (parentNode != null) return generateStateInsert(currentNode, parentNode) + else return generateStateInsert(currentNode, currentNode) } updateNode.value = item @@ -260,8 +261,8 @@ abstract class TreeStruct< fun find(obj: Pack): Pack? = findItem(obj).contentNode?.value - fun inOrder(): List { - val arrayNodes = mutableListOf() + fun inOrder(): List { + val arrayNodes = mutableListOf() var flagVisited = 0 var current = root val parents = ArrayDeque() @@ -278,24 +279,26 @@ abstract class TreeStruct< } } current?.let { - arrayNodes.add(it.value) + arrayNodes.add(it) if (it.right != null) { flagVisited = 0 current = it.right } else { if (parents.isEmpty()) - return@inOrder arrayNodes + return@inOrder arrayNodes.map {toVertex(it)} flagVisited = 1 current = parents.removeLast() } } } - return arrayNodes + return arrayNodes.map{toVertex(it)} } - fun postOrder(): List { + abstract fun toVertex(node: NodeType): VertexType + + fun postOrder(): List { val parents = ArrayDeque() - val arrayNodes = mutableListOf() + val arrayNodes = mutableListOf() var flagVisited = 0 var current = root @@ -316,9 +319,9 @@ abstract class TreeStruct< current = it.right flagVisited = 0 } else { - arrayNodes.add(it.value) + arrayNodes.add(it) if (parents.isEmpty()) - return@postOrder arrayNodes + return@postOrder arrayNodes.map{toVertex(it)} val parent = parents.removeLast() if (parent.right == it) { flagVisited = 2 @@ -327,11 +330,11 @@ abstract class TreeStruct< } } ?: throw MultithreadingException(ImpossibleCaseException()) } - return arrayNodes + return arrayNodes.map{toVertex(it)} } - fun preOrder(): List { - val arrayNodes = mutableListOf() + fun preOrder(): List { + val arrayNodes = mutableListOf() var current: NodeType val queue = ArrayDeque() @@ -339,7 +342,7 @@ abstract class TreeStruct< queue.add(root) while (queue.isNotEmpty()) { current = queue.removeLast() - arrayNodes.add(current.value) + arrayNodes.add(current) if (current.right != null) current.right?.let { queue.add(it) @@ -351,6 +354,8 @@ abstract class TreeStruct< } ?: throw MultithreadingException(ImpossibleCaseException()) } } - return arrayNodes + return arrayNodes.map {toVertex(it)} } + + } diff --git a/lib/src/main/kotlin/treelib/abstractTree/Vertex.kt b/lib/src/main/kotlin/treelib/abstractTree/Vertex.kt new file mode 100644 index 0000000..abbb7a5 --- /dev/null +++ b/lib/src/main/kotlin/treelib/abstractTree/Vertex.kt @@ -0,0 +1,5 @@ +package treelib.abstractTree + +abstract class Vertex>{ + abstract val value: Pack +} \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/abstractTree/balanced/BalancedTreeStruct.kt b/lib/src/main/kotlin/treelib/abstractTree/balanced/BalancedTreeStruct.kt index 5dd24c3..96e8458 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/balanced/BalancedTreeStruct.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/balanced/BalancedTreeStruct.kt @@ -3,13 +3,15 @@ package treelib.abstractTree.balanced import treelib.abstractTree.Node import treelib.abstractTree.StateContainer import treelib.abstractTree.TreeStruct +import treelib.abstractTree.Vertex abstract class BalancedTreeStruct< Pack : Comparable, NodeType : Node, State : StateContainer, + VertexType: Vertex, BalancerType : Balancer, - > : TreeStruct() { + > : TreeStruct() { protected abstract val balancer: BalancerType diff --git a/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt b/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt index f275439..7893341 100644 --- a/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt +++ b/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt @@ -3,7 +3,7 @@ package treelib.avlTree import treelib.abstractTree.balanced.BalancedTreeStruct class AVLStruct> : - BalancedTreeStruct, AVLStateContainer, AVLBalancer>() { + BalancedTreeStruct, AVLStateContainer, AVLVertex, AVLBalancer>() { override var root: AVLNode? = null override val balancer = AVLBalancer(root) @@ -40,6 +40,10 @@ class AVLStruct> : } } + override fun toVertex(node: AVLNode): AVLVertex { + return AVLVertex(node.value, node.height) + } + override fun createNode(item: Pack): AVLNode = AVLNode(item) override fun getNodeKernel(node: AVLNode): AVLNode = AVLNode(node.value, height = node.height) diff --git a/lib/src/main/kotlin/treelib/avlTree/AVLTree.kt b/lib/src/main/kotlin/treelib/avlTree/AVLTree.kt index 6155af6..5df840f 100644 --- a/lib/src/main/kotlin/treelib/avlTree/AVLTree.kt +++ b/lib/src/main/kotlin/treelib/avlTree/AVLTree.kt @@ -4,12 +4,12 @@ import treelib.abstractTree.Tree import treelib.singleObjects.Container -class AVLTree, Value> : - Tree>, AVLStateContainer>>() { +class AVLTree, V> : + Tree>, AVLStateContainer>, AVLVertex>>() { - override val treeStruct = AVLStruct>() + override val treeStruct = AVLStruct>() - operator fun AVLTree.get(key: Key): Value? = getItem(key) + operator fun AVLTree.get(key: K): V? = getItem(key) - operator fun AVLTree.set(key: Key, value: Value) = putItem(key to value) + operator fun AVLTree.set(key: K, value: V) = putItem(key to value) } diff --git a/lib/src/main/kotlin/treelib/avlTree/AVLVertex.kt b/lib/src/main/kotlin/treelib/avlTree/AVLVertex.kt new file mode 100644 index 0000000..a43ea26 --- /dev/null +++ b/lib/src/main/kotlin/treelib/avlTree/AVLVertex.kt @@ -0,0 +1,8 @@ +package treelib.avlTree + +import treelib.abstractTree.Vertex + +class AVLVertex>( + override val value: Pack, + val height: UInt, +) : Vertex() \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/binTree/BINStruct.kt b/lib/src/main/kotlin/treelib/binTree/BINStruct.kt index e555924..f3bfc09 100644 --- a/lib/src/main/kotlin/treelib/binTree/BINStruct.kt +++ b/lib/src/main/kotlin/treelib/binTree/BINStruct.kt @@ -3,7 +3,7 @@ package treelib.binTree import treelib.abstractTree.TreeStruct class BINStruct> : - TreeStruct, BINStateContainer>() { + TreeStruct, BINStateContainer, BINVertex>() { override var root: BINNode? = null @@ -53,6 +53,10 @@ class BINStruct> : return node } + override fun toVertex(node: BINNode): BINVertex { + return BINVertex(node.value) + } + override fun createNode(item: Pack) = BINNode(item) override fun delete(item: Pack) { diff --git a/lib/src/main/kotlin/treelib/binTree/BINTree.kt b/lib/src/main/kotlin/treelib/binTree/BINTree.kt index f8ac560..f0a92d9 100644 --- a/lib/src/main/kotlin/treelib/binTree/BINTree.kt +++ b/lib/src/main/kotlin/treelib/binTree/BINTree.kt @@ -3,12 +3,12 @@ package treelib.binTree import treelib.abstractTree.Tree import treelib.singleObjects.Container -class BINTree, Value> - : Tree>, BINStateContainer>>() { +class BINTree, V> + : Tree>, BINStateContainer>, BINVertex>>() { - override val treeStruct = BINStruct>() + override val treeStruct = BINStruct>() - operator fun BINTree.get(key: Key): Value? = getItem(key) + operator fun BINTree.get(key: K): V? = getItem(key) - operator fun BINTree.set(key: Key, value: Value) = putItem(key to value) + operator fun BINTree.set(key: K, value: V) = putItem(key to value) } diff --git a/lib/src/main/kotlin/treelib/binTree/BINVertex.kt b/lib/src/main/kotlin/treelib/binTree/BINVertex.kt new file mode 100644 index 0000000..e660d8c --- /dev/null +++ b/lib/src/main/kotlin/treelib/binTree/BINVertex.kt @@ -0,0 +1,5 @@ +package treelib.binTree + +import treelib.abstractTree.Vertex + +class BINVertex>(override val value: Pack): Vertex() \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt b/lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt new file mode 100644 index 0000000..b3ee499 --- /dev/null +++ b/lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt @@ -0,0 +1,10 @@ +package treelib.rbTree + +import treelib.singleObjects.Markers + +class DrawRBVertex>( + value: Pack, + color: Markers, + val x: Double = 0.0, + val y: Double = 0.0 +) : RBVertex(value, color) \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt b/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt index 211e007..c8c4cf6 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt @@ -2,6 +2,8 @@ package treelib.rbTree import treelib.abstractTree.balanced.BalancerParent import treelib.singleObjects.Markers +import treelib.singleObjects.exceptions.IllegalBaseNodeException +import treelib.singleObjects.exceptions.IllegalNodeStateException class RBBalancer>(private var root: RBNode?) : BalancerParent, RBStateContainer>() { @@ -42,7 +44,7 @@ class RBBalancer>(private var root: RBNode?) : override fun balance(stateContainer: RBStateContainer): RBNode { val node = stateContainer.contentNode - ?: throw IllegalStateException() //IllegalBaseNodeException("A non-existent node (null) was passed to the method") + ?: throw IllegalBaseNodeException() val uncle = getUncle(node) when { /** node insertion case **/ @@ -65,7 +67,7 @@ class RBBalancer>(private var root: RBNode?) : currentNode = parent } parent = - currentNode.parent?.parent ?: throw IllegalStateException() // IllegalNodeStateException() + currentNode.parent?.parent ?: throw IllegalNodeStateException() currentNode = rightRotate(parent) currentNode.color = Markers.BLACK currentNode.right?.color = Markers.RED @@ -78,7 +80,7 @@ class RBBalancer>(private var root: RBNode?) : currentNode = parent } parent = - currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() + currentNode.parent?.parent ?: throw IllegalNodeStateException() currentNode = leftRotate(parent) currentNode.color = Markers.BLACK currentNode.right?.color = Markers.RED @@ -133,7 +135,7 @@ class RBBalancer>(private var root: RBNode?) : val uncle = getUncle(currentNode) if (uncle?.color == Markers.RED) { currentNode.parent?.color = Markers.BLACK - currentNode = currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() + currentNode = currentNode.parent?.parent ?: throw IllegalNodeStateException() currentNode.color = Markers.RED uncle.color = Markers.BLACK } else if (uncle != null) { @@ -156,13 +158,13 @@ class RBBalancer>(private var root: RBNode?) : getRoot(parent) } - else -> getRoot(node ?: throw NullPointerException() /* IllegalNodeStateException() */) + else -> getRoot(node ?: throw IllegalNodeStateException()) } } /** parent is red **/ private fun secondCase(parent: RBNode, node: RBNode?) { - var brother = getBrother(parent, node) ?: throw NullPointerException() // IllegalNodeStateException() + var brother = getBrother(parent, node) ?: throw IllegalNodeStateException() if (brother.color == Markers.RED) throw NullPointerException() @@ -214,7 +216,7 @@ class RBBalancer>(private var root: RBNode?) : /** parent is black **/ private fun thirdCase(parent: RBNode, node: RBNode?) { - val brother = getBrother(parent, node) ?: throw NullPointerException() // IllegalNodeStateException() + val brother = getBrother(parent, node) ?: throw IllegalNodeStateException() when (brother.color) { Markers.RED -> thirdCaseSubFirst(brother, parent) Markers.BLACK -> thirdCaseSubSecond(brother, parent) @@ -225,7 +227,7 @@ class RBBalancer>(private var root: RBNode?) : private fun thirdCaseSubFirst(brother: RBNode, parent: RBNode) { when (brother) { brother.parent?.left -> { - var rightBrotherSon = brother.right ?: throw NullPointerException() // IllegalNodeStateException() + var rightBrotherSon = brother.right ?: throw IllegalNodeStateException() if (rightBrotherSon.right?.color != Markers.RED && rightBrotherSon.left?.color != Markers.RED) { rightBrotherSon.color = Markers.RED @@ -242,7 +244,7 @@ class RBBalancer>(private var root: RBNode?) : leftRotate(rightBrotherSon) rightBrotherSon = - rightBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() + rightBrotherSon.parent ?: throw IllegalNodeStateException() rightBrotherSon.color = Markers.BLACK } @@ -258,7 +260,7 @@ class RBBalancer>(private var root: RBNode?) : if (leftBrotherSon.right?.color != Markers.RED && leftBrotherSon.left?.color != Markers.RED) { leftBrotherSon.color = Markers.RED brother.color = Markers.BLACK - leftRotate(brother.parent ?: throw NullPointerException()) // IllegalNodeStateException() + leftRotate(brother.parent ?: throw IllegalNodeStateException()) return } @@ -266,7 +268,7 @@ class RBBalancer>(private var root: RBNode?) : rightRotate(leftBrotherSon) leftBrotherSon.color = Markers.RED leftBrotherSon = - leftBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() + leftBrotherSon.parent ?: throw IllegalNodeStateException() leftBrotherSon.color = Markers.BLACK } diff --git a/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt b/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt index ee6a216..47dd91d 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt @@ -1,6 +1,5 @@ package treelib.rbTree -import treelib.DBNodeRB import treelib.abstractTree.balanced.BalancedTreeStruct import treelib.singleObjects.Markers import treelib.singleObjects.exceptions.ImpossibleCaseException @@ -8,7 +7,7 @@ import treelib.singleObjects.exceptions.MultithreadingException import java.util.* class RBStruct> : - BalancedTreeStruct, RBStateContainer, RBBalancer>() { + BalancedTreeStruct, RBStateContainer, RBVertex, RBBalancer>() { override var root: RBNode? = null @@ -57,6 +56,10 @@ class RBStruct> : override fun getNodeKernel(node: RBNode): RBNode = RBNode(node.value, color = node.color) + override fun toVertex(node: RBNode): RBVertex { + return RBVertex(node.value, node.color) + } + override fun createNode(item: Pack): RBNode = RBNode(item) override fun linkNewNode(node: RBNode, parent: RBNode?): RBNode { @@ -73,7 +76,7 @@ class RBStruct> : return node } - fun restoreTreeFromDatabase(preOrder: List>, inOrder: List>) { + fun > restoreTreeFromDatabase(preOrder: List, inOrder: List) { var inOrderIndex = 0 var preOrderIndex = 0 val set = HashSet>() @@ -81,7 +84,7 @@ class RBStruct> : while (preOrderIndex in preOrder.indices) { var currentNode: RBNode? - var drawNode: DBNodeRB + var drawNode: RBVertexType do { drawNode = preOrder[preOrderIndex] @@ -117,7 +120,7 @@ class RBStruct> : } - private fun createRBNode(drawNode: DBNodeRB): RBNode { + private fun > createRBNode(drawNode: RBVertexType): RBNode { val node = RBNode(value = drawNode.value, color = drawNode.color) return node } diff --git a/lib/src/main/kotlin/treelib/rbTree/RBTree.kt b/lib/src/main/kotlin/treelib/rbTree/RBTree.kt index 6ccfa32..a29234e 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBTree.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBTree.kt @@ -4,12 +4,12 @@ import treelib.abstractTree.Tree import treelib.singleObjects.Container -class RBTree, Value> : - Tree>, RBStateContainer>>() { +class RBTree, V> : + Tree>, RBStateContainer>, RBVertex>>() { - override val treeStruct = RBStruct>() + override val treeStruct = RBStruct>() - operator fun RBTree.get(key: Key): Value? = getItem(key) + operator fun RBTree.get(key: K): V? = getItem(key) - operator fun RBTree.set(key: Key, value: Value) = putItem(key to value) + operator fun RBTree.set(key: K, value: V) = putItem(key to value) } diff --git a/lib/src/main/kotlin/treelib/rbTree/RBVertex.kt b/lib/src/main/kotlin/treelib/rbTree/RBVertex.kt new file mode 100644 index 0000000..5d9d161 --- /dev/null +++ b/lib/src/main/kotlin/treelib/rbTree/RBVertex.kt @@ -0,0 +1,9 @@ +package treelib.rbTree + +import treelib.abstractTree.Vertex +import treelib.singleObjects.Markers + +open class RBVertex>( + override val value: Pack, + val color: Markers, +):Vertex() \ No newline at end of file From f38f068df4581969a4958e9953928ee6efd9cc8b Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 18 Apr 2023 22:04:52 +0300 Subject: [PATCH 62/84] fix: Add running on multiple OS --- .github/workflows/CI.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index ae15aca..8697f86 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -4,7 +4,10 @@ on: [push, pull_request] jobs: run: - runs-on: ubuntu-latest + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + runs-on: ${{ matrix.os }} steps: - name: Checkout uses: actions/checkout@v3 From 64ad32044afe4ea44b02a6ad074d84d3c80affe5 Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 18 Apr 2023 22:37:53 +0300 Subject: [PATCH 63/84] fix: Fix tree class definitions --- .gitignore | 3 ++- lib/src/test/kotlin/treelib/AVLStructTest.kt | 3 ++- lib/src/test/kotlin/treelib/BINStructTest.kt | 3 ++- lib/src/test/kotlin/treelib/RBStructTest.kt | 3 ++- lib/src/test/kotlin/utils/TreeStructWrapper.kt | 3 ++- lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt | 3 ++- lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt | 3 ++- .../test/kotlin/utils/fuzzers/TreeStructFuzzer.kt | 12 +++++++----- 8 files changed, 21 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 7061064..38f0b3d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /.gradle/ /.idea/ /build/ -/lib/build/ \ No newline at end of file +/lib/build/ +/lib/TEST_TEST/ diff --git a/lib/src/test/kotlin/treelib/AVLStructTest.kt b/lib/src/test/kotlin/treelib/AVLStructTest.kt index 1e522fe..f003b60 100644 --- a/lib/src/test/kotlin/treelib/AVLStructTest.kt +++ b/lib/src/test/kotlin/treelib/AVLStructTest.kt @@ -7,12 +7,13 @@ import org.junit.jupiter.api.fail import treelib.avlTree.AVLNode import treelib.avlTree.AVLStateContainer import treelib.avlTree.AVLStruct +import treelib.avlTree.AVLVertex import utils.AVLAnalyzer import utils.TreeStructWrapper @DisplayName("Test: AVL Struct") class AVLStructTest { - private val treeW = TreeStructWrapper, AVLStateContainer, AVLStruct>() + private val treeW = TreeStructWrapper, AVLVertex, AVLStateContainer, AVLStruct>() private val treeH = AVLAnalyzer(::testAssert) private var treeStruct = AVLStruct() diff --git a/lib/src/test/kotlin/treelib/BINStructTest.kt b/lib/src/test/kotlin/treelib/BINStructTest.kt index 952a6fa..1075631 100644 --- a/lib/src/test/kotlin/treelib/BINStructTest.kt +++ b/lib/src/test/kotlin/treelib/BINStructTest.kt @@ -7,13 +7,14 @@ import org.junit.jupiter.api.fail import treelib.binTree.BINNode import treelib.binTree.BINStateContainer import treelib.binTree.BINStruct +import treelib.binTree.BINVertex import utils.BINAnalyzer import utils.TreeStructWrapper import kotlin.test.assertEquals @DisplayName("Test: Binary Search Tree Struct") class BINStructTest { - val treeW = TreeStructWrapper, BINStateContainer, BINStruct>() + val treeW = TreeStructWrapper, BINVertex, BINStateContainer, BINStruct>() var treeStruct = BINStruct() private fun testAssert(msg: String): Nothing = fail(msg) diff --git a/lib/src/test/kotlin/treelib/RBStructTest.kt b/lib/src/test/kotlin/treelib/RBStructTest.kt index 606ca40..3196207 100644 --- a/lib/src/test/kotlin/treelib/RBStructTest.kt +++ b/lib/src/test/kotlin/treelib/RBStructTest.kt @@ -4,6 +4,7 @@ import org.junit.jupiter.api.* import treelib.rbTree.RBNode import treelib.rbTree.RBStateContainer import treelib.rbTree.RBStruct +import treelib.rbTree.RBVertex import treelib.singleObjects.Markers import utils.RBAnalyzer import utils.TreeStructWrapper @@ -12,7 +13,7 @@ import kotlin.test.assertEquals @DisplayName("Test: Red-Black Tree Struct") class RBStructTest { - private val treeW = TreeStructWrapper, RBStateContainer, RBStruct>() + private val treeW = TreeStructWrapper, RBVertex, RBStateContainer, RBStruct>() private var treeStruct = RBStruct() private fun testAssert(msg: String): Nothing = fail(msg) diff --git a/lib/src/test/kotlin/utils/TreeStructWrapper.kt b/lib/src/test/kotlin/utils/TreeStructWrapper.kt index 1bdb93e..64fea41 100644 --- a/lib/src/test/kotlin/utils/TreeStructWrapper.kt +++ b/lib/src/test/kotlin/utils/TreeStructWrapper.kt @@ -3,8 +3,9 @@ package utils import treelib.abstractTree.Node import treelib.abstractTree.StateContainer import treelib.abstractTree.TreeStruct +import treelib.abstractTree.Vertex -class TreeStructWrapper, NodeType : Node, State: StateContainer, TStruct : TreeStruct> { +class TreeStructWrapper, NodeType : Node, VertexType: Vertex, State: StateContainer, TStruct : TreeStruct> { fun getPrivateNode(tree: TStruct, name: String = "root"): NodeType? { val field = tree.javaClass.getDeclaredField(name) diff --git a/lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt b/lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt index 5ce3959..bc79507 100644 --- a/lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt +++ b/lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt @@ -3,12 +3,13 @@ package utils.fuzzers import treelib.binTree.BINNode import treelib.binTree.BINStateContainer import treelib.binTree.BINStruct +import treelib.binTree.BINVertex import utils.BINAnalyzer class BINStructFuzzer>( override val baseInput: Array, override val assertMethod: (input: String) -> Unit -): TreeStructFuzzer, BINAnalyzer, BINStateContainer, BINStruct>() { +): TreeStructFuzzer, BINVertex, BINAnalyzer, BINStateContainer, BINStruct>() { override fun createTreeStruct(): BINStruct = BINStruct() diff --git a/lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt b/lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt index 6b59799..2a6bb7f 100644 --- a/lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt +++ b/lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt @@ -3,12 +3,13 @@ package utils.fuzzers import treelib.rbTree.RBNode import treelib.rbTree.RBStateContainer import treelib.rbTree.RBStruct +import treelib.rbTree.RBVertex import utils.RBAnalyzer class RBStructFuzzer>( override val baseInput: Array, override val assertMethod: (input: String) -> Unit -): TreeStructFuzzer, RBAnalyzer, RBStateContainer, RBStruct>() { +): TreeStructFuzzer, RBVertex, RBAnalyzer, RBStateContainer, RBStruct>() { override fun createTreeStruct(): RBStruct = RBStruct() diff --git a/lib/src/test/kotlin/utils/fuzzers/TreeStructFuzzer.kt b/lib/src/test/kotlin/utils/fuzzers/TreeStructFuzzer.kt index a5390b9..7d5e0d6 100644 --- a/lib/src/test/kotlin/utils/fuzzers/TreeStructFuzzer.kt +++ b/lib/src/test/kotlin/utils/fuzzers/TreeStructFuzzer.kt @@ -3,20 +3,22 @@ package utils.fuzzers import treelib.abstractTree.Node import treelib.abstractTree.StateContainer import treelib.abstractTree.TreeStruct -import kotlin.random.Random -import utils.Analyzer +import treelib.abstractTree.Vertex import treelib.singleObjects.exceptions.* -import kotlin.random.nextInt +import utils.Analyzer import utils.TreeStructWrapper import java.io.File import java.time.Instant +import kotlin.random.Random +import kotlin.random.nextInt abstract class TreeStructFuzzer< Pack : Comparable, NodeType : Node, + VertexType: Vertex, AnalyzerType : Analyzer, State : StateContainer, - TreeStructType : TreeStruct, + TreeStructType : TreeStruct, > { abstract val baseInput: Array @@ -26,7 +28,7 @@ abstract class TreeStructFuzzer< private var dirPath: String? = null - protected val treeWrapper = TreeStructWrapper() + protected val treeWrapper = TreeStructWrapper() protected abstract fun createTreeStruct(): TreeStructType From 48b670d37be64be073a176926306810690c83538 Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 18 Apr 2023 23:33:36 +0300 Subject: [PATCH 64/84] fix(CI): Add a condition to run jacoco --- .github/workflows/CI.yml | 6 ++++-- lib/src/test/kotlin/{ => treelib}/AVLBalancerTest.kt | 0 lib/src/test/kotlin/{ => treelib}/RBBalancerTest.kt | 0 lib/src/test/kotlin/{ => treelib}/TestModelAVL.kt | 0 lib/src/test/kotlin/{ => treelib}/TestModelRBT.kt | 0 5 files changed, 4 insertions(+), 2 deletions(-) rename lib/src/test/kotlin/{ => treelib}/AVLBalancerTest.kt (100%) rename lib/src/test/kotlin/{ => treelib}/RBBalancerTest.kt (100%) rename lib/src/test/kotlin/{ => treelib}/TestModelAVL.kt (100%) rename lib/src/test/kotlin/{ => treelib}/TestModelRBT.kt (100%) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 8697f86..243bd23 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -22,10 +22,12 @@ jobs: - name: Run Tests run: ./gradlew clean test - - name: Run Test Coverage + - if: matrix.os == 'ubuntu-latest' # Container action is only supported on Linux + name: Run Test Coverage run: ./gradlew jacocoTestReport - - name: Jacoco Code Coverage Report + - if: matrix.os == 'ubuntu-latest' + name: Jacoco Code Coverage Report uses: cicirello/jacoco-badge-generator@v2.8.0 with: generate-branches-badge: true diff --git a/lib/src/test/kotlin/AVLBalancerTest.kt b/lib/src/test/kotlin/treelib/AVLBalancerTest.kt similarity index 100% rename from lib/src/test/kotlin/AVLBalancerTest.kt rename to lib/src/test/kotlin/treelib/AVLBalancerTest.kt diff --git a/lib/src/test/kotlin/RBBalancerTest.kt b/lib/src/test/kotlin/treelib/RBBalancerTest.kt similarity index 100% rename from lib/src/test/kotlin/RBBalancerTest.kt rename to lib/src/test/kotlin/treelib/RBBalancerTest.kt diff --git a/lib/src/test/kotlin/TestModelAVL.kt b/lib/src/test/kotlin/treelib/TestModelAVL.kt similarity index 100% rename from lib/src/test/kotlin/TestModelAVL.kt rename to lib/src/test/kotlin/treelib/TestModelAVL.kt diff --git a/lib/src/test/kotlin/TestModelRBT.kt b/lib/src/test/kotlin/treelib/TestModelRBT.kt similarity index 100% rename from lib/src/test/kotlin/TestModelRBT.kt rename to lib/src/test/kotlin/treelib/TestModelRBT.kt From f3f514c04ea8835cbc9569b47a969b12a3b7176e Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 18 Apr 2023 23:36:42 +0300 Subject: [PATCH 65/84] refactor: Rename some methods in test classes --- lib/build.gradle.kts | 6 +++--- lib/src/test/kotlin/treelib/AVLBalancerTest.kt | 2 ++ lib/src/test/kotlin/treelib/RBBalancerTest.kt | 2 ++ lib/src/test/kotlin/treelib/TestModelAVL.kt | 2 ++ lib/src/test/kotlin/treelib/TestModelRBT.kt | 2 ++ 5 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 0dfd5f1..08851db 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -87,7 +87,7 @@ tasks.jacocoTestReport { tasks.jacocoTestCoverageVerification { classDirectories.setFrom( classDirectories.files.flatMap { fileTree(it) { - include("**/RBBalancer.class", "**/AVLBalancer.class", "**/BINStruct") + include("**/RBBalancer.class", "**/AVLBalancer.class", "**/BINStruct", "**/AVLStruct.class", "**/BINStruct.class") } }) dependsOn(tasks.jacocoTestReport) violationRules { @@ -95,7 +95,7 @@ tasks.jacocoTestCoverageVerification { element = "CLASS" limit { counter = "BRANCH" - minimum = 0.4.toBigDecimal() + minimum = 0.5.toBigDecimal() } } rule { @@ -109,7 +109,7 @@ tasks.jacocoTestCoverageVerification { element = "CLASS" limit { counter = "METHOD" - minimum = 1.0.toBigDecimal() + minimum = 0.9.toBigDecimal() } } } diff --git a/lib/src/test/kotlin/treelib/AVLBalancerTest.kt b/lib/src/test/kotlin/treelib/AVLBalancerTest.kt index 862a497..3ee5452 100644 --- a/lib/src/test/kotlin/treelib/AVLBalancerTest.kt +++ b/lib/src/test/kotlin/treelib/AVLBalancerTest.kt @@ -1,3 +1,5 @@ +package treelib + import org.junit.jupiter.api.* import org.junit.jupiter.api.Assertions.assertEquals import treelib.avlTree.AVLBalancer diff --git a/lib/src/test/kotlin/treelib/RBBalancerTest.kt b/lib/src/test/kotlin/treelib/RBBalancerTest.kt index 0bc9e43..d18134e 100644 --- a/lib/src/test/kotlin/treelib/RBBalancerTest.kt +++ b/lib/src/test/kotlin/treelib/RBBalancerTest.kt @@ -1,3 +1,5 @@ +package treelib + import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Nested diff --git a/lib/src/test/kotlin/treelib/TestModelAVL.kt b/lib/src/test/kotlin/treelib/TestModelAVL.kt index c96773d..8a3ba26 100644 --- a/lib/src/test/kotlin/treelib/TestModelAVL.kt +++ b/lib/src/test/kotlin/treelib/TestModelAVL.kt @@ -1,3 +1,5 @@ +package treelib + import treelib.avlTree.AVLNode class TestModelAVL { diff --git a/lib/src/test/kotlin/treelib/TestModelRBT.kt b/lib/src/test/kotlin/treelib/TestModelRBT.kt index ac86a6c..ca7efe7 100644 --- a/lib/src/test/kotlin/treelib/TestModelRBT.kt +++ b/lib/src/test/kotlin/treelib/TestModelRBT.kt @@ -1,3 +1,5 @@ +package treelib + import treelib.rbTree.RBNode import treelib.singleObjects.Markers From dfb677243edfc418b618a7fb8623e4cc753d7032 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 19 Apr 2023 04:39:37 +0300 Subject: [PATCH 66/84] feat: Implement sketch of jsonRepository --- .gitignore | 1 + lib/build.gradle.kts | 3 + .../Neo4jController.kt} | 6 +- .../kotlin/dbSave/jsonFormat/DrawBINVertex.kt | 9 +++ .../dbSave/jsonFormat/JsonRepository.kt | 34 ++++++++++ .../kotlin/{ => dbSave/neo4j}/CONTAINER.conf | 0 .../rbTree => dbSave/neo4j}/DrawRBVertex.kt | 3 +- .../neo4j/Neo4jRepository.kt} | 4 +- .../kotlin/{ => dbSave/neo4j}/testNeo4j.sh | 11 ---- lib/src/main/kotlin/initNeo4j.sh | 0 lib/src/main/kotlin/loadNeo4j.sh | 8 --- lib/src/main/kotlin/treelib/DBNodeRB.kt | 11 ---- lib/src/main/kotlin/treelib/Main.kt | 66 ------------------- .../main/kotlin/treelib/binTree/BINVertex.kt | 2 +- 14 files changed, 57 insertions(+), 101 deletions(-) rename lib/src/main/kotlin/{Controller.kt => controller/Neo4jController.kt} (91%) create mode 100644 lib/src/main/kotlin/dbSave/jsonFormat/DrawBINVertex.kt create mode 100644 lib/src/main/kotlin/dbSave/jsonFormat/JsonRepository.kt rename lib/src/main/kotlin/{ => dbSave/neo4j}/CONTAINER.conf (100%) rename lib/src/main/kotlin/{treelib/rbTree => dbSave/neo4j}/DrawRBVertex.kt (79%) rename lib/src/main/kotlin/{DataBase.kt => dbSave/neo4j/Neo4jRepository.kt} (99%) rename lib/src/main/kotlin/{ => dbSave/neo4j}/testNeo4j.sh (59%) delete mode 100644 lib/src/main/kotlin/initNeo4j.sh delete mode 100644 lib/src/main/kotlin/loadNeo4j.sh delete mode 100644 lib/src/main/kotlin/treelib/DBNodeRB.kt delete mode 100644 lib/src/main/kotlin/treelib/Main.kt diff --git a/.gitignore b/.gitignore index 38f0b3d..16cba14 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ /build/ /lib/build/ /lib/TEST_TEST/ +/gradle/ diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 08851db..fd77a45 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -23,6 +23,8 @@ dependencies { api("org.apache.commons:commons-math3:3.6.1") implementation("com.google.guava:guava:31.1-jre") + implementation("com.google.code.gson:gson:2.8.5") + val neo4jCore = "4.0.5" implementation("org.neo4j", "neo4j-ogm-core", neo4jCore) implementation("org.neo4j", "neo4j-ogm-bolt-driver", neo4jCore) @@ -34,6 +36,7 @@ dependencies { testImplementation("org.jetbrains.kotlin:kotlin-test-junit5:1.8.10") testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.2") implementation(kotlin("stdlib-jdk8")) + } diff --git a/lib/src/main/kotlin/Controller.kt b/lib/src/main/kotlin/controller/Neo4jController.kt similarity index 91% rename from lib/src/main/kotlin/Controller.kt rename to lib/src/main/kotlin/controller/Neo4jController.kt index a59a3b0..3744351 100644 --- a/lib/src/main/kotlin/Controller.kt +++ b/lib/src/main/kotlin/controller/Neo4jController.kt @@ -1,9 +1,11 @@ +package controller -import treelib.rbTree.DrawRBVertex +import dbSave.neo4j.DrawRBVertex +import dbSave.neo4j.Neo4jRepository import treelib.rbTree.RBStruct import treelib.singleObjects.Container -class Controller { +class Neo4jController { fun initTree() { val neo4jDB = Neo4jRepository() diff --git a/lib/src/main/kotlin/dbSave/jsonFormat/DrawBINVertex.kt b/lib/src/main/kotlin/dbSave/jsonFormat/DrawBINVertex.kt new file mode 100644 index 0000000..783a1de --- /dev/null +++ b/lib/src/main/kotlin/dbSave/jsonFormat/DrawBINVertex.kt @@ -0,0 +1,9 @@ +package dbSave.jsonFormat + +import treelib.binTree.BINVertex + +class DrawBINVertex>( + value: Pack, + val x: Double = 0.0, + val y: Double = 0.0 +) : BINVertex(value) \ No newline at end of file diff --git a/lib/src/main/kotlin/dbSave/jsonFormat/JsonRepository.kt b/lib/src/main/kotlin/dbSave/jsonFormat/JsonRepository.kt new file mode 100644 index 0000000..88a1396 --- /dev/null +++ b/lib/src/main/kotlin/dbSave/jsonFormat/JsonRepository.kt @@ -0,0 +1,34 @@ +package dbSave.jsonFormat +import com.google.common.reflect.TypeToken +import com.google.gson.GsonBuilder +import java.io.File + +class JsonRepository>(private val dirPath: String) { + + init { + File(dirPath).mkdirs() + } + + fun saveChanges(preOrder: Array>, typeToken: TypeToken>>, fileName: String) { + + val gson = GsonBuilder().setPrettyPrinting().create() + val json = gson.toJson(preOrder) + + File(dirPath, fileName).run { + createNewFile() + writeText(json) + } + + val preOrd = gson.fromJson>>(json, typeToken.type) + + } + + fun exportTree(fileName: String) { + val gson = GsonBuilder().setPrettyPrinting().create() + //val json = gson.fromJson(File(dirPath, fileName).readText(), ArrayVertices::class.java) + + + } + + +} \ No newline at end of file diff --git a/lib/src/main/kotlin/CONTAINER.conf b/lib/src/main/kotlin/dbSave/neo4j/CONTAINER.conf similarity index 100% rename from lib/src/main/kotlin/CONTAINER.conf rename to lib/src/main/kotlin/dbSave/neo4j/CONTAINER.conf diff --git a/lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt b/lib/src/main/kotlin/dbSave/neo4j/DrawRBVertex.kt similarity index 79% rename from lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt rename to lib/src/main/kotlin/dbSave/neo4j/DrawRBVertex.kt index b3ee499..37100de 100644 --- a/lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt +++ b/lib/src/main/kotlin/dbSave/neo4j/DrawRBVertex.kt @@ -1,5 +1,6 @@ -package treelib.rbTree +package dbSave.neo4j +import treelib.rbTree.RBVertex import treelib.singleObjects.Markers class DrawRBVertex>( diff --git a/lib/src/main/kotlin/DataBase.kt b/lib/src/main/kotlin/dbSave/neo4j/Neo4jRepository.kt similarity index 99% rename from lib/src/main/kotlin/DataBase.kt rename to lib/src/main/kotlin/dbSave/neo4j/Neo4jRepository.kt index 809eb64..316dc4c 100644 --- a/lib/src/main/kotlin/DataBase.kt +++ b/lib/src/main/kotlin/dbSave/neo4j/Neo4jRepository.kt @@ -1,9 +1,11 @@ +package dbSave.neo4j + + import org.neo4j.driver.AuthTokens import org.neo4j.driver.Driver import org.neo4j.driver.GraphDatabase import org.neo4j.driver.TransactionContext import org.neo4j.driver.exceptions.SessionExpiredException -import treelib.rbTree.DrawRBVertex import treelib.singleObjects.Container import treelib.singleObjects.Markers import java.io.Closeable diff --git a/lib/src/main/kotlin/testNeo4j.sh b/lib/src/main/kotlin/dbSave/neo4j/testNeo4j.sh similarity index 59% rename from lib/src/main/kotlin/testNeo4j.sh rename to lib/src/main/kotlin/dbSave/neo4j/testNeo4j.sh index 87b69c4..6b07269 100644 --- a/lib/src/main/kotlin/testNeo4j.sh +++ b/lib/src/main/kotlin/dbSave/neo4j/testNeo4j.sh @@ -3,7 +3,6 @@ BASEDIR=$(realpath "$(dirname "$0")") . "${BASEDIR}/CONTAINER.conf" -# -d docker run \ -i \ --name "$CONTAINER_NAME" \ @@ -12,13 +11,3 @@ docker run \ --publish=7474:7474 --publish=7687:7687 \ --env NEO4J_AUTH=neo4j/"$PASSWORD" \ neo4j:latest \ -# -c /bin/bash -#neo4j-admin database dump neo4j --to-path=$HOME/neo4j/data:/data - -#docker ps -a - -#docker stop "$CONTAINER_NAME" - -#cp $HOME/neo4j/data:/data $HOME/ - -#docker stop neo4j:latest diff --git a/lib/src/main/kotlin/initNeo4j.sh b/lib/src/main/kotlin/initNeo4j.sh deleted file mode 100644 index e69de29..0000000 diff --git a/lib/src/main/kotlin/loadNeo4j.sh b/lib/src/main/kotlin/loadNeo4j.sh deleted file mode 100644 index d4d9fcd..0000000 --- a/lib/src/main/kotlin/loadNeo4j.sh +++ /dev/null @@ -1,8 +0,0 @@ - -BASEDIR=$(realpath "$(dirname "$0")") - -. "${BASEDIR}/CONTAINER.conf" - -docker stop "$CONTAINER_NAME" - -neo4j-admin dump --database=neo4j --to=/data/backups/ \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/DBNodeRB.kt b/lib/src/main/kotlin/treelib/DBNodeRB.kt deleted file mode 100644 index cf067e1..0000000 --- a/lib/src/main/kotlin/treelib/DBNodeRB.kt +++ /dev/null @@ -1,11 +0,0 @@ -package treelib - -import treelib.singleObjects.Markers - - -class DBNodeRB>( - val value: Pack, - val color: Markers = Markers.RED, - val x: Double = 0.0, - val y: Double = 0.0 -) diff --git a/lib/src/main/kotlin/treelib/Main.kt b/lib/src/main/kotlin/treelib/Main.kt deleted file mode 100644 index 15e0eab..0000000 --- a/lib/src/main/kotlin/treelib/Main.kt +++ /dev/null @@ -1,66 +0,0 @@ -package treelib - -import Controller -import treelib.rbTree.RBStruct -import treelib.singleObjects.Container - - -fun main() { - // 25, 15, 10, 4, 12, 22, 18, 24, 50, 35, 31, 44, 70, 66, 90 - // 4, 10, 12, 15, 18, 22, 24, 25, 31, 35, 44, 50, 66, 70, 90 - - /* - - val neo4jRep = Neo4jRepository() - val a1 = DBNodeRB(Container(Pair(1, 25))) - val a2 = DBNodeRB(Container(Pair(1, 15))) - val a3 = DBNodeRB(Container(Pair(1, 10))) - val a4 = DBNodeRB(Container(Pair(1, 4))) - val a5 = DBNodeRB(Container(Pair(1, 12))) - val a6 = DBNodeRB(Container(Pair(1, 22))) - val a7 = DBNodeRB(Container(Pair(1, 18))) - val a8 = DBNodeRB(Container(Pair(1, 24))) - val a9 = DBNodeRB(Container(Pair(1, 50))) - val a10 = DBNodeRB(Container(Pair(1, 35))) - val a11 = DBNodeRB(Container(Pair(1, 31))) - val a12 = DBNodeRB(Container(Pair(1, 44))) - val a13 = DBNodeRB(Container(Pair(1, 70))) - val a14 = DBNodeRB(Container(Pair(1, 66))) - val a15 = DBNodeRB(Container(Pair(1, 90))) - val preArr = arrayOf(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) - val inArr = arrayOf(a4, a3, a5, a2, a7, a6, a8, a1, a11, a10, a12, a9, a14, a13, a15) - neo4jRep.open("bolt://localhost:7687", "neo4j", "test-neo4j") - neo4jRep.saveChanges(preArr, inArr) - */ - - val tree = RBStruct>() - tree.insert(Container(Pair(25 , 1))) - tree.insert(Container(Pair(15 , 1))) - tree.insert(Container(Pair(50 , 1))) - tree.insert(Container(Pair(10 , 1))) - tree.insert(Container(Pair(22 , 1))) - tree.insert(Container(Pair(35 , 1))) - tree.insert(Container(Pair(70 , 1))) - tree.insert(Container(Pair(4 , 1))) - tree.insert(Container(Pair(12 , 1))) - tree.insert(Container(Pair(18 , 1))) - tree.insert(Container(Pair(24 , 1))) - tree.insert(Container(Pair(31 , 1))) - tree.insert(Container(Pair(44 , 1))) - tree.insert(Container(Pair(66 , 1))) - tree.insert(Container(Pair(90 , 1))) - val controller = Controller() - controller.saveTree(tree) - tree.insert(Container(Pair(100, 1))) - controller.saveTree(tree) - controller.initTree() - - //neo4jRep.exportRBtree() - - //neo4jRep.close() -} - -fun test() { - val cont = Controller() - cont.initTree() -} \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/binTree/BINVertex.kt b/lib/src/main/kotlin/treelib/binTree/BINVertex.kt index e660d8c..8939461 100644 --- a/lib/src/main/kotlin/treelib/binTree/BINVertex.kt +++ b/lib/src/main/kotlin/treelib/binTree/BINVertex.kt @@ -2,4 +2,4 @@ package treelib.binTree import treelib.abstractTree.Vertex -class BINVertex>(override val value: Pack): Vertex() \ No newline at end of file +open class BINVertex>(override val value: Pack): Vertex() \ No newline at end of file From b9ef5e8788dc071a4308b090b56963fa7b03326d Mon Sep 17 00:00:00 2001 From: Georgy S Date: Wed, 19 Apr 2023 03:20:10 +0300 Subject: [PATCH 67/84] feat: Implement AVLStruct.restoreStruct and BINStruct.restoreStruct. --- .../main/kotlin/controller/Neo4jController.kt | 2 +- .../kotlin/treelib/abstractTree/TreeStruct.kt | 2 +- .../main/kotlin/treelib/avlTree/AVLStruct.kt | 15 ++++++++++++--- .../main/kotlin/treelib/binTree/BINStruct.kt | 13 +++++++++++++ lib/src/main/kotlin/treelib/rbTree/RBStruct.kt | 3 +-- .../singleObjects/exceptions/IncorrectUsage.kt | 18 ++++++++++++++++++ lib/src/test/kotlin/treeTests/RBTreeTest.kt | 16 ++++++++++++++++ 7 files changed, 62 insertions(+), 7 deletions(-) create mode 100644 lib/src/main/kotlin/treelib/singleObjects/exceptions/IncorrectUsage.kt create mode 100644 lib/src/test/kotlin/treeTests/RBTreeTest.kt diff --git a/lib/src/main/kotlin/controller/Neo4jController.kt b/lib/src/main/kotlin/controller/Neo4jController.kt index 3744351..5c47c63 100644 --- a/lib/src/main/kotlin/controller/Neo4jController.kt +++ b/lib/src/main/kotlin/controller/Neo4jController.kt @@ -16,7 +16,7 @@ class Neo4jController { neo4jDB.exportRBtree() val RBtree = RBStruct>>() - RBtree.restoreTreeFromDatabase(orders.first, orders.second) + RBtree.restoreStruct(orders.first, orders.second) neo4jDB.close() } diff --git a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt index c91c6ed..d9b223b 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt @@ -15,7 +15,7 @@ abstract class TreeStruct< protected abstract var root: NodeType? - private fun getLeafForInsert(item: Pack): NodeType? { + protected fun getLeafForInsert(item: Pack): NodeType? { var currentNode: NodeType? = root ?: return null while (true) { diff --git a/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt b/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt index 7893341..b0ee0ae 100644 --- a/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt +++ b/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt @@ -1,6 +1,7 @@ package treelib.avlTree import treelib.abstractTree.balanced.BalancedTreeStruct +import treelib.singleObjects.exceptions.IncorrectUsage class AVLStruct> : BalancedTreeStruct, AVLStateContainer, AVLVertex, AVLBalancer>() { @@ -40,9 +41,9 @@ class AVLStruct> : } } - override fun toVertex(node: AVLNode): AVLVertex { - return AVLVertex(node.value, node.height) - } + override fun toVertex(node: AVLNode): AVLVertex = AVLVertex(node.value, node.height) + + fun toNode(vertex: AVLVertex): AVLNode = AVLNode(value = vertex.value, height = vertex.height) override fun createNode(item: Pack): AVLNode = AVLNode(item) @@ -56,4 +57,12 @@ class AVLStruct> : } return node } + fun > restoreStruct(preOrder: List){ + if (root != null) throw IncorrectUsage("The tree already exists") + for (vertex in preOrder){ + val currentNode = toNode(vertex) + val leaf = getLeafForInsert(currentNode.value) + linkNewNode(currentNode, leaf) + } + } } diff --git a/lib/src/main/kotlin/treelib/binTree/BINStruct.kt b/lib/src/main/kotlin/treelib/binTree/BINStruct.kt index f3bfc09..ea03cb6 100644 --- a/lib/src/main/kotlin/treelib/binTree/BINStruct.kt +++ b/lib/src/main/kotlin/treelib/binTree/BINStruct.kt @@ -1,6 +1,8 @@ package treelib.binTree import treelib.abstractTree.TreeStruct +import treelib.abstractTree.Vertex +import treelib.singleObjects.exceptions.IncorrectUsage class BINStruct> : TreeStruct, BINStateContainer, BINVertex>() { @@ -66,4 +68,15 @@ class BINStruct> : override fun insert(item: Pack) { insertItem(item).contentNode } + + private fun toNode(vertex: BINVertex): BINNode = BINNode(value = vertex.value) + + fun > restoreStruct(preOrder: List){ + if (root != null) throw IncorrectUsage("The tree already exists") + for (vertex in preOrder){ + val currentNode = toNode(vertex) + val leaf = getLeafForInsert(currentNode.value) + linkNewNode(currentNode, leaf) + } + } } diff --git a/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt b/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt index 47dd91d..999c113 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt @@ -76,7 +76,7 @@ class RBStruct> : return node } - fun > restoreTreeFromDatabase(preOrder: List, inOrder: List) { + fun > restoreStruct(preOrder: List, inOrder: List) { var inOrderIndex = 0 var preOrderIndex = 0 val set = HashSet>() @@ -117,7 +117,6 @@ class RBStruct> : stack.push(currentNode) } } - } private fun > createRBNode(drawNode: RBVertexType): RBNode { diff --git a/lib/src/main/kotlin/treelib/singleObjects/exceptions/IncorrectUsage.kt b/lib/src/main/kotlin/treelib/singleObjects/exceptions/IncorrectUsage.kt new file mode 100644 index 0000000..9fce7ef --- /dev/null +++ b/lib/src/main/kotlin/treelib/singleObjects/exceptions/IncorrectUsage.kt @@ -0,0 +1,18 @@ +package treelib.singleObjects.exceptions + +class IncorrectUsage : Exception { + constructor() : super( + "Incorrect use of the tree" + ) + + constructor(message: String) : super( + "$message", + ) + + constructor(message: String, cause: Throwable) : super( + "$message", + cause, + ) + + constructor(cause: Throwable) : super(cause) +} \ No newline at end of file diff --git a/lib/src/test/kotlin/treeTests/RBTreeTest.kt b/lib/src/test/kotlin/treeTests/RBTreeTest.kt new file mode 100644 index 0000000..fa56cc6 --- /dev/null +++ b/lib/src/test/kotlin/treeTests/RBTreeTest.kt @@ -0,0 +1,16 @@ +package treeTests + +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import treelib.rbTree.RBTree + +@DisplayName("Test: Red-Black Tree") +class RBTreeTest { + private var rbTree = RBTree() + + @Test + fun `insert two elements`(){ + rbTree.putItem(Pair(25, 1)) + rbTree.putItem(Pair(15, 1)) + } +} \ No newline at end of file From 92d064c583ebe7901ce0cbe9fdd3828e7cac50c1 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 19 Apr 2023 05:19:33 +0300 Subject: [PATCH 68/84] fix: Fix some problems after rebase onto Tests branch --- lib/build.gradle.kts | 1 + lib/src/test/kotlin/treelib/AVLTreeTest.kt | 9 +++------ lib/src/test/kotlin/treelib/BINTreeTest.kt | 11 ++++------- lib/src/test/kotlin/treelib/RBTreeTest.kt | 9 +++------ lib/src/test/kotlin/utils/TreeWrapper.kt | 10 ++++------ lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt | 3 ++- 6 files changed, 17 insertions(+), 26 deletions(-) diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index fd77a45..f528253 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -34,6 +34,7 @@ dependencies { testImplementation("io.mockk:mockk:1.13.4") testImplementation("org.jetbrains.kotlin:kotlin-test-junit5:1.8.10") + testImplementation("org.junit.jupiter:junit-jupiter-params:5.9.2") testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.2") implementation(kotlin("stdlib-jdk8")) diff --git a/lib/src/test/kotlin/treelib/AVLTreeTest.kt b/lib/src/test/kotlin/treelib/AVLTreeTest.kt index 5531d35..5915d99 100644 --- a/lib/src/test/kotlin/treelib/AVLTreeTest.kt +++ b/lib/src/test/kotlin/treelib/AVLTreeTest.kt @@ -2,10 +2,7 @@ package treelib import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.ValueSource -import treelib.avlTree.AVLNode -import treelib.avlTree.AVLStateContainer -import treelib.avlTree.AVLStruct -import treelib.avlTree.AVLTree +import treelib.avlTree.* import treelib.singleObjects.Container import utils.TreeStructWrapper import utils.TreeWrapper @@ -15,9 +12,9 @@ import kotlin.test.assertEquals class AVLTreeTest { private val tree = AVLTree() private val treeW = - TreeWrapper>, AVLStateContainer>, AVLStruct>, AVLTree>() + TreeWrapper>, AVLVertex>, AVLStateContainer>, AVLStruct>, AVLTree>() private val treeSW = - TreeStructWrapper, AVLNode>, AVLStateContainer>, AVLStruct>>() + TreeStructWrapper, AVLNode>, AVLVertex>, AVLStateContainer>, AVLStruct>>() @ParameterizedTest diff --git a/lib/src/test/kotlin/treelib/BINTreeTest.kt b/lib/src/test/kotlin/treelib/BINTreeTest.kt index 172c545..5157c95 100644 --- a/lib/src/test/kotlin/treelib/BINTreeTest.kt +++ b/lib/src/test/kotlin/treelib/BINTreeTest.kt @@ -3,21 +3,18 @@ package treelib import org.junit.jupiter.api.Test import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.ValueSource -import treelib.binTree.BINNode -import treelib.binTree.BINStateContainer -import treelib.binTree.BINStruct -import treelib.binTree.BINTree -import utils.TreeWrapper +import treelib.binTree.* import treelib.singleObjects.Container import utils.TreeStructWrapper +import utils.TreeWrapper import kotlin.test.assertEquals class BINTreeTest { private val tree = BINTree() private val treeW = - TreeWrapper>, BINStateContainer>, BINStruct>, BINTree>() + TreeWrapper>, BINVertex>, BINStateContainer>, BINStruct>, BINTree>() private val treeSW = - TreeStructWrapper, BINNode>, BINStateContainer>, BINStruct>>() + TreeStructWrapper, BINNode>, BINVertex>, BINStateContainer>, BINStruct>>() // line - 0.6, branch - 0.5, methods = 0.9 diff --git a/lib/src/test/kotlin/treelib/RBTreeTest.kt b/lib/src/test/kotlin/treelib/RBTreeTest.kt index 5a3ceee..cd7ce2a 100644 --- a/lib/src/test/kotlin/treelib/RBTreeTest.kt +++ b/lib/src/test/kotlin/treelib/RBTreeTest.kt @@ -2,10 +2,7 @@ package treelib import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.ValueSource -import treelib.rbTree.RBNode -import treelib.rbTree.RBStateContainer -import treelib.rbTree.RBStruct -import treelib.rbTree.RBTree +import treelib.rbTree.* import treelib.singleObjects.Container import treelib.singleObjects.Markers import utils.TreeStructWrapper @@ -15,9 +12,9 @@ import kotlin.test.assertEquals class RBTreeTest { private val tree = RBTree() private val treeW = - TreeWrapper>, RBStateContainer>, RBStruct>, RBTree>() + TreeWrapper>, RBVertex>, RBStateContainer>, RBStruct>, RBTree>() private val treeSW = - TreeStructWrapper, RBNode>, RBStateContainer>, RBStruct>>() + TreeStructWrapper, RBNode>, RBVertex>, RBStateContainer>, RBStruct>>() @ParameterizedTest diff --git a/lib/src/test/kotlin/utils/TreeWrapper.kt b/lib/src/test/kotlin/utils/TreeWrapper.kt index 5ca8ea7..47858d9 100644 --- a/lib/src/test/kotlin/utils/TreeWrapper.kt +++ b/lib/src/test/kotlin/utils/TreeWrapper.kt @@ -1,9 +1,6 @@ package utils -import treelib.abstractTree.Node -import treelib.abstractTree.StateContainer -import treelib.abstractTree.Tree -import treelib.abstractTree.TreeStruct +import treelib.abstractTree.* import treelib.singleObjects.Container @@ -11,9 +8,10 @@ class TreeWrapper < V : Comparable, Value, NodeType: Node, NodeType>, + VertexType: Vertex>, State: StateContainer, NodeType>, - TStruct: TreeStruct, NodeType, State>, - Wood : Tree> { + TStruct: TreeStruct, NodeType, State, VertexType>, + Wood : Tree> { fun getPrivateNode(tree: Wood, name: String = "treeStruct"): TStruct { val treeS = tree.javaClass.getDeclaredField(name) treeS.isAccessible = true diff --git a/lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt b/lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt index 7cbed69..17d52a2 100644 --- a/lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt +++ b/lib/src/test/kotlin/utils/fuzzers/AVLStructFuzzer.kt @@ -3,12 +3,13 @@ package utils.fuzzers import treelib.avlTree.AVLNode import treelib.avlTree.AVLStateContainer import treelib.avlTree.AVLStruct +import treelib.avlTree.AVLVertex import utils.AVLAnalyzer class AVLStructFuzzer>( override val baseInput: Array, override val assertMethod: (input: String) -> Unit -) : TreeStructFuzzer, AVLAnalyzer, AVLStateContainer, AVLStruct>() { +) : TreeStructFuzzer, AVLVertex, AVLAnalyzer, AVLStateContainer, AVLStruct>() { override fun createTreeStruct(): AVLStruct = AVLStruct() From 4a67e300b727f3331539142d95d60eb081f88b58 Mon Sep 17 00:00:00 2001 From: Artem Date: Sat, 15 Apr 2023 15:27:37 +0300 Subject: [PATCH 69/84] fix: Partially change exceptions --- .../kotlin/treelib/avlTree/AVLBalancer.kt | 15 +-- .../main/kotlin/treelib/rbTree/RBBalancer.kt | 99 +++++++++---------- 2 files changed, 53 insertions(+), 61 deletions(-) diff --git a/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt b/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt index 1a3afb9..5f80a87 100644 --- a/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt +++ b/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt @@ -2,8 +2,7 @@ package treelib.avlTree import treelib.abstractTree.balanced.BalancerNoParent -class AVLBalancer>(private var root: AVLNode?) : - BalancerNoParent, AVLStateContainer>() { +class AVLBalancer>(private var root: AVLNode?): BalancerNoParent, AVLStateContainer>() { private fun updateBalance(node: AVLNode?): Int { return (getHeight(node?.left) - getHeight(node?.right)).toInt() } @@ -14,16 +13,14 @@ class AVLBalancer>(private var root: AVLNode?) : private fun updateHeight(currentNode: AVLNode?) { if (currentNode != null) - currentNode.height = maxOf(getHeight(currentNode.left), getHeight(currentNode.right)) + 1u + currentNode.height = maxOf(getHeight(currentNode.left), getHeight(currentNode.right))+1u } override fun balance(stateContainer: AVLStateContainer): AVLNode { - val node = stateContainer.contentNode - ?: throw IllegalStateException("") // IllegalBaseNodeException("A non-existent node (null) was passed to the method") + val node = stateContainer.contentNode ?: throw IllegalStateException("") // IllegalBaseNodeException("A non-existent node (null) was passed to the method") root = stateContainer.root return balance(root, node.value) } - /*** In the method we pass the parent of the removed/inserted node ***/ private fun balance(currentNode: AVLNode?, value: Pack): AVLNode { if (currentNode == null) { @@ -37,8 +34,7 @@ class AVLBalancer>(private var root: AVLNode?) : val balance = updateBalance(currentNode) if (balance == -2) { if (updateBalance(currentNode.right) == 1) { - currentNode.right = currentNode.right?.let { rightRotate(it) } - ?: throw NullPointerException() // IllegalNodeStateException() + currentNode.right = currentNode.right?.let { rightRotate(it) } ?: throw NullPointerException() // IllegalNodeStateException() updateHeight(currentNode.right?.right) } val balancedNode = leftRotate(currentNode) @@ -48,8 +44,7 @@ class AVLBalancer>(private var root: AVLNode?) : } if (balance == 2) { if (updateBalance(currentNode.left) == -1) { - currentNode.left = currentNode.left?.let { leftRotate(it) } - ?: throw NullPointerException() // IllegalNodeStateException("There is no node required by the condition of the algorithm") + currentNode.left = currentNode.left?.let { leftRotate(it) } ?: throw NullPointerException() // IllegalNodeStateException("There is no node required by the condition of the algorithm") updateHeight(currentNode.left?.left) } val balanceNode = rightRotate(currentNode) diff --git a/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt b/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt index c8c4cf6..67e5427 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt @@ -2,11 +2,8 @@ package treelib.rbTree import treelib.abstractTree.balanced.BalancerParent import treelib.singleObjects.Markers -import treelib.singleObjects.exceptions.IllegalBaseNodeException -import treelib.singleObjects.exceptions.IllegalNodeStateException -class RBBalancer>(private var root: RBNode?) : - BalancerParent, RBStateContainer>() { +class RBBalancer>(private var root: RBNode?): BalancerParent, RBStateContainer>() { init { root?.color = Markers.BLACK @@ -42,13 +39,14 @@ class RBBalancer>(private var root: RBNode?) : return node.right == null && node.left == null } - override fun balance(stateContainer: RBStateContainer): RBNode { - val node = stateContainer.contentNode - ?: throw IllegalBaseNodeException() + override fun balance(stateContainer: RBStateContainer): RBNode { + val node = stateContainer.contentNode ?: + throw IllegalStateException() //IllegalBaseNodeException("A non-existent node (null) was passed to the method") val uncle = getUncle(node) when { /** node insertion case **/ - node.color == Markers.RED && node.right == null && node.left == null -> { + node.color == Markers.RED && node.right == null && node.left == null-> + { var currentNode = node if (currentNode.parent?.color == Markers.RED && uncle?.color == Markers.RED) { @@ -58,35 +56,30 @@ class RBBalancer>(private var root: RBNode?) : return getRoot(currentNode) } - var parent = - currentNode.parent ?: throw IllegalStateException() // в данном случае родитель не может быть null + var parent = currentNode.parent ?: throw IllegalStateException() // в данном случае родитель не может быть null when (parent) { parent.parent?.left -> { if (currentNode == parent.right) { leftRotate(parent) currentNode = parent } - parent = - currentNode.parent?.parent ?: throw IllegalNodeStateException() + parent = currentNode.parent?.parent ?: throw IllegalStateException() // IllegalNodeStateException() currentNode = rightRotate(parent) currentNode.color = Markers.BLACK currentNode.right?.color = Markers.RED currentNode.left?.color = Markers.RED } - parent.parent?.right -> { if (currentNode == parent.left) { rightRotate(parent) currentNode = parent } - parent = - currentNode.parent?.parent ?: throw IllegalNodeStateException() + parent = currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() currentNode = leftRotate(parent) currentNode.color = Markers.BLACK currentNode.right?.color = Markers.RED currentNode.left?.color = Markers.RED } - else -> throw IllegalStateException() // невозможное условие выполнения } if (currentNode.parent == null) @@ -94,21 +87,21 @@ class RBBalancer>(private var root: RBNode?) : return root ?: throw NullPointerException() } /** node removal cases **/ - node.color == Markers.RED && (node.right != null || node.left != null) -> { + node.color == Markers.RED && (node.right != null || node.left != null) -> + { when { /** black leaf removal case **/ node.right?.color == Markers.BLACK -> { return firstCase(node, node.left) } - node.left?.color == Markers.BLACK -> { return firstCase(node, node.right) } } } - - node.color == Markers.BLACK -> { + node.color == Markers.BLACK -> + { return when { /** red leaf removal case **/ (node.left == null && node.right == null) || @@ -117,11 +110,10 @@ class RBBalancer>(private var root: RBNode?) : getRoot(node) } /** black leaf removal case **/ - node.left == null || node.right == null -> { + node.left == null || node.right == null-> { firstCase(node, null) } - else -> throw IllegalStateException() } } @@ -135,10 +127,11 @@ class RBBalancer>(private var root: RBNode?) : val uncle = getUncle(currentNode) if (uncle?.color == Markers.RED) { currentNode.parent?.color = Markers.BLACK - currentNode = currentNode.parent?.parent ?: throw IllegalNodeStateException() + currentNode = currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() currentNode.color = Markers.RED uncle.color = Markers.BLACK - } else if (uncle != null) { + } + else if(uncle != null){ return currentNode } } @@ -158,13 +151,13 @@ class RBBalancer>(private var root: RBNode?) : getRoot(parent) } - else -> getRoot(node ?: throw IllegalNodeStateException()) + else -> getRoot(node ?: throw NullPointerException() /* IllegalNodeStateException() */) } } /** parent is red **/ private fun secondCase(parent: RBNode, node: RBNode?) { - var brother = getBrother(parent, node) ?: throw IllegalNodeStateException() + var brother = getBrother(parent, node) ?: throw NullPointerException() // IllegalNodeStateException() if (brother.color == Markers.RED) throw NullPointerException() @@ -175,48 +168,52 @@ class RBBalancer>(private var root: RBNode?) : } when (node) { - parent.left -> { + parent.left -> + { if (brother.right?.color == Markers.RED) { leftRotate(parent) brother.left?.color = Markers.RED brother.right?.color = Markers.RED brother.color = Markers.BLACK - } else if (brother.left?.color == Markers.RED) { + } + else if (brother.left?.color == Markers.RED) { brother = rightRotate(brother) leftRotate(parent) brother.left?.color = Markers.BLACK brother.left?.color = Markers.BLACK brother.color = Markers.RED - } else { + } + else { throw IllegalStateException() } } - - parent.right -> { + parent.right -> + { if (brother.left?.color == Markers.RED) { rightRotate(parent) brother.color = Markers.BLACK brother.left?.color = Markers.RED brother.right?.color = Markers.RED - } else if (brother.right?.color == Markers.RED) { + } + else if (brother.right?.color == Markers.RED) { brother = leftRotate(brother) rightRotate(parent) brother.color = Markers.RED brother.left?.color = Markers.BLACK brother.right?.color = Markers.BLACK - } else { + } + else { throw IllegalStateException() } } - else -> throw IllegalStateException() } } /** parent is black **/ private fun thirdCase(parent: RBNode, node: RBNode?) { - val brother = getBrother(parent, node) ?: throw IllegalNodeStateException() + val brother = getBrother(parent, node) ?: throw NullPointerException() // IllegalNodeStateException() when (brother.color) { Markers.RED -> thirdCaseSubFirst(brother, parent) Markers.BLACK -> thirdCaseSubSecond(brother, parent) @@ -226,8 +223,9 @@ class RBBalancer>(private var root: RBNode?) : /** black parent and red brother **/ private fun thirdCaseSubFirst(brother: RBNode, parent: RBNode) { when (brother) { - brother.parent?.left -> { - var rightBrotherSon = brother.right ?: throw IllegalNodeStateException() + brother.parent?.left -> + { + var rightBrotherSon = brother.right ?: throw NullPointerException() // IllegalNodeStateException() if (rightBrotherSon.right?.color != Markers.RED && rightBrotherSon.left?.color != Markers.RED) { rightBrotherSon.color = Markers.RED @@ -243,8 +241,7 @@ class RBBalancer>(private var root: RBNode?) : rightBrotherSon.color = Markers.RED leftRotate(rightBrotherSon) - rightBrotherSon = - rightBrotherSon.parent ?: throw IllegalNodeStateException() + rightBrotherSon = rightBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() rightBrotherSon.color = Markers.BLACK } @@ -254,21 +251,20 @@ class RBBalancer>(private var root: RBNode?) : rightRotate(parent) } } - - brother.parent?.right -> { + brother.parent?.right -> + { var leftBrotherSon = brother.left ?: throw NullPointerException() if (leftBrotherSon.right?.color != Markers.RED && leftBrotherSon.left?.color != Markers.RED) { leftBrotherSon.color = Markers.RED brother.color = Markers.BLACK - leftRotate(brother.parent ?: throw IllegalNodeStateException()) + leftRotate(brother.parent ?: throw NullPointerException()) // IllegalNodeStateException() return } if (leftBrotherSon.left?.color == Markers.RED) { rightRotate(leftBrotherSon) leftBrotherSon.color = Markers.RED - leftBrotherSon = - leftBrotherSon.parent ?: throw IllegalNodeStateException() + leftBrotherSon = leftBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() leftBrotherSon.color = Markers.BLACK } @@ -278,7 +274,6 @@ class RBBalancer>(private var root: RBNode?) : leftRotate(parent) } } - else -> throw IllegalStateException() } } @@ -294,27 +289,29 @@ class RBBalancer>(private var root: RBNode?) : return } when { - brother.left?.color == Markers.RED -> { + brother.left?.color == Markers.RED -> + { brother.left?.color = Markers.BLACK if (brother == parent.left) { rightRotate(parent) - } else { + } + else { rightRotate(brother) leftRotate(parent) } } - - brother.right?.color == Markers.RED -> { + brother.right?.color == Markers.RED -> + { brother.right?.color = Markers.BLACK if (brother == parent.right) { leftRotate(parent) - } else { + } + else { leftRotate(brother) rightRotate(parent) } } - else -> throw IllegalStateException() } } From 8b43bd144e2a3007c14c281906af30c317beddcd Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 17 Apr 2023 14:37:18 +0300 Subject: [PATCH 70/84] feat: Implement neo4j database sketch --- lib/build.gradle.kts | 10 +- lib/src/main/kotlin/CONTAINER.conf | 3 + lib/src/main/kotlin/DataBase.kt | 172 ++++++++++++++++++++++++ lib/src/main/kotlin/testNeo4j.sh | 15 +++ lib/src/main/kotlin/treelib/DBNodeRB.kt | 14 ++ 5 files changed, 208 insertions(+), 6 deletions(-) create mode 100644 lib/src/main/kotlin/CONTAINER.conf create mode 100644 lib/src/main/kotlin/DataBase.kt create mode 100644 lib/src/main/kotlin/testNeo4j.sh create mode 100644 lib/src/main/kotlin/treelib/DBNodeRB.kt diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index f528253..891ea29 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -34,13 +34,11 @@ dependencies { testImplementation("io.mockk:mockk:1.13.4") testImplementation("org.jetbrains.kotlin:kotlin-test-junit5:1.8.10") - testImplementation("org.junit.jupiter:junit-jupiter-params:5.9.2") testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.2") + testImplementation("org.junit.jupiter:junit-jupiter-params:5.9.2") implementation(kotlin("stdlib-jdk8")) - } - tasks.test { finalizedBy(tasks.jacocoTestReport) useJUnitPlatform() @@ -91,7 +89,7 @@ tasks.jacocoTestReport { tasks.jacocoTestCoverageVerification { classDirectories.setFrom( classDirectories.files.flatMap { fileTree(it) { - include("**/RBBalancer.class", "**/AVLBalancer.class", "**/BINStruct", "**/AVLStruct.class", "**/BINStruct.class") + include("**/RBBalancer.class", "**/AVLBalancer.class", "**/BINStruct") } }) dependsOn(tasks.jacocoTestReport) violationRules { @@ -99,7 +97,7 @@ tasks.jacocoTestCoverageVerification { element = "CLASS" limit { counter = "BRANCH" - minimum = 0.5.toBigDecimal() + minimum = 0.4.toBigDecimal() } } rule { @@ -113,7 +111,7 @@ tasks.jacocoTestCoverageVerification { element = "CLASS" limit { counter = "METHOD" - minimum = 0.9.toBigDecimal() + minimum = 1.0.toBigDecimal() } } } diff --git a/lib/src/main/kotlin/CONTAINER.conf b/lib/src/main/kotlin/CONTAINER.conf new file mode 100644 index 0000000..9b9fb0a --- /dev/null +++ b/lib/src/main/kotlin/CONTAINER.conf @@ -0,0 +1,3 @@ +CONTAINER_NAME=neo4j-db +PASSWORD="test-neo4j" +VOLUMEDIR="/volume" \ No newline at end of file diff --git a/lib/src/main/kotlin/DataBase.kt b/lib/src/main/kotlin/DataBase.kt new file mode 100644 index 0000000..ddc72a3 --- /dev/null +++ b/lib/src/main/kotlin/DataBase.kt @@ -0,0 +1,172 @@ + +import org.neo4j.driver.AuthTokens +import org.neo4j.driver.Driver +import org.neo4j.driver.GraphDatabase +import org.neo4j.driver.exceptions.SessionExpiredException +import treelib.DBNodeRB +import treelib.singleObjects.Markers +import java.io.Closeable +import java.io.IOException +import java.util.* + +class Neo4jRepository: Closeable { + + private var driver: Driver? = null + + fun open(uri: String, username: String, password: String) { + try { + driver = GraphDatabase.driver(uri, AuthTokens.basic(username, password)) + } catch(ex: IllegalArgumentException) { + throw IOException() + } catch(ex: SessionExpiredException) { + throw IOException() + } + + } + + // я наверное смогу получить рут, используя фильтр что-то вроде: на данный узел не указывает ни один другой узел с отношением [left_child] / [right_child] + + fun , V> saveChanges(preOrder: Array>, inOrder: Array>) { + + /*** сюда по ощущениям лучше всего добавлять именно то поддерево исходного дерева, которое было изменено ***/ + val session = driver?.session() ?: throw IOException() + + var inOrderIndex = 0 + var preOrderIndex = 0 + val set = HashSet>() + val stack = LinkedList>() + + while (preOrderIndex in preOrder.indices) { + do { + val currentNode = preOrder[preOrderIndex] + if (preOrderIndex == 0) { + session.executeWrite { tx -> + tx.run( + "MERGE(:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY})", + mutableMapOf( + "nodeValue" to currentNode.value, + "nodeKey" to currentNode.key, + "nodeColor" to currentNode.color.toString(), + "nodeX" to currentNode.x, + "nodeY" to currentNode.y + ) + ) + } + } + if (!stack.isEmpty()) { + if ( set.contains( stack.peek() ) ) { + set.remove(stack.peek()) + val parentNode = stack.pop() + session.executeWrite {tx -> + tx.run("MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + + "MERGE (parent)-[:RIGHT_SON]->(son)", + mutableMapOf( + "parentNodeValue" to parentNode.value, + "parentNodeKey" to parentNode.key, + "parentNodeColor" to parentNode.color.toString(), + "parentNodeX" to parentNode.x, + "parentNodeY" to parentNode.y, + "nodeValue" to currentNode.value, + "nodeKey" to currentNode.key, + "nodeColor" to currentNode.color.toString(), + "nodeX" to currentNode.x, + "nodeY" to currentNode.y + ) + ) + } + } + else { + val parentNode = stack.peek() + session.executeWrite {tx -> + tx.run("MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + + "MERGE (parent)-[:LEFT_SON]->(son)", + mutableMapOf( + "parentNodeValue" to parentNode.value, + "parentNodeKey" to parentNode.key, + "parentNodeColor" to parentNode.color.toString(), + "parentNodeX" to parentNode.x, + "parentNodeY" to parentNode.y, + "nodeValue" to currentNode.value, + "nodeKey" to currentNode.key, + "nodeColor" to currentNode.color.toString(), + "nodeX" to currentNode.x, + "nodeY" to currentNode.y + ) + ) + } + } + } + stack.push(currentNode) + } while (preOrder[preOrderIndex++] != inOrder[inOrderIndex] && preOrderIndex < preOrder.size) + + var currentNode: DBNodeRB? = null + + while(!stack.isEmpty() && inOrderIndex < inOrder.size && stack.peek().key == inOrder[inOrderIndex].key) { + currentNode = stack.pop() + ++inOrderIndex + } + + if (currentNode != null) { + set.add(currentNode) + stack.push(currentNode) + } + + } + + session.close() + } + + // Это скорее всего будем запускать при открытии приложения, нужно будет сразу восстановить дерево + + fun exportRBtree() { + + val session = driver?.session() ?: throw IOException() + var preOrder: List>> = listOf() + var inOrder: List>> = listOf() + + session.executeRead {tx -> + preOrder = tx.run("MATCH (node: Node) " + + "RETURN node.value, node.key, node.color, node.x, node.y ").list() + .map{ DBNodeRB( + value = it.values().get(0).toString(), + key = it.values().get(1).toString(), + color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, + x = it.values().get(3).toString().toDouble(), + y = it.values().get(4).toString().toDouble()) + } + + inOrder = tx.run("MATCH (node: Node) " + + "RETURN node.value, node.key, node.color, node.x, node.y " + + "ORDER BY node.key").list() + .map{ DBNodeRB( + value = it.values().get(0).toString(), + key = it.values().get(1).toString(), + color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, + x = it.values().get(3).toString().toDouble(), + y = it.values().get(4).toString().toDouble()) + } + } + + session.close() + + } + + override fun close() { + driver?.close() + } +} + +// neo4j-admin, backup, restore +/* +у меня есть вершины и ребра между ними, надо уметь сохранять дерево в базе, но как? +вопрос: когда заносить изменения в бд и как это реализовывать? +надо еще подумать над оптимизацией, те чтобы не пересобирать дерево в бд каждый раз, когда мы добавили за сессию всего один узел + +root = tx.run("MATCH (parent: Node)-->(son: Node) " + + "WHERE NOT ()-->(parent) " + + "RETURN parent.value, parent.key, parent.color, parent.x, parent.y").list().map {it.values()}.get(0) + */ diff --git a/lib/src/main/kotlin/testNeo4j.sh b/lib/src/main/kotlin/testNeo4j.sh new file mode 100644 index 0000000..97ad8db --- /dev/null +++ b/lib/src/main/kotlin/testNeo4j.sh @@ -0,0 +1,15 @@ + +BASEDIR=$(realpath "$(dirname "$0")") + +. "${BASEDIR}/CONTAINER.conf" + +docker run \ + --rm \ + --name "CONTAINER_NAME" \ + --volume=$HOME/neo4j/data:/data \ + --volume=$HOME/neo4j/logs:/logs \ + --publish=7474:7474 --publish=7687:7687 \ + --env NEO4J_AUTH=neo4j/"$PASSWORD" \ + neo4j:latest \ + +#docker stop neo4j:latest diff --git a/lib/src/main/kotlin/treelib/DBNodeRB.kt b/lib/src/main/kotlin/treelib/DBNodeRB.kt new file mode 100644 index 0000000..d048930 --- /dev/null +++ b/lib/src/main/kotlin/treelib/DBNodeRB.kt @@ -0,0 +1,14 @@ +package treelib + +import treelib.singleObjects.Markers + + +class DBNodeRB, V>(val value: V, + val key: K, + val color: Markers = Markers.RED, + val x: Double = 0.0, + val y: Double = 0.0) { + + + +} From f67c7f7b9839dbee9d1dae9712c0b29d8ea4bfe6 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 17 Apr 2023 19:32:32 +0300 Subject: [PATCH 71/84] feat: Implement initialize tree from DB --- lib/src/main/kotlin/Controller.kt | 50 ++++++++++++++++++++++ lib/src/main/kotlin/DataBase.kt | 55 ++++++++++++------------- lib/src/main/kotlin/treelib/DBNodeRB.kt | 9 +--- lib/src/main/kotlin/treelib/Main.kt | 39 ++++++++++++++++++ 4 files changed, 118 insertions(+), 35 deletions(-) create mode 100644 lib/src/main/kotlin/Controller.kt create mode 100644 lib/src/main/kotlin/treelib/Main.kt diff --git a/lib/src/main/kotlin/Controller.kt b/lib/src/main/kotlin/Controller.kt new file mode 100644 index 0000000..cc4e699 --- /dev/null +++ b/lib/src/main/kotlin/Controller.kt @@ -0,0 +1,50 @@ +import treelib.DBNodeRB +import treelib.rbTree.RBStruct +import treelib.rbTree.RBTree +import treelib.singleObjects.Container + +class Controller { + + fun initTree() { + val neo4jDB = Neo4jRepository() + neo4jDB.open("bolt://localhost:7687", "neo4j", "test-neo4j") + /*** orders.first = preOrder, orders.second = inOrder ***/ + val orders: Pair>>>, List>>>> = + neo4jDB.exportRBtree() + + val RBtree = RBStruct>>() + RBtree.restoreTreeFromDatabase(orders.first, orders.second) + } + + fun saveTree() { + val tree = RBTree() + tree.putItem(Pair(25, 1)) + tree.putItem(Pair(15, 1)) + tree.putItem(Pair(50, 1)) + tree.putItem(Pair(10, 1)) + tree.putItem(Pair(22, 1)) + tree.putItem(Pair(35, 1)) + tree.putItem(Pair(70, 1)) + tree.putItem(Pair(4, 1)) + tree.putItem(Pair(12, 1)) + tree.putItem(Pair(18, 1)) + tree.putItem(Pair(24, 1)) + tree.putItem(Pair(31, 1)) + tree.putItem(Pair(44, 1)) + tree.putItem(Pair(66, 1)) + tree.putItem(Pair(90, 1)) + + val neo4jDB = Neo4jRepository() + neo4jDB.open("bolt://localhost:7687", "neo4j", "test-neo4j") + + val preOrder = tree.preOrder().map { DBNodeRB(it.value, it.color) } + val inOrder = tree.inOrder().map { DBNodeRB(it.value, it.color) } + + neo4jDB.saveChanges(preOrder.toTypedArray(), inOrder.toTypedArray()) + + neo4jDB.close() + + + } + +} \ No newline at end of file diff --git a/lib/src/main/kotlin/DataBase.kt b/lib/src/main/kotlin/DataBase.kt index ddc72a3..3e94aac 100644 --- a/lib/src/main/kotlin/DataBase.kt +++ b/lib/src/main/kotlin/DataBase.kt @@ -4,6 +4,7 @@ import org.neo4j.driver.Driver import org.neo4j.driver.GraphDatabase import org.neo4j.driver.exceptions.SessionExpiredException import treelib.DBNodeRB +import treelib.singleObjects.Container import treelib.singleObjects.Markers import java.io.Closeable import java.io.IOException @@ -21,31 +22,29 @@ class Neo4jRepository: Closeable { } catch(ex: SessionExpiredException) { throw IOException() } - } - // я наверное смогу получить рут, используя фильтр что-то вроде: на данный узел не указывает ни один другой узел с отношением [left_child] / [right_child] - - fun , V> saveChanges(preOrder: Array>, inOrder: Array>) { + fun > saveChanges(preOrder: Array>, inOrder: Array>) { /*** сюда по ощущениям лучше всего добавлять именно то поддерево исходного дерева, которое было изменено ***/ val session = driver?.session() ?: throw IOException() var inOrderIndex = 0 var preOrderIndex = 0 - val set = HashSet>() - val stack = LinkedList>() + val set = HashSet>() + val stack = LinkedList>() while (preOrderIndex in preOrder.indices) { do { val currentNode = preOrder[preOrderIndex] + currentNode.value as Container<*, *> if (preOrderIndex == 0) { session.executeWrite { tx -> tx.run( "MERGE(:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY})", mutableMapOf( - "nodeValue" to currentNode.value, - "nodeKey" to currentNode.key, + "nodeValue" to currentNode.value.pair.second, + "nodeKey" to currentNode.value.pair.first, "nodeColor" to currentNode.color.toString(), "nodeX" to currentNode.x, "nodeY" to currentNode.y @@ -57,19 +56,20 @@ class Neo4jRepository: Closeable { if ( set.contains( stack.peek() ) ) { set.remove(stack.peek()) val parentNode = stack.pop() + parentNode.value as Container<*, *> session.executeWrite {tx -> tx.run("MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + "MERGE (parent)-[:RIGHT_SON]->(son)", mutableMapOf( - "parentNodeValue" to parentNode.value, - "parentNodeKey" to parentNode.key, + "parentNodeValue" to parentNode.value.pair.second, + "parentNodeKey" to parentNode.value.pair.first, "parentNodeColor" to parentNode.color.toString(), "parentNodeX" to parentNode.x, "parentNodeY" to parentNode.y, - "nodeValue" to currentNode.value, - "nodeKey" to currentNode.key, + "nodeValue" to currentNode.value.pair.second, + "nodeKey" to currentNode.value.pair.first, "nodeColor" to currentNode.color.toString(), "nodeX" to currentNode.x, "nodeY" to currentNode.y @@ -79,19 +79,20 @@ class Neo4jRepository: Closeable { } else { val parentNode = stack.peek() + parentNode.value as Container<*, *> session.executeWrite {tx -> tx.run("MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + "MERGE (parent)-[:LEFT_SON]->(son)", mutableMapOf( - "parentNodeValue" to parentNode.value, - "parentNodeKey" to parentNode.key, + "parentNodeValue" to parentNode.value.pair.second, + "parentNodeKey" to parentNode.value.pair.first, "parentNodeColor" to parentNode.color.toString(), "parentNodeX" to parentNode.x, "parentNodeY" to parentNode.y, - "nodeValue" to currentNode.value, - "nodeKey" to currentNode.key, + "nodeValue" to currentNode.value.pair.second, + "nodeKey" to currentNode.value.pair.first, "nodeColor" to currentNode.color.toString(), "nodeX" to currentNode.x, "nodeY" to currentNode.y @@ -103,9 +104,9 @@ class Neo4jRepository: Closeable { stack.push(currentNode) } while (preOrder[preOrderIndex++] != inOrder[inOrderIndex] && preOrderIndex < preOrder.size) - var currentNode: DBNodeRB? = null + var currentNode: DBNodeRB? = null - while(!stack.isEmpty() && inOrderIndex < inOrder.size && stack.peek().key == inOrder[inOrderIndex].key) { + while(!stack.isEmpty() && inOrderIndex < inOrder.size && stack.peek().value == inOrder[inOrderIndex].value) { currentNode = stack.pop() ++inOrderIndex } @@ -120,20 +121,17 @@ class Neo4jRepository: Closeable { session.close() } - // Это скорее всего будем запускать при открытии приложения, нужно будет сразу восстановить дерево - - fun exportRBtree() { + fun exportRBtree(): Pair>>>, List>>>>{ val session = driver?.session() ?: throw IOException() - var preOrder: List>> = listOf() - var inOrder: List>> = listOf() + var preOrder: List>>> = listOf() + var inOrder: List>>> = listOf() session.executeRead {tx -> preOrder = tx.run("MATCH (node: Node) " + "RETURN node.value, node.key, node.color, node.x, node.y ").list() .map{ DBNodeRB( - value = it.values().get(0).toString(), - key = it.values().get(1).toString(), + value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, x = it.values().get(3).toString().toDouble(), y = it.values().get(4).toString().toDouble()) @@ -143,16 +141,17 @@ class Neo4jRepository: Closeable { "RETURN node.value, node.key, node.color, node.x, node.y " + "ORDER BY node.key").list() .map{ DBNodeRB( - value = it.values().get(0).toString(), - key = it.values().get(1).toString(), + value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, x = it.values().get(3).toString().toDouble(), y = it.values().get(4).toString().toDouble()) } } - + session.close() + return Pair(preOrder, inOrder) + } override fun close() { diff --git a/lib/src/main/kotlin/treelib/DBNodeRB.kt b/lib/src/main/kotlin/treelib/DBNodeRB.kt index d048930..b28228f 100644 --- a/lib/src/main/kotlin/treelib/DBNodeRB.kt +++ b/lib/src/main/kotlin/treelib/DBNodeRB.kt @@ -3,12 +3,7 @@ package treelib import treelib.singleObjects.Markers -class DBNodeRB, V>(val value: V, - val key: K, +class DBNodeRB>(val value: Pack, val color: Markers = Markers.RED, val x: Double = 0.0, - val y: Double = 0.0) { - - - -} + val y: Double = 0.0) diff --git a/lib/src/main/kotlin/treelib/Main.kt b/lib/src/main/kotlin/treelib/Main.kt new file mode 100644 index 0000000..0aeb3e0 --- /dev/null +++ b/lib/src/main/kotlin/treelib/Main.kt @@ -0,0 +1,39 @@ +package treelib + +import Controller + + +fun main() { + // 25, 15, 10, 4, 12, 22, 18, 24, 50, 35, 31, 44, 70, 66, 90 + // 4, 10, 12, 15, 18, 22, 24, 25, 31, 35, 44, 50, 66, 70, 90 + + /* + + val neo4jRep = Neo4jRepository() + val a1 = DBNodeRB(Container(Pair(1, 25))) + val a2 = DBNodeRB(Container(Pair(1, 15))) + val a3 = DBNodeRB(Container(Pair(1, 10))) + val a4 = DBNodeRB(Container(Pair(1, 4))) + val a5 = DBNodeRB(Container(Pair(1, 12))) + val a6 = DBNodeRB(Container(Pair(1, 22))) + val a7 = DBNodeRB(Container(Pair(1, 18))) + val a8 = DBNodeRB(Container(Pair(1, 24))) + val a9 = DBNodeRB(Container(Pair(1, 50))) + val a10 = DBNodeRB(Container(Pair(1, 35))) + val a11 = DBNodeRB(Container(Pair(1, 31))) + val a12 = DBNodeRB(Container(Pair(1, 44))) + val a13 = DBNodeRB(Container(Pair(1, 70))) + val a14 = DBNodeRB(Container(Pair(1, 66))) + val a15 = DBNodeRB(Container(Pair(1, 90))) + val preArr = arrayOf(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) + val inArr = arrayOf(a4, a3, a5, a2, a7, a6, a8, a1, a11, a10, a12, a9, a14, a13, a15) + neo4jRep.open("bolt://localhost:7687", "neo4j", "test-neo4j") + neo4jRep.saveChanges(preArr, inArr) + */ + val controller = Controller() + controller.saveTree() + + //neo4jRep.exportRBtree() + + //neo4jRep.close() +} \ No newline at end of file From f2681ab1c269d85d063d6747f2984b52d8a9f41c Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 17 Apr 2023 20:21:27 +0300 Subject: [PATCH 72/84] fix: Fix adding to database (neo4j) --- lib/src/main/kotlin/DataBase.kt | 82 ++++++++++-------- lib/src/main/kotlin/treelib/DBNodeRB.kt | 10 ++- .../kotlin/treelib/avlTree/AVLBalancer.kt | 15 ++-- .../main/kotlin/treelib/rbTree/RBBalancer.kt | 85 ++++++++++--------- 4 files changed, 104 insertions(+), 88 deletions(-) diff --git a/lib/src/main/kotlin/DataBase.kt b/lib/src/main/kotlin/DataBase.kt index 3e94aac..e7ca4c6 100644 --- a/lib/src/main/kotlin/DataBase.kt +++ b/lib/src/main/kotlin/DataBase.kt @@ -1,4 +1,3 @@ - import org.neo4j.driver.AuthTokens import org.neo4j.driver.Driver import org.neo4j.driver.GraphDatabase @@ -10,21 +9,21 @@ import java.io.Closeable import java.io.IOException import java.util.* -class Neo4jRepository: Closeable { +class Neo4jRepository : Closeable { private var driver: Driver? = null fun open(uri: String, username: String, password: String) { try { driver = GraphDatabase.driver(uri, AuthTokens.basic(username, password)) - } catch(ex: IllegalArgumentException) { - throw IOException() - } catch(ex: SessionExpiredException) { + } catch (ex: IllegalArgumentException) { + throw IOException() + } catch (ex: SessionExpiredException) { throw IOException() } } - fun > saveChanges(preOrder: Array>, inOrder: Array>) { + fun > saveChanges(preOrder: Array>, inOrder: Array>) { /*** сюда по ощущениям лучше всего добавлять именно то поддерево исходного дерева, которое было изменено ***/ val session = driver?.session() ?: throw IOException() @@ -53,15 +52,16 @@ class Neo4jRepository: Closeable { } } if (!stack.isEmpty()) { - if ( set.contains( stack.peek() ) ) { + if (set.contains(stack.peek())) { set.remove(stack.peek()) val parentNode = stack.pop() parentNode.value as Container<*, *> - session.executeWrite {tx -> - tx.run("MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + - "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + - "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + - "MERGE (parent)-[:RIGHT_SON]->(son)", + session.executeWrite { tx -> + tx.run( + "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + + "MERGE (parent)-[:RIGHT_SON]->(son)", mutableMapOf( "parentNodeValue" to parentNode.value.pair.second, "parentNodeKey" to parentNode.value.pair.first, @@ -76,15 +76,15 @@ class Neo4jRepository: Closeable { ) ) } - } - else { + } else { val parentNode = stack.peek() parentNode.value as Container<*, *> - session.executeWrite {tx -> - tx.run("MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + - "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + - "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + - "MERGE (parent)-[:LEFT_SON]->(son)", + session.executeWrite { tx -> + tx.run( + "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + + "MERGE (parent)-[:LEFT_SON]->(son)", mutableMapOf( "parentNodeValue" to parentNode.value.pair.second, "parentNodeKey" to parentNode.value.pair.first, @@ -106,7 +106,7 @@ class Neo4jRepository: Closeable { var currentNode: DBNodeRB? = null - while(!stack.isEmpty() && inOrderIndex < inOrder.size && stack.peek().value == inOrder[inOrderIndex].value) { + while (!stack.isEmpty() && inOrderIndex < inOrder.size && stack.peek().value == inOrder[inOrderIndex].value) { currentNode = stack.pop() ++inOrderIndex } @@ -121,30 +121,38 @@ class Neo4jRepository: Closeable { session.close() } - fun exportRBtree(): Pair>>>, List>>>>{ + fun exportRBtree(): Pair>>>, List>>>> { val session = driver?.session() ?: throw IOException() var preOrder: List>>> = listOf() var inOrder: List>>> = listOf() - session.executeRead {tx -> - preOrder = tx.run("MATCH (node: Node) " + - "RETURN node.value, node.key, node.color, node.x, node.y ").list() - .map{ DBNodeRB( - value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), - color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, - x = it.values().get(3).toString().toDouble(), - y = it.values().get(4).toString().toDouble()) + session.executeRead { tx -> + preOrder = tx.run( + "MATCH (node: Node) " + + "RETURN node.value, node.key, node.color, node.x, node.y " + ).list() + .map { + DBNodeRB( + value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), + color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, + x = it.values().get(3).toString().toDouble(), + y = it.values().get(4).toString().toDouble() + ) } - inOrder = tx.run("MATCH (node: Node) " + - "RETURN node.value, node.key, node.color, node.x, node.y " + - "ORDER BY node.key").list() - .map{ DBNodeRB( - value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), - color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, - x = it.values().get(3).toString().toDouble(), - y = it.values().get(4).toString().toDouble()) + inOrder = tx.run( + "MATCH (node: Node) " + + "RETURN node.value, node.key, node.color, node.x, node.y " + + "ORDER BY node.key" + ).list() + .map { + DBNodeRB( + value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), + color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, + x = it.values().get(3).toString().toDouble(), + y = it.values().get(4).toString().toDouble() + ) } } diff --git a/lib/src/main/kotlin/treelib/DBNodeRB.kt b/lib/src/main/kotlin/treelib/DBNodeRB.kt index b28228f..cf067e1 100644 --- a/lib/src/main/kotlin/treelib/DBNodeRB.kt +++ b/lib/src/main/kotlin/treelib/DBNodeRB.kt @@ -3,7 +3,9 @@ package treelib import treelib.singleObjects.Markers -class DBNodeRB>(val value: Pack, - val color: Markers = Markers.RED, - val x: Double = 0.0, - val y: Double = 0.0) +class DBNodeRB>( + val value: Pack, + val color: Markers = Markers.RED, + val x: Double = 0.0, + val y: Double = 0.0 +) diff --git a/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt b/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt index 5f80a87..1a3afb9 100644 --- a/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt +++ b/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt @@ -2,7 +2,8 @@ package treelib.avlTree import treelib.abstractTree.balanced.BalancerNoParent -class AVLBalancer>(private var root: AVLNode?): BalancerNoParent, AVLStateContainer>() { +class AVLBalancer>(private var root: AVLNode?) : + BalancerNoParent, AVLStateContainer>() { private fun updateBalance(node: AVLNode?): Int { return (getHeight(node?.left) - getHeight(node?.right)).toInt() } @@ -13,14 +14,16 @@ class AVLBalancer>(private var root: AVLNode?): Bal private fun updateHeight(currentNode: AVLNode?) { if (currentNode != null) - currentNode.height = maxOf(getHeight(currentNode.left), getHeight(currentNode.right))+1u + currentNode.height = maxOf(getHeight(currentNode.left), getHeight(currentNode.right)) + 1u } override fun balance(stateContainer: AVLStateContainer): AVLNode { - val node = stateContainer.contentNode ?: throw IllegalStateException("") // IllegalBaseNodeException("A non-existent node (null) was passed to the method") + val node = stateContainer.contentNode + ?: throw IllegalStateException("") // IllegalBaseNodeException("A non-existent node (null) was passed to the method") root = stateContainer.root return balance(root, node.value) } + /*** In the method we pass the parent of the removed/inserted node ***/ private fun balance(currentNode: AVLNode?, value: Pack): AVLNode { if (currentNode == null) { @@ -34,7 +37,8 @@ class AVLBalancer>(private var root: AVLNode?): Bal val balance = updateBalance(currentNode) if (balance == -2) { if (updateBalance(currentNode.right) == 1) { - currentNode.right = currentNode.right?.let { rightRotate(it) } ?: throw NullPointerException() // IllegalNodeStateException() + currentNode.right = currentNode.right?.let { rightRotate(it) } + ?: throw NullPointerException() // IllegalNodeStateException() updateHeight(currentNode.right?.right) } val balancedNode = leftRotate(currentNode) @@ -44,7 +48,8 @@ class AVLBalancer>(private var root: AVLNode?): Bal } if (balance == 2) { if (updateBalance(currentNode.left) == -1) { - currentNode.left = currentNode.left?.let { leftRotate(it) } ?: throw NullPointerException() // IllegalNodeStateException("There is no node required by the condition of the algorithm") + currentNode.left = currentNode.left?.let { leftRotate(it) } + ?: throw NullPointerException() // IllegalNodeStateException("There is no node required by the condition of the algorithm") updateHeight(currentNode.left?.left) } val balanceNode = rightRotate(currentNode) diff --git a/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt b/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt index 67e5427..211e007 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt @@ -3,7 +3,8 @@ package treelib.rbTree import treelib.abstractTree.balanced.BalancerParent import treelib.singleObjects.Markers -class RBBalancer>(private var root: RBNode?): BalancerParent, RBStateContainer>() { +class RBBalancer>(private var root: RBNode?) : + BalancerParent, RBStateContainer>() { init { root?.color = Markers.BLACK @@ -39,14 +40,13 @@ class RBBalancer>(private var root: RBNode?): Balan return node.right == null && node.left == null } - override fun balance(stateContainer: RBStateContainer): RBNode { - val node = stateContainer.contentNode ?: - throw IllegalStateException() //IllegalBaseNodeException("A non-existent node (null) was passed to the method") + override fun balance(stateContainer: RBStateContainer): RBNode { + val node = stateContainer.contentNode + ?: throw IllegalStateException() //IllegalBaseNodeException("A non-existent node (null) was passed to the method") val uncle = getUncle(node) when { /** node insertion case **/ - node.color == Markers.RED && node.right == null && node.left == null-> - { + node.color == Markers.RED && node.right == null && node.left == null -> { var currentNode = node if (currentNode.parent?.color == Markers.RED && uncle?.color == Markers.RED) { @@ -56,30 +56,35 @@ class RBBalancer>(private var root: RBNode?): Balan return getRoot(currentNode) } - var parent = currentNode.parent ?: throw IllegalStateException() // в данном случае родитель не может быть null + var parent = + currentNode.parent ?: throw IllegalStateException() // в данном случае родитель не может быть null when (parent) { parent.parent?.left -> { if (currentNode == parent.right) { leftRotate(parent) currentNode = parent } - parent = currentNode.parent?.parent ?: throw IllegalStateException() // IllegalNodeStateException() + parent = + currentNode.parent?.parent ?: throw IllegalStateException() // IllegalNodeStateException() currentNode = rightRotate(parent) currentNode.color = Markers.BLACK currentNode.right?.color = Markers.RED currentNode.left?.color = Markers.RED } + parent.parent?.right -> { if (currentNode == parent.left) { rightRotate(parent) currentNode = parent } - parent = currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() + parent = + currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() currentNode = leftRotate(parent) currentNode.color = Markers.BLACK currentNode.right?.color = Markers.RED currentNode.left?.color = Markers.RED } + else -> throw IllegalStateException() // невозможное условие выполнения } if (currentNode.parent == null) @@ -87,21 +92,21 @@ class RBBalancer>(private var root: RBNode?): Balan return root ?: throw NullPointerException() } /** node removal cases **/ - node.color == Markers.RED && (node.right != null || node.left != null) -> - { + node.color == Markers.RED && (node.right != null || node.left != null) -> { when { /** black leaf removal case **/ node.right?.color == Markers.BLACK -> { return firstCase(node, node.left) } + node.left?.color == Markers.BLACK -> { return firstCase(node, node.right) } } } - node.color == Markers.BLACK -> - { + + node.color == Markers.BLACK -> { return when { /** red leaf removal case **/ (node.left == null && node.right == null) || @@ -110,10 +115,11 @@ class RBBalancer>(private var root: RBNode?): Balan getRoot(node) } /** black leaf removal case **/ - node.left == null || node.right == null-> { + node.left == null || node.right == null -> { firstCase(node, null) } + else -> throw IllegalStateException() } } @@ -130,8 +136,7 @@ class RBBalancer>(private var root: RBNode?): Balan currentNode = currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() currentNode.color = Markers.RED uncle.color = Markers.BLACK - } - else if(uncle != null){ + } else if (uncle != null) { return currentNode } } @@ -168,45 +173,41 @@ class RBBalancer>(private var root: RBNode?): Balan } when (node) { - parent.left -> - { + parent.left -> { if (brother.right?.color == Markers.RED) { leftRotate(parent) brother.left?.color = Markers.RED brother.right?.color = Markers.RED brother.color = Markers.BLACK - } - else if (brother.left?.color == Markers.RED) { + } else if (brother.left?.color == Markers.RED) { brother = rightRotate(brother) leftRotate(parent) brother.left?.color = Markers.BLACK brother.left?.color = Markers.BLACK brother.color = Markers.RED - } - else { + } else { throw IllegalStateException() } } - parent.right -> - { + + parent.right -> { if (brother.left?.color == Markers.RED) { rightRotate(parent) brother.color = Markers.BLACK brother.left?.color = Markers.RED brother.right?.color = Markers.RED - } - else if (brother.right?.color == Markers.RED) { + } else if (brother.right?.color == Markers.RED) { brother = leftRotate(brother) rightRotate(parent) brother.color = Markers.RED brother.left?.color = Markers.BLACK brother.right?.color = Markers.BLACK - } - else { + } else { throw IllegalStateException() } } + else -> throw IllegalStateException() } } @@ -223,8 +224,7 @@ class RBBalancer>(private var root: RBNode?): Balan /** black parent and red brother **/ private fun thirdCaseSubFirst(brother: RBNode, parent: RBNode) { when (brother) { - brother.parent?.left -> - { + brother.parent?.left -> { var rightBrotherSon = brother.right ?: throw NullPointerException() // IllegalNodeStateException() if (rightBrotherSon.right?.color != Markers.RED && rightBrotherSon.left?.color != Markers.RED) { @@ -241,7 +241,8 @@ class RBBalancer>(private var root: RBNode?): Balan rightBrotherSon.color = Markers.RED leftRotate(rightBrotherSon) - rightBrotherSon = rightBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() + rightBrotherSon = + rightBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() rightBrotherSon.color = Markers.BLACK } @@ -251,8 +252,8 @@ class RBBalancer>(private var root: RBNode?): Balan rightRotate(parent) } } - brother.parent?.right -> - { + + brother.parent?.right -> { var leftBrotherSon = brother.left ?: throw NullPointerException() if (leftBrotherSon.right?.color != Markers.RED && leftBrotherSon.left?.color != Markers.RED) { leftBrotherSon.color = Markers.RED @@ -264,7 +265,8 @@ class RBBalancer>(private var root: RBNode?): Balan if (leftBrotherSon.left?.color == Markers.RED) { rightRotate(leftBrotherSon) leftBrotherSon.color = Markers.RED - leftBrotherSon = leftBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() + leftBrotherSon = + leftBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() leftBrotherSon.color = Markers.BLACK } @@ -274,6 +276,7 @@ class RBBalancer>(private var root: RBNode?): Balan leftRotate(parent) } } + else -> throw IllegalStateException() } } @@ -289,29 +292,27 @@ class RBBalancer>(private var root: RBNode?): Balan return } when { - brother.left?.color == Markers.RED -> - { + brother.left?.color == Markers.RED -> { brother.left?.color = Markers.BLACK if (brother == parent.left) { rightRotate(parent) - } - else { + } else { rightRotate(brother) leftRotate(parent) } } - brother.right?.color == Markers.RED -> - { + + brother.right?.color == Markers.RED -> { brother.right?.color = Markers.BLACK if (brother == parent.right) { leftRotate(parent) - } - else { + } else { leftRotate(brother) rightRotate(parent) } } + else -> throw IllegalStateException() } } From 95afccd6041bfd3e94b63dce254a278d246ab5ac Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 18 Apr 2023 21:33:22 +0300 Subject: [PATCH 73/84] fix: Fix database interaction --- lib/src/main/kotlin/Controller.kt | 35 +--- lib/src/main/kotlin/DataBase.kt | 186 ++++++++++-------- lib/src/main/kotlin/initNeo4j.sh | 0 lib/src/main/kotlin/loadNeo4j.sh | 8 + lib/src/main/kotlin/testNeo4j.sh | 13 +- lib/src/main/kotlin/treelib/Main.kt | 29 ++- .../kotlin/treelib/rbTree/DrawRBVertex.kt | 10 + .../main/kotlin/treelib/rbTree/RBBalancer.kt | 24 +-- 8 files changed, 187 insertions(+), 118 deletions(-) create mode 100644 lib/src/main/kotlin/initNeo4j.sh create mode 100644 lib/src/main/kotlin/loadNeo4j.sh create mode 100644 lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt diff --git a/lib/src/main/kotlin/Controller.kt b/lib/src/main/kotlin/Controller.kt index cc4e699..a59a3b0 100644 --- a/lib/src/main/kotlin/Controller.kt +++ b/lib/src/main/kotlin/Controller.kt @@ -1,6 +1,6 @@ -import treelib.DBNodeRB + +import treelib.rbTree.DrawRBVertex import treelib.rbTree.RBStruct -import treelib.rbTree.RBTree import treelib.singleObjects.Container class Controller { @@ -8,43 +8,28 @@ class Controller { fun initTree() { val neo4jDB = Neo4jRepository() neo4jDB.open("bolt://localhost:7687", "neo4j", "test-neo4j") + /*** orders.first = preOrder, orders.second = inOrder ***/ - val orders: Pair>>>, List>>>> = + val orders: Pair>>>, List>>>> = neo4jDB.exportRBtree() val RBtree = RBStruct>>() RBtree.restoreTreeFromDatabase(orders.first, orders.second) + neo4jDB.close() } - fun saveTree() { - val tree = RBTree() - tree.putItem(Pair(25, 1)) - tree.putItem(Pair(15, 1)) - tree.putItem(Pair(50, 1)) - tree.putItem(Pair(10, 1)) - tree.putItem(Pair(22, 1)) - tree.putItem(Pair(35, 1)) - tree.putItem(Pair(70, 1)) - tree.putItem(Pair(4, 1)) - tree.putItem(Pair(12, 1)) - tree.putItem(Pair(18, 1)) - tree.putItem(Pair(24, 1)) - tree.putItem(Pair(31, 1)) - tree.putItem(Pair(44, 1)) - tree.putItem(Pair(66, 1)) - tree.putItem(Pair(90, 1)) - + fun > saveTree(tree: RBStruct) { val neo4jDB = Neo4jRepository() neo4jDB.open("bolt://localhost:7687", "neo4j", "test-neo4j") - val preOrder = tree.preOrder().map { DBNodeRB(it.value, it.color) } - val inOrder = tree.inOrder().map { DBNodeRB(it.value, it.color) } + // вот тут плохо, потому что тут надо получать не base nodes, а для рисовалки - neo4jDB.saveChanges(preOrder.toTypedArray(), inOrder.toTypedArray()) + val preOrder = tree.preOrder().map { DrawRBVertex(it.value, it.color) } + val inOrder = tree.inOrder().map { DrawRBVertex(it.value, it.color) } + neo4jDB.saveChanges(preOrder.toTypedArray(), inOrder.toTypedArray()) neo4jDB.close() - } } \ No newline at end of file diff --git a/lib/src/main/kotlin/DataBase.kt b/lib/src/main/kotlin/DataBase.kt index e7ca4c6..809eb64 100644 --- a/lib/src/main/kotlin/DataBase.kt +++ b/lib/src/main/kotlin/DataBase.kt @@ -1,8 +1,9 @@ import org.neo4j.driver.AuthTokens import org.neo4j.driver.Driver import org.neo4j.driver.GraphDatabase +import org.neo4j.driver.TransactionContext import org.neo4j.driver.exceptions.SessionExpiredException -import treelib.DBNodeRB +import treelib.rbTree.DrawRBVertex import treelib.singleObjects.Container import treelib.singleObjects.Markers import java.io.Closeable @@ -23,88 +24,50 @@ class Neo4jRepository : Closeable { } } - fun > saveChanges(preOrder: Array>, inOrder: Array>) { + fun > saveChanges(preOrder: Array>, inOrder: Array>) { /*** сюда по ощущениям лучше всего добавлять именно то поддерево исходного дерева, которое было изменено ***/ val session = driver?.session() ?: throw IOException() var inOrderIndex = 0 var preOrderIndex = 0 - val set = HashSet>() - val stack = LinkedList>() + val set = HashSet>() + val stack = LinkedList>() + var id = 0 while (preOrderIndex in preOrder.indices) { do { val currentNode = preOrder[preOrderIndex] - currentNode.value as Container<*, *> + //currentNode.value as Container<*, *> if (preOrderIndex == 0) { session.executeWrite { tx -> - tx.run( - "MERGE(:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY})", - mutableMapOf( - "nodeValue" to currentNode.value.pair.second, - "nodeKey" to currentNode.value.pair.first, - "nodeColor" to currentNode.color.toString(), - "nodeX" to currentNode.x, - "nodeY" to currentNode.y - ) - ) + cleanDB(tx) + createRoot(tx, currentNode, id) } + ++id } if (!stack.isEmpty()) { if (set.contains(stack.peek())) { set.remove(stack.peek()) val parentNode = stack.pop() - parentNode.value as Container<*, *> + //parentNode.value as Container<*, *> session.executeWrite { tx -> - tx.run( - "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + - "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + - "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + - "MERGE (parent)-[:RIGHT_SON]->(son)", - mutableMapOf( - "parentNodeValue" to parentNode.value.pair.second, - "parentNodeKey" to parentNode.value.pair.first, - "parentNodeColor" to parentNode.color.toString(), - "parentNodeX" to parentNode.x, - "parentNodeY" to parentNode.y, - "nodeValue" to currentNode.value.pair.second, - "nodeKey" to currentNode.value.pair.first, - "nodeColor" to currentNode.color.toString(), - "nodeX" to currentNode.x, - "nodeY" to currentNode.y - ) - ) + createRightSon(tx, parentNode, currentNode, id) } + ++id } else { val parentNode = stack.peek() parentNode.value as Container<*, *> session.executeWrite { tx -> - tx.run( - "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + - "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + - "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY}) " + - "MERGE (parent)-[:LEFT_SON]->(son)", - mutableMapOf( - "parentNodeValue" to parentNode.value.pair.second, - "parentNodeKey" to parentNode.value.pair.first, - "parentNodeColor" to parentNode.color.toString(), - "parentNodeX" to parentNode.x, - "parentNodeY" to parentNode.y, - "nodeValue" to currentNode.value.pair.second, - "nodeKey" to currentNode.value.pair.first, - "nodeColor" to currentNode.color.toString(), - "nodeX" to currentNode.x, - "nodeY" to currentNode.y - ) - ) + createLeftSon(tx, parentNode, currentNode, id) } + ++id } } stack.push(currentNode) - } while (preOrder[preOrderIndex++] != inOrder[inOrderIndex] && preOrderIndex < preOrder.size) + } while (preOrder[preOrderIndex++].value != inOrder[inOrderIndex].value && preOrderIndex < preOrder.size) - var currentNode: DBNodeRB? = null + var currentNode: DrawRBVertex? = null while (!stack.isEmpty() && inOrderIndex < inOrder.size && stack.peek().value == inOrder[inOrderIndex].value) { currentNode = stack.pop() @@ -121,23 +84,26 @@ class Neo4jRepository : Closeable { session.close() } - fun exportRBtree(): Pair>>>, List>>>> { + fun exportRBtree(): Pair>>>, List>>>> { + + /*** Вот тут короче надо обращаться к neo4j с темЮ чтобы она инициализировала себя как-то ***/ val session = driver?.session() ?: throw IOException() - var preOrder: List>>> = listOf() - var inOrder: List>>> = listOf() + var preOrder: List>>> = listOf() + var inOrder: List>>> = listOf() session.executeRead { tx -> preOrder = tx.run( "MATCH (node: Node) " + - "RETURN node.value, node.key, node.color, node.x, node.y " + "RETURN node.value, node.key, node.color, node.x, node.y " + + "ORDER BY node.id" ).list() .map { - DBNodeRB( - value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), - color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, - x = it.values().get(3).toString().toDouble(), - y = it.values().get(4).toString().toDouble() + DrawRBVertex( + value = Container(Pair(it.values()[1].toString(), it.values()[0].toString())), + color = if (it.values()[2].toString() == """RED""") Markers.RED else Markers.BLACK, + x = it.values()[3].toString().toDouble(), + y = it.values()[4].toString().toDouble() ) } @@ -147,11 +113,11 @@ class Neo4jRepository : Closeable { "ORDER BY node.key" ).list() .map { - DBNodeRB( - value = Container(Pair(it.values().get(0).toString(), it.values().get(1).toString())), - color = if (it.values().get(2).toString() == """RED""") Markers.RED else Markers.BLACK, - x = it.values().get(3).toString().toDouble(), - y = it.values().get(4).toString().toDouble() + DrawRBVertex( + value = Container(Pair(it.values()[1].toString(), it.values()[0].toString())), + color = if (it.values()[2].toString() == """RED""") Markers.RED else Markers.BLACK, + x = it.values()[3].toString().toDouble(), + y = it.values()[4].toString().toDouble() ) } } @@ -162,18 +128,80 @@ class Neo4jRepository : Closeable { } + private fun cleanDB(tx: TransactionContext) { + tx.run("MATCH (n: Node) DETACH DELETE n") + } + + private fun > createRoot(tx: TransactionContext, rootNode: DrawRBVertex, id: Int) { + rootNode.value as Container<*, *> + tx.run( + "MERGE(:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY, id: \$nodeID})", + mutableMapOf( + "nodeValue" to rootNode.value.pair.second, + "nodeKey" to rootNode.value.pair.first, + "nodeColor" to rootNode.color.toString(), + "nodeX" to rootNode.x, + "nodeY" to rootNode.y, + "nodeID" to id + ) + ) + } + + private fun > createRightSon( + tx: TransactionContext, parentNode: DrawRBVertex, + currentNode: DrawRBVertex, id: Int + ) { + parentNode.value as Container<*, *> + currentNode.value as Container<*, *> + tx.run( + "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY, id: \$nodeID}) " + + "MERGE (parent)-[:RIGHT_SON]->(son)", + mutableMapOf( + "parentNodeValue" to parentNode.value.pair.second, + "parentNodeKey" to parentNode.value.pair.first, + "parentNodeColor" to parentNode.color.toString(), + "parentNodeX" to parentNode.x, + "parentNodeY" to parentNode.y, + "nodeValue" to currentNode.value.pair.second, + "nodeKey" to currentNode.value.pair.first, + "nodeColor" to currentNode.color.toString(), + "nodeX" to currentNode.x, + "nodeY" to currentNode.y, + "nodeID" to id, + ) + ) + } + + private fun > createLeftSon( + tx: TransactionContext, parentNode: DrawRBVertex, + currentNode: DrawRBVertex, id: Int + ) { + parentNode.value as Container<*, *> + currentNode.value as Container<*, *> + tx.run( + "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + + "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + + "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY, id: \$nodeID}) " + + "MERGE (parent)-[:LEFT_SON]->(son)", + mutableMapOf( + "parentNodeValue" to parentNode.value.pair.second, + "parentNodeKey" to parentNode.value.pair.first, + "parentNodeColor" to parentNode.color.toString(), + "parentNodeX" to parentNode.x, + "parentNodeY" to parentNode.y, + "nodeValue" to currentNode.value.pair.second, + "nodeKey" to currentNode.value.pair.first, + "nodeColor" to currentNode.color.toString(), + "nodeX" to currentNode.x, + "nodeY" to currentNode.y, + "nodeID" to id, + ) + ) + } + override fun close() { driver?.close() } } - -// neo4j-admin, backup, restore -/* -у меня есть вершины и ребра между ними, надо уметь сохранять дерево в базе, но как? -вопрос: когда заносить изменения в бд и как это реализовывать? -надо еще подумать над оптимизацией, те чтобы не пересобирать дерево в бд каждый раз, когда мы добавили за сессию всего один узел - -root = tx.run("MATCH (parent: Node)-->(son: Node) " + - "WHERE NOT ()-->(parent) " + - "RETURN parent.value, parent.key, parent.color, parent.x, parent.y").list().map {it.values()}.get(0) - */ diff --git a/lib/src/main/kotlin/initNeo4j.sh b/lib/src/main/kotlin/initNeo4j.sh new file mode 100644 index 0000000..e69de29 diff --git a/lib/src/main/kotlin/loadNeo4j.sh b/lib/src/main/kotlin/loadNeo4j.sh new file mode 100644 index 0000000..d4d9fcd --- /dev/null +++ b/lib/src/main/kotlin/loadNeo4j.sh @@ -0,0 +1,8 @@ + +BASEDIR=$(realpath "$(dirname "$0")") + +. "${BASEDIR}/CONTAINER.conf" + +docker stop "$CONTAINER_NAME" + +neo4j-admin dump --database=neo4j --to=/data/backups/ \ No newline at end of file diff --git a/lib/src/main/kotlin/testNeo4j.sh b/lib/src/main/kotlin/testNeo4j.sh index 97ad8db..87b69c4 100644 --- a/lib/src/main/kotlin/testNeo4j.sh +++ b/lib/src/main/kotlin/testNeo4j.sh @@ -3,13 +3,22 @@ BASEDIR=$(realpath "$(dirname "$0")") . "${BASEDIR}/CONTAINER.conf" +# -d docker run \ - --rm \ - --name "CONTAINER_NAME" \ + -i \ + --name "$CONTAINER_NAME" \ --volume=$HOME/neo4j/data:/data \ --volume=$HOME/neo4j/logs:/logs \ --publish=7474:7474 --publish=7687:7687 \ --env NEO4J_AUTH=neo4j/"$PASSWORD" \ neo4j:latest \ +# -c /bin/bash +#neo4j-admin database dump neo4j --to-path=$HOME/neo4j/data:/data + +#docker ps -a + +#docker stop "$CONTAINER_NAME" + +#cp $HOME/neo4j/data:/data $HOME/ #docker stop neo4j:latest diff --git a/lib/src/main/kotlin/treelib/Main.kt b/lib/src/main/kotlin/treelib/Main.kt index 0aeb3e0..15e0eab 100644 --- a/lib/src/main/kotlin/treelib/Main.kt +++ b/lib/src/main/kotlin/treelib/Main.kt @@ -1,6 +1,8 @@ package treelib import Controller +import treelib.rbTree.RBStruct +import treelib.singleObjects.Container fun main() { @@ -30,10 +32,35 @@ fun main() { neo4jRep.open("bolt://localhost:7687", "neo4j", "test-neo4j") neo4jRep.saveChanges(preArr, inArr) */ + + val tree = RBStruct>() + tree.insert(Container(Pair(25 , 1))) + tree.insert(Container(Pair(15 , 1))) + tree.insert(Container(Pair(50 , 1))) + tree.insert(Container(Pair(10 , 1))) + tree.insert(Container(Pair(22 , 1))) + tree.insert(Container(Pair(35 , 1))) + tree.insert(Container(Pair(70 , 1))) + tree.insert(Container(Pair(4 , 1))) + tree.insert(Container(Pair(12 , 1))) + tree.insert(Container(Pair(18 , 1))) + tree.insert(Container(Pair(24 , 1))) + tree.insert(Container(Pair(31 , 1))) + tree.insert(Container(Pair(44 , 1))) + tree.insert(Container(Pair(66 , 1))) + tree.insert(Container(Pair(90 , 1))) val controller = Controller() - controller.saveTree() + controller.saveTree(tree) + tree.insert(Container(Pair(100, 1))) + controller.saveTree(tree) + controller.initTree() //neo4jRep.exportRBtree() //neo4jRep.close() +} + +fun test() { + val cont = Controller() + cont.initTree() } \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt b/lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt new file mode 100644 index 0000000..b3ee499 --- /dev/null +++ b/lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt @@ -0,0 +1,10 @@ +package treelib.rbTree + +import treelib.singleObjects.Markers + +class DrawRBVertex>( + value: Pack, + color: Markers, + val x: Double = 0.0, + val y: Double = 0.0 +) : RBVertex(value, color) \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt b/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt index 211e007..c8c4cf6 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt @@ -2,6 +2,8 @@ package treelib.rbTree import treelib.abstractTree.balanced.BalancerParent import treelib.singleObjects.Markers +import treelib.singleObjects.exceptions.IllegalBaseNodeException +import treelib.singleObjects.exceptions.IllegalNodeStateException class RBBalancer>(private var root: RBNode?) : BalancerParent, RBStateContainer>() { @@ -42,7 +44,7 @@ class RBBalancer>(private var root: RBNode?) : override fun balance(stateContainer: RBStateContainer): RBNode { val node = stateContainer.contentNode - ?: throw IllegalStateException() //IllegalBaseNodeException("A non-existent node (null) was passed to the method") + ?: throw IllegalBaseNodeException() val uncle = getUncle(node) when { /** node insertion case **/ @@ -65,7 +67,7 @@ class RBBalancer>(private var root: RBNode?) : currentNode = parent } parent = - currentNode.parent?.parent ?: throw IllegalStateException() // IllegalNodeStateException() + currentNode.parent?.parent ?: throw IllegalNodeStateException() currentNode = rightRotate(parent) currentNode.color = Markers.BLACK currentNode.right?.color = Markers.RED @@ -78,7 +80,7 @@ class RBBalancer>(private var root: RBNode?) : currentNode = parent } parent = - currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() + currentNode.parent?.parent ?: throw IllegalNodeStateException() currentNode = leftRotate(parent) currentNode.color = Markers.BLACK currentNode.right?.color = Markers.RED @@ -133,7 +135,7 @@ class RBBalancer>(private var root: RBNode?) : val uncle = getUncle(currentNode) if (uncle?.color == Markers.RED) { currentNode.parent?.color = Markers.BLACK - currentNode = currentNode.parent?.parent ?: throw NullPointerException() // IllegalNodeStateException() + currentNode = currentNode.parent?.parent ?: throw IllegalNodeStateException() currentNode.color = Markers.RED uncle.color = Markers.BLACK } else if (uncle != null) { @@ -156,13 +158,13 @@ class RBBalancer>(private var root: RBNode?) : getRoot(parent) } - else -> getRoot(node ?: throw NullPointerException() /* IllegalNodeStateException() */) + else -> getRoot(node ?: throw IllegalNodeStateException()) } } /** parent is red **/ private fun secondCase(parent: RBNode, node: RBNode?) { - var brother = getBrother(parent, node) ?: throw NullPointerException() // IllegalNodeStateException() + var brother = getBrother(parent, node) ?: throw IllegalNodeStateException() if (brother.color == Markers.RED) throw NullPointerException() @@ -214,7 +216,7 @@ class RBBalancer>(private var root: RBNode?) : /** parent is black **/ private fun thirdCase(parent: RBNode, node: RBNode?) { - val brother = getBrother(parent, node) ?: throw NullPointerException() // IllegalNodeStateException() + val brother = getBrother(parent, node) ?: throw IllegalNodeStateException() when (brother.color) { Markers.RED -> thirdCaseSubFirst(brother, parent) Markers.BLACK -> thirdCaseSubSecond(brother, parent) @@ -225,7 +227,7 @@ class RBBalancer>(private var root: RBNode?) : private fun thirdCaseSubFirst(brother: RBNode, parent: RBNode) { when (brother) { brother.parent?.left -> { - var rightBrotherSon = brother.right ?: throw NullPointerException() // IllegalNodeStateException() + var rightBrotherSon = brother.right ?: throw IllegalNodeStateException() if (rightBrotherSon.right?.color != Markers.RED && rightBrotherSon.left?.color != Markers.RED) { rightBrotherSon.color = Markers.RED @@ -242,7 +244,7 @@ class RBBalancer>(private var root: RBNode?) : leftRotate(rightBrotherSon) rightBrotherSon = - rightBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() + rightBrotherSon.parent ?: throw IllegalNodeStateException() rightBrotherSon.color = Markers.BLACK } @@ -258,7 +260,7 @@ class RBBalancer>(private var root: RBNode?) : if (leftBrotherSon.right?.color != Markers.RED && leftBrotherSon.left?.color != Markers.RED) { leftBrotherSon.color = Markers.RED brother.color = Markers.BLACK - leftRotate(brother.parent ?: throw NullPointerException()) // IllegalNodeStateException() + leftRotate(brother.parent ?: throw IllegalNodeStateException()) return } @@ -266,7 +268,7 @@ class RBBalancer>(private var root: RBNode?) : rightRotate(leftBrotherSon) leftBrotherSon.color = Markers.RED leftBrotherSon = - leftBrotherSon.parent ?: throw NullPointerException() // IllegalNodeStateException() + leftBrotherSon.parent ?: throw IllegalNodeStateException() leftBrotherSon.color = Markers.BLACK } From c7c39d8383311a3d2d2212e0f0c404bb9e0029e7 Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 18 Apr 2023 22:37:53 +0300 Subject: [PATCH 74/84] fix: Fix tree class definitions --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 16cba14..2b25734 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,4 @@ /build/ /lib/build/ /lib/TEST_TEST/ -/gradle/ +/gradle/ \ No newline at end of file From 74fb9789e51f002c0d33781935dd248df90a227c Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 18 Apr 2023 23:36:42 +0300 Subject: [PATCH 75/84] refactor: Rename some methods in test classes --- lib/build.gradle.kts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 891ea29..d0c56d7 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -89,7 +89,7 @@ tasks.jacocoTestReport { tasks.jacocoTestCoverageVerification { classDirectories.setFrom( classDirectories.files.flatMap { fileTree(it) { - include("**/RBBalancer.class", "**/AVLBalancer.class", "**/BINStruct") + include("**/RBBalancer.class", "**/AVLBalancer.class", "**/BINStruct", "**/AVLStruct.class", "**/BINStruct.class") } }) dependsOn(tasks.jacocoTestReport) violationRules { @@ -97,7 +97,7 @@ tasks.jacocoTestCoverageVerification { element = "CLASS" limit { counter = "BRANCH" - minimum = 0.4.toBigDecimal() + minimum = 0.5.toBigDecimal() } } rule { @@ -111,7 +111,7 @@ tasks.jacocoTestCoverageVerification { element = "CLASS" limit { counter = "METHOD" - minimum = 1.0.toBigDecimal() + minimum = 0.9.toBigDecimal() } } } From b43054a73c8020b1b535bb4f3e11cc3c4288ec8c Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 19 Apr 2023 04:39:37 +0300 Subject: [PATCH 76/84] feat: Implement sketch of jsonRepository --- .gitignore | 2 +- lib/build.gradle.kts | 1 + lib/src/main/kotlin/CONTAINER.conf | 3 - lib/src/main/kotlin/Controller.kt | 35 --- lib/src/main/kotlin/DataBase.kt | 207 ------------------ .../main/kotlin/controller/Neo4jController.kt | 2 +- lib/src/main/kotlin/initNeo4j.sh | 0 lib/src/main/kotlin/loadNeo4j.sh | 8 - lib/src/main/kotlin/testNeo4j.sh | 24 -- lib/src/main/kotlin/treelib/DBNodeRB.kt | 11 - lib/src/main/kotlin/treelib/Main.kt | 66 ------ .../kotlin/treelib/rbTree/DrawRBVertex.kt | 10 - 12 files changed, 3 insertions(+), 366 deletions(-) delete mode 100644 lib/src/main/kotlin/CONTAINER.conf delete mode 100644 lib/src/main/kotlin/Controller.kt delete mode 100644 lib/src/main/kotlin/DataBase.kt delete mode 100644 lib/src/main/kotlin/initNeo4j.sh delete mode 100644 lib/src/main/kotlin/loadNeo4j.sh delete mode 100644 lib/src/main/kotlin/testNeo4j.sh delete mode 100644 lib/src/main/kotlin/treelib/DBNodeRB.kt delete mode 100644 lib/src/main/kotlin/treelib/Main.kt delete mode 100644 lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt diff --git a/.gitignore b/.gitignore index 2b25734..16cba14 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,4 @@ /build/ /lib/build/ /lib/TEST_TEST/ -/gradle/ \ No newline at end of file +/gradle/ diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index d0c56d7..9d6fcd3 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -37,6 +37,7 @@ dependencies { testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.2") testImplementation("org.junit.jupiter:junit-jupiter-params:5.9.2") implementation(kotlin("stdlib-jdk8")) + } tasks.test { diff --git a/lib/src/main/kotlin/CONTAINER.conf b/lib/src/main/kotlin/CONTAINER.conf deleted file mode 100644 index 9b9fb0a..0000000 --- a/lib/src/main/kotlin/CONTAINER.conf +++ /dev/null @@ -1,3 +0,0 @@ -CONTAINER_NAME=neo4j-db -PASSWORD="test-neo4j" -VOLUMEDIR="/volume" \ No newline at end of file diff --git a/lib/src/main/kotlin/Controller.kt b/lib/src/main/kotlin/Controller.kt deleted file mode 100644 index a59a3b0..0000000 --- a/lib/src/main/kotlin/Controller.kt +++ /dev/null @@ -1,35 +0,0 @@ - -import treelib.rbTree.DrawRBVertex -import treelib.rbTree.RBStruct -import treelib.singleObjects.Container - -class Controller { - - fun initTree() { - val neo4jDB = Neo4jRepository() - neo4jDB.open("bolt://localhost:7687", "neo4j", "test-neo4j") - - /*** orders.first = preOrder, orders.second = inOrder ***/ - val orders: Pair>>>, List>>>> = - neo4jDB.exportRBtree() - - val RBtree = RBStruct>>() - RBtree.restoreTreeFromDatabase(orders.first, orders.second) - neo4jDB.close() - } - - fun > saveTree(tree: RBStruct) { - val neo4jDB = Neo4jRepository() - neo4jDB.open("bolt://localhost:7687", "neo4j", "test-neo4j") - - // вот тут плохо, потому что тут надо получать не base nodes, а для рисовалки - - val preOrder = tree.preOrder().map { DrawRBVertex(it.value, it.color) } - val inOrder = tree.inOrder().map { DrawRBVertex(it.value, it.color) } - - neo4jDB.saveChanges(preOrder.toTypedArray(), inOrder.toTypedArray()) - neo4jDB.close() - - } - -} \ No newline at end of file diff --git a/lib/src/main/kotlin/DataBase.kt b/lib/src/main/kotlin/DataBase.kt deleted file mode 100644 index 809eb64..0000000 --- a/lib/src/main/kotlin/DataBase.kt +++ /dev/null @@ -1,207 +0,0 @@ -import org.neo4j.driver.AuthTokens -import org.neo4j.driver.Driver -import org.neo4j.driver.GraphDatabase -import org.neo4j.driver.TransactionContext -import org.neo4j.driver.exceptions.SessionExpiredException -import treelib.rbTree.DrawRBVertex -import treelib.singleObjects.Container -import treelib.singleObjects.Markers -import java.io.Closeable -import java.io.IOException -import java.util.* - -class Neo4jRepository : Closeable { - - private var driver: Driver? = null - - fun open(uri: String, username: String, password: String) { - try { - driver = GraphDatabase.driver(uri, AuthTokens.basic(username, password)) - } catch (ex: IllegalArgumentException) { - throw IOException() - } catch (ex: SessionExpiredException) { - throw IOException() - } - } - - fun > saveChanges(preOrder: Array>, inOrder: Array>) { - - /*** сюда по ощущениям лучше всего добавлять именно то поддерево исходного дерева, которое было изменено ***/ - val session = driver?.session() ?: throw IOException() - - var inOrderIndex = 0 - var preOrderIndex = 0 - val set = HashSet>() - val stack = LinkedList>() - var id = 0 - - while (preOrderIndex in preOrder.indices) { - do { - val currentNode = preOrder[preOrderIndex] - //currentNode.value as Container<*, *> - if (preOrderIndex == 0) { - session.executeWrite { tx -> - cleanDB(tx) - createRoot(tx, currentNode, id) - } - ++id - } - if (!stack.isEmpty()) { - if (set.contains(stack.peek())) { - set.remove(stack.peek()) - val parentNode = stack.pop() - //parentNode.value as Container<*, *> - session.executeWrite { tx -> - createRightSon(tx, parentNode, currentNode, id) - } - ++id - } else { - val parentNode = stack.peek() - parentNode.value as Container<*, *> - session.executeWrite { tx -> - createLeftSon(tx, parentNode, currentNode, id) - } - ++id - } - } - stack.push(currentNode) - } while (preOrder[preOrderIndex++].value != inOrder[inOrderIndex].value && preOrderIndex < preOrder.size) - - var currentNode: DrawRBVertex? = null - - while (!stack.isEmpty() && inOrderIndex < inOrder.size && stack.peek().value == inOrder[inOrderIndex].value) { - currentNode = stack.pop() - ++inOrderIndex - } - - if (currentNode != null) { - set.add(currentNode) - stack.push(currentNode) - } - - } - - session.close() - } - - fun exportRBtree(): Pair>>>, List>>>> { - - /*** Вот тут короче надо обращаться к neo4j с темЮ чтобы она инициализировала себя как-то ***/ - - val session = driver?.session() ?: throw IOException() - var preOrder: List>>> = listOf() - var inOrder: List>>> = listOf() - - session.executeRead { tx -> - preOrder = tx.run( - "MATCH (node: Node) " + - "RETURN node.value, node.key, node.color, node.x, node.y " + - "ORDER BY node.id" - ).list() - .map { - DrawRBVertex( - value = Container(Pair(it.values()[1].toString(), it.values()[0].toString())), - color = if (it.values()[2].toString() == """RED""") Markers.RED else Markers.BLACK, - x = it.values()[3].toString().toDouble(), - y = it.values()[4].toString().toDouble() - ) - } - - inOrder = tx.run( - "MATCH (node: Node) " + - "RETURN node.value, node.key, node.color, node.x, node.y " + - "ORDER BY node.key" - ).list() - .map { - DrawRBVertex( - value = Container(Pair(it.values()[1].toString(), it.values()[0].toString())), - color = if (it.values()[2].toString() == """RED""") Markers.RED else Markers.BLACK, - x = it.values()[3].toString().toDouble(), - y = it.values()[4].toString().toDouble() - ) - } - } - - session.close() - - return Pair(preOrder, inOrder) - - } - - private fun cleanDB(tx: TransactionContext) { - tx.run("MATCH (n: Node) DETACH DELETE n") - } - - private fun > createRoot(tx: TransactionContext, rootNode: DrawRBVertex, id: Int) { - rootNode.value as Container<*, *> - tx.run( - "MERGE(:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY, id: \$nodeID})", - mutableMapOf( - "nodeValue" to rootNode.value.pair.second, - "nodeKey" to rootNode.value.pair.first, - "nodeColor" to rootNode.color.toString(), - "nodeX" to rootNode.x, - "nodeY" to rootNode.y, - "nodeID" to id - ) - ) - } - - private fun > createRightSon( - tx: TransactionContext, parentNode: DrawRBVertex, - currentNode: DrawRBVertex, id: Int - ) { - parentNode.value as Container<*, *> - currentNode.value as Container<*, *> - tx.run( - "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + - "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + - "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY, id: \$nodeID}) " + - "MERGE (parent)-[:RIGHT_SON]->(son)", - mutableMapOf( - "parentNodeValue" to parentNode.value.pair.second, - "parentNodeKey" to parentNode.value.pair.first, - "parentNodeColor" to parentNode.color.toString(), - "parentNodeX" to parentNode.x, - "parentNodeY" to parentNode.y, - "nodeValue" to currentNode.value.pair.second, - "nodeKey" to currentNode.value.pair.first, - "nodeColor" to currentNode.color.toString(), - "nodeX" to currentNode.x, - "nodeY" to currentNode.y, - "nodeID" to id, - ) - ) - } - - private fun > createLeftSon( - tx: TransactionContext, parentNode: DrawRBVertex, - currentNode: DrawRBVertex, id: Int - ) { - parentNode.value as Container<*, *> - currentNode.value as Container<*, *> - tx.run( - "MERGE(parent:Node {value: \$parentNodeValue, key: \$parentNodeKey, " + - "color: \$parentNodeColor, x: \$parentNodeX, y: \$parentNodeY}) " + - "MERGE(son:Node {value: \$nodeValue, key: \$nodeKey, color: \$nodeColor, x: \$nodeX, y: \$nodeY, id: \$nodeID}) " + - "MERGE (parent)-[:LEFT_SON]->(son)", - mutableMapOf( - "parentNodeValue" to parentNode.value.pair.second, - "parentNodeKey" to parentNode.value.pair.first, - "parentNodeColor" to parentNode.color.toString(), - "parentNodeX" to parentNode.x, - "parentNodeY" to parentNode.y, - "nodeValue" to currentNode.value.pair.second, - "nodeKey" to currentNode.value.pair.first, - "nodeColor" to currentNode.color.toString(), - "nodeX" to currentNode.x, - "nodeY" to currentNode.y, - "nodeID" to id, - ) - ) - } - - override fun close() { - driver?.close() - } -} diff --git a/lib/src/main/kotlin/controller/Neo4jController.kt b/lib/src/main/kotlin/controller/Neo4jController.kt index 5c47c63..3744351 100644 --- a/lib/src/main/kotlin/controller/Neo4jController.kt +++ b/lib/src/main/kotlin/controller/Neo4jController.kt @@ -16,7 +16,7 @@ class Neo4jController { neo4jDB.exportRBtree() val RBtree = RBStruct>>() - RBtree.restoreStruct(orders.first, orders.second) + RBtree.restoreTreeFromDatabase(orders.first, orders.second) neo4jDB.close() } diff --git a/lib/src/main/kotlin/initNeo4j.sh b/lib/src/main/kotlin/initNeo4j.sh deleted file mode 100644 index e69de29..0000000 diff --git a/lib/src/main/kotlin/loadNeo4j.sh b/lib/src/main/kotlin/loadNeo4j.sh deleted file mode 100644 index d4d9fcd..0000000 --- a/lib/src/main/kotlin/loadNeo4j.sh +++ /dev/null @@ -1,8 +0,0 @@ - -BASEDIR=$(realpath "$(dirname "$0")") - -. "${BASEDIR}/CONTAINER.conf" - -docker stop "$CONTAINER_NAME" - -neo4j-admin dump --database=neo4j --to=/data/backups/ \ No newline at end of file diff --git a/lib/src/main/kotlin/testNeo4j.sh b/lib/src/main/kotlin/testNeo4j.sh deleted file mode 100644 index 87b69c4..0000000 --- a/lib/src/main/kotlin/testNeo4j.sh +++ /dev/null @@ -1,24 +0,0 @@ - -BASEDIR=$(realpath "$(dirname "$0")") - -. "${BASEDIR}/CONTAINER.conf" - -# -d -docker run \ - -i \ - --name "$CONTAINER_NAME" \ - --volume=$HOME/neo4j/data:/data \ - --volume=$HOME/neo4j/logs:/logs \ - --publish=7474:7474 --publish=7687:7687 \ - --env NEO4J_AUTH=neo4j/"$PASSWORD" \ - neo4j:latest \ -# -c /bin/bash -#neo4j-admin database dump neo4j --to-path=$HOME/neo4j/data:/data - -#docker ps -a - -#docker stop "$CONTAINER_NAME" - -#cp $HOME/neo4j/data:/data $HOME/ - -#docker stop neo4j:latest diff --git a/lib/src/main/kotlin/treelib/DBNodeRB.kt b/lib/src/main/kotlin/treelib/DBNodeRB.kt deleted file mode 100644 index cf067e1..0000000 --- a/lib/src/main/kotlin/treelib/DBNodeRB.kt +++ /dev/null @@ -1,11 +0,0 @@ -package treelib - -import treelib.singleObjects.Markers - - -class DBNodeRB>( - val value: Pack, - val color: Markers = Markers.RED, - val x: Double = 0.0, - val y: Double = 0.0 -) diff --git a/lib/src/main/kotlin/treelib/Main.kt b/lib/src/main/kotlin/treelib/Main.kt deleted file mode 100644 index 15e0eab..0000000 --- a/lib/src/main/kotlin/treelib/Main.kt +++ /dev/null @@ -1,66 +0,0 @@ -package treelib - -import Controller -import treelib.rbTree.RBStruct -import treelib.singleObjects.Container - - -fun main() { - // 25, 15, 10, 4, 12, 22, 18, 24, 50, 35, 31, 44, 70, 66, 90 - // 4, 10, 12, 15, 18, 22, 24, 25, 31, 35, 44, 50, 66, 70, 90 - - /* - - val neo4jRep = Neo4jRepository() - val a1 = DBNodeRB(Container(Pair(1, 25))) - val a2 = DBNodeRB(Container(Pair(1, 15))) - val a3 = DBNodeRB(Container(Pair(1, 10))) - val a4 = DBNodeRB(Container(Pair(1, 4))) - val a5 = DBNodeRB(Container(Pair(1, 12))) - val a6 = DBNodeRB(Container(Pair(1, 22))) - val a7 = DBNodeRB(Container(Pair(1, 18))) - val a8 = DBNodeRB(Container(Pair(1, 24))) - val a9 = DBNodeRB(Container(Pair(1, 50))) - val a10 = DBNodeRB(Container(Pair(1, 35))) - val a11 = DBNodeRB(Container(Pair(1, 31))) - val a12 = DBNodeRB(Container(Pair(1, 44))) - val a13 = DBNodeRB(Container(Pair(1, 70))) - val a14 = DBNodeRB(Container(Pair(1, 66))) - val a15 = DBNodeRB(Container(Pair(1, 90))) - val preArr = arrayOf(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) - val inArr = arrayOf(a4, a3, a5, a2, a7, a6, a8, a1, a11, a10, a12, a9, a14, a13, a15) - neo4jRep.open("bolt://localhost:7687", "neo4j", "test-neo4j") - neo4jRep.saveChanges(preArr, inArr) - */ - - val tree = RBStruct>() - tree.insert(Container(Pair(25 , 1))) - tree.insert(Container(Pair(15 , 1))) - tree.insert(Container(Pair(50 , 1))) - tree.insert(Container(Pair(10 , 1))) - tree.insert(Container(Pair(22 , 1))) - tree.insert(Container(Pair(35 , 1))) - tree.insert(Container(Pair(70 , 1))) - tree.insert(Container(Pair(4 , 1))) - tree.insert(Container(Pair(12 , 1))) - tree.insert(Container(Pair(18 , 1))) - tree.insert(Container(Pair(24 , 1))) - tree.insert(Container(Pair(31 , 1))) - tree.insert(Container(Pair(44 , 1))) - tree.insert(Container(Pair(66 , 1))) - tree.insert(Container(Pair(90 , 1))) - val controller = Controller() - controller.saveTree(tree) - tree.insert(Container(Pair(100, 1))) - controller.saveTree(tree) - controller.initTree() - - //neo4jRep.exportRBtree() - - //neo4jRep.close() -} - -fun test() { - val cont = Controller() - cont.initTree() -} \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt b/lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt deleted file mode 100644 index b3ee499..0000000 --- a/lib/src/main/kotlin/treelib/rbTree/DrawRBVertex.kt +++ /dev/null @@ -1,10 +0,0 @@ -package treelib.rbTree - -import treelib.singleObjects.Markers - -class DrawRBVertex>( - value: Pack, - color: Markers, - val x: Double = 0.0, - val y: Double = 0.0 -) : RBVertex(value, color) \ No newline at end of file From 4b87eeedfc4a6f8dc8c210f221c5d8d6230fb3c1 Mon Sep 17 00:00:00 2001 From: Georgy S Date: Wed, 19 Apr 2023 03:20:10 +0300 Subject: [PATCH 77/84] feat: Implement AVLStruct.restoreStruct and BINStruct.restoreStruct. --- lib/src/main/kotlin/controller/Neo4jController.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/controller/Neo4jController.kt b/lib/src/main/kotlin/controller/Neo4jController.kt index 3744351..5c47c63 100644 --- a/lib/src/main/kotlin/controller/Neo4jController.kt +++ b/lib/src/main/kotlin/controller/Neo4jController.kt @@ -16,7 +16,7 @@ class Neo4jController { neo4jDB.exportRBtree() val RBtree = RBStruct>>() - RBtree.restoreTreeFromDatabase(orders.first, orders.second) + RBtree.restoreStruct(orders.first, orders.second) neo4jDB.close() } From f6f213785aa561cde7be4af80b850825d9ad9127 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 19 Apr 2023 06:06:19 +0300 Subject: [PATCH 78/84] refactor: Rename some classes after rebase onto SQLiteDB branch --- lib/build.gradle.kts | 1 + .../{treelib/controller => dbSave}/DrawVertex.kt | 2 +- .../sqlite/DrawAVLVertex.kt} | 6 +++--- .../sqlite/SQLiteRepository.kt} | 16 ++++++++-------- .../kotlin/treelib/singleObjects/Container.kt | 3 +++ 5 files changed, 16 insertions(+), 12 deletions(-) rename lib/src/main/kotlin/{treelib/controller => dbSave}/DrawVertex.kt (79%) rename lib/src/main/kotlin/{treelib/dbSave/avlSQLite/AVLDrawVertex.kt => dbSave/sqlite/DrawAVLVertex.kt} (53%) rename lib/src/main/kotlin/{treelib/dbSave/avlSQLite/SQLiteAVL.kt => dbSave/sqlite/SQLiteRepository.kt} (94%) diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 9d6fcd3..080c014 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -22,6 +22,7 @@ repositories { dependencies { api("org.apache.commons:commons-math3:3.6.1") implementation("com.google.guava:guava:31.1-jre") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0") implementation("com.google.code.gson:gson:2.8.5") diff --git a/lib/src/main/kotlin/treelib/controller/DrawVertex.kt b/lib/src/main/kotlin/dbSave/DrawVertex.kt similarity index 79% rename from lib/src/main/kotlin/treelib/controller/DrawVertex.kt rename to lib/src/main/kotlin/dbSave/DrawVertex.kt index 8ccd5dc..ab0ed41 100644 --- a/lib/src/main/kotlin/treelib/controller/DrawVertex.kt +++ b/lib/src/main/kotlin/dbSave/DrawVertex.kt @@ -1,4 +1,4 @@ -package treelib.controller +package dbSave interface DrawVertex> { val value: Pack diff --git a/lib/src/main/kotlin/treelib/dbSave/avlSQLite/AVLDrawVertex.kt b/lib/src/main/kotlin/dbSave/sqlite/DrawAVLVertex.kt similarity index 53% rename from lib/src/main/kotlin/treelib/dbSave/avlSQLite/AVLDrawVertex.kt rename to lib/src/main/kotlin/dbSave/sqlite/DrawAVLVertex.kt index be2938c..6b773db 100644 --- a/lib/src/main/kotlin/treelib/dbSave/avlSQLite/AVLDrawVertex.kt +++ b/lib/src/main/kotlin/dbSave/sqlite/DrawAVLVertex.kt @@ -1,8 +1,8 @@ -package treelib.dbSave.avlSQLite +package dbSave.sqlite -import treelib.controller.DrawVertex +import dbSave.DrawVertex -class AVLDrawVertex>( +class DrawAVLVertex>( override val value: Pack, override val x: Double, override val y: Double, diff --git a/lib/src/main/kotlin/treelib/dbSave/avlSQLite/SQLiteAVL.kt b/lib/src/main/kotlin/dbSave/sqlite/SQLiteRepository.kt similarity index 94% rename from lib/src/main/kotlin/treelib/dbSave/avlSQLite/SQLiteAVL.kt rename to lib/src/main/kotlin/dbSave/sqlite/SQLiteRepository.kt index c125768..f12f015 100644 --- a/lib/src/main/kotlin/treelib/dbSave/avlSQLite/SQLiteAVL.kt +++ b/lib/src/main/kotlin/dbSave/sqlite/SQLiteRepository.kt @@ -1,10 +1,10 @@ -package treelib.dbSave.avlSQLite +package dbSave.sqlite import java.io.Closeable import java.sql.DriverManager import java.sql.SQLException -class SQLiteAVL>( +class SQLiteRepository>( private val dbPath: String, private val serializeData: (input: Pack) -> String, private val deSerializeData: (input: String) -> Pack, @@ -124,7 +124,7 @@ class SQLiteAVL>( else throw SQLException("Impossible case") } - fun addVertex(avlDVertex: AVLDrawVertex, treeName: String) { + fun addVertex(avlDVertex: DrawAVLVertex, treeName: String) { val isInDB = getVertexId(avlDVertex, treeName) if (isInDB != 0) { deleteVertex(isInDB, treeName) @@ -147,7 +147,7 @@ class SQLiteAVL>( } - fun addVertexes(list: List>, treeName: String) { + fun addVertexes(list: List>, treeName: String) { for (el in list) addVertex(el, treeName) } @@ -163,15 +163,15 @@ class SQLiteAVL>( } } - fun getAllVertexes(treeName: String): MutableList> { - val info = mutableListOf>() + fun getAllVertexes(treeName: String): MutableList> { + val info = mutableListOf>() connection.createStatement().also { stmt -> try { val result = stmt.executeQuery("SELECT $treeName.$value as $value, $treeName.$height as $height, $treeName.$xCord as $xCord, $treeName.$yCord as $yCord FROM $treeName;") while (result.next()) { info.add( - AVLDrawVertex( + DrawAVLVertex( value = deSerializeData(result.getString(value)), height = result.getInt(height), x = result.getDouble(xCord), @@ -189,7 +189,7 @@ class SQLiteAVL>( } } - private fun getVertexId(vertex: AVLDrawVertex, tableName: String): Int { + private fun getVertexId(vertex: DrawAVLVertex, tableName: String): Int { var id: Int? = null try { val stmt = diff --git a/lib/src/main/kotlin/treelib/singleObjects/Container.kt b/lib/src/main/kotlin/treelib/singleObjects/Container.kt index 5ad9da1..910cd24 100644 --- a/lib/src/main/kotlin/treelib/singleObjects/Container.kt +++ b/lib/src/main/kotlin/treelib/singleObjects/Container.kt @@ -1,5 +1,8 @@ package treelib.singleObjects +import kotlinx.serialization.Serializable + +@Serializable class Container, V>(val pair: Pair) : Comparable> { val key = pair.first From 66835546e4e6a1fbc31e86d49a0b0af6c7ffda97 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 19 Apr 2023 07:49:38 +0300 Subject: [PATCH 79/84] refactor: Change the names of some classes --- .../main/kotlin/controller/BINTreeManager.kt | 21 +++++++++++++++++++ .../{Neo4jController.kt => RBTreeManager.kt} | 9 +++++--- lib/src/main/kotlin/controller/TreeManager.kt | 4 ++++ .../dbSave/jsonFormat/JsonRepository.kt | 14 ++++++------- .../kotlin/dbSave/neo4j/Neo4jRepository.kt | 2 +- 5 files changed, 38 insertions(+), 12 deletions(-) create mode 100644 lib/src/main/kotlin/controller/BINTreeManager.kt rename lib/src/main/kotlin/controller/{Neo4jController.kt => RBTreeManager.kt} (88%) create mode 100644 lib/src/main/kotlin/controller/TreeManager.kt diff --git a/lib/src/main/kotlin/controller/BINTreeManager.kt b/lib/src/main/kotlin/controller/BINTreeManager.kt new file mode 100644 index 0000000..7232c6e --- /dev/null +++ b/lib/src/main/kotlin/controller/BINTreeManager.kt @@ -0,0 +1,21 @@ +package controller + +import dbSave.jsonFormat.JsonRepository +import treelib.binTree.BINStruct + +class BINTreeManager: TreeManager() { + + /*** using json format files ***/ + + val jsonRep = JsonRepository(System.getProperty("user.dir")) + + + /*** 1.7.6 ***/ + fun initTree(treeName: String) { + TODO() + } + + fun > saveTree(tree: BINStruct) { + TODO() + } +} \ No newline at end of file diff --git a/lib/src/main/kotlin/controller/Neo4jController.kt b/lib/src/main/kotlin/controller/RBTreeManager.kt similarity index 88% rename from lib/src/main/kotlin/controller/Neo4jController.kt rename to lib/src/main/kotlin/controller/RBTreeManager.kt index 5c47c63..0d3456e 100644 --- a/lib/src/main/kotlin/controller/Neo4jController.kt +++ b/lib/src/main/kotlin/controller/RBTreeManager.kt @@ -5,9 +5,11 @@ import dbSave.neo4j.Neo4jRepository import treelib.rbTree.RBStruct import treelib.singleObjects.Container -class Neo4jController { +class RBTreeManager { - fun initTree() { + /*** using neo4j ***/ + + fun initTree(treeName: String): RBStruct>> { val neo4jDB = Neo4jRepository() neo4jDB.open("bolt://localhost:7687", "neo4j", "test-neo4j") @@ -18,6 +20,8 @@ class Neo4jController { val RBtree = RBStruct>>() RBtree.restoreStruct(orders.first, orders.second) neo4jDB.close() + + return RBtree } fun > saveTree(tree: RBStruct) { @@ -31,7 +35,6 @@ class Neo4jController { neo4jDB.saveChanges(preOrder.toTypedArray(), inOrder.toTypedArray()) neo4jDB.close() - } } \ No newline at end of file diff --git a/lib/src/main/kotlin/controller/TreeManager.kt b/lib/src/main/kotlin/controller/TreeManager.kt new file mode 100644 index 0000000..cc751e0 --- /dev/null +++ b/lib/src/main/kotlin/controller/TreeManager.kt @@ -0,0 +1,4 @@ +package controller + +abstract class TreeManager { +} \ No newline at end of file diff --git a/lib/src/main/kotlin/dbSave/jsonFormat/JsonRepository.kt b/lib/src/main/kotlin/dbSave/jsonFormat/JsonRepository.kt index 88a1396..7f58420 100644 --- a/lib/src/main/kotlin/dbSave/jsonFormat/JsonRepository.kt +++ b/lib/src/main/kotlin/dbSave/jsonFormat/JsonRepository.kt @@ -3,13 +3,13 @@ import com.google.common.reflect.TypeToken import com.google.gson.GsonBuilder import java.io.File -class JsonRepository>(private val dirPath: String) { +class JsonRepository(private val dirPath: String) { init { File(dirPath).mkdirs() } - fun saveChanges(preOrder: Array>, typeToken: TypeToken>>, fileName: String) { + fun >saveChanges(preOrder: Array>, fileName: String) { val gson = GsonBuilder().setPrettyPrinting().create() val json = gson.toJson(preOrder) @@ -19,16 +19,14 @@ class JsonRepository>(private val dirPath: String) { writeText(json) } - val preOrd = gson.fromJson>>(json, typeToken.type) - } - fun exportTree(fileName: String) { + fun> exportTree(fileName: String, typeToken: TypeToken>>): Array> { val gson = GsonBuilder().setPrettyPrinting().create() - //val json = gson.fromJson(File(dirPath, fileName).readText(), ArrayVertices::class.java) - + val json = File(dirPath, fileName).readText() + val preOrder = gson.fromJson>>(json, typeToken.type) + return preOrder } - } \ No newline at end of file diff --git a/lib/src/main/kotlin/dbSave/neo4j/Neo4jRepository.kt b/lib/src/main/kotlin/dbSave/neo4j/Neo4jRepository.kt index 316dc4c..f04cf8c 100644 --- a/lib/src/main/kotlin/dbSave/neo4j/Neo4jRepository.kt +++ b/lib/src/main/kotlin/dbSave/neo4j/Neo4jRepository.kt @@ -88,7 +88,7 @@ class Neo4jRepository : Closeable { fun exportRBtree(): Pair>>>, List>>>> { - /*** Вот тут короче надо обращаться к neo4j с темЮ чтобы она инициализировала себя как-то ***/ + /*** Плохо, что передаем Container с четко привязанными типами (K, V), потому что может быть так, что вместо контейнера будет просто инт ***/ val session = driver?.session() ?: throw IOException() var preOrder: List>>> = listOf() From 0b26e58e05a82ae44538c7cd93084ac90bc2220c Mon Sep 17 00:00:00 2001 From: Georgy S Date: Wed, 19 Apr 2023 08:11:53 +0300 Subject: [PATCH 80/84] feat: Implement Beta-SQLiteController; refactor code-style. --- .../kotlin/controller/SQLiteController.kt | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 lib/src/main/kotlin/controller/SQLiteController.kt diff --git a/lib/src/main/kotlin/controller/SQLiteController.kt b/lib/src/main/kotlin/controller/SQLiteController.kt new file mode 100644 index 0000000..fa39c9d --- /dev/null +++ b/lib/src/main/kotlin/controller/SQLiteController.kt @@ -0,0 +1,58 @@ +package controller + +import dbSave.sqlite.DrawAVLVertex +import dbSave.sqlite.SQLiteRepository +import treelib.avlTree.AVLStruct +import treelib.avlTree.AVLVertex +import java.io.Closeable + +class SQLiteController>( + private var treeName: String, + private val dbPath: String, + private val serializeData: (input: Pack) -> String, + private val deSerializeData: (input: String) -> Pack, +) : Closeable { + private val db = SQLiteRepository(dbPath, serializeData, deSerializeData) + private var avlTree = AVLStruct() + + + private fun drawVertexToVertex(drawVertex: MutableList>): MutableList> { + //TODO: Rewrite while working on GUI + val ans = mutableListOf>() + for (el in drawVertex) ans.add(AVLVertex(value = el.value, height = el.height.toUInt())) + return ans + } + + private fun vertexToDrawVertex(drawVertex: List>): MutableList> { + //TODO: Rewrite while working on GUI + val ans = mutableListOf>() + for (el in drawVertex) ans.add(DrawAVLVertex(value = el.value, height = el.height.toInt(), x = 1.1, y = 1.1)) + return ans + } + + fun initTree() { + avlTree = AVLStruct() + if (db.getTreeId(treeName) == 0) { + db.addTree(treeName) + } else { + avlTree.restoreStruct(drawVertexToVertex(db.getAllVertexes(treeName))) + } + db.addTree(treeName) + } + + fun saveTree() { + db.addVertexes(vertexToDrawVertex(avlTree.preOrder()), treeName) + } + + fun deleteTree() { + if (db.getTreeId(treeName) != 0) { + db.deleteTree(treeName) + } + } + + fun insert(item: Pack) = avlTree.insert(item) + + fun delete(item: Pack) = avlTree.delete(item) + + override fun close() = db.close() +} From a15abed7790c0c0585f0647f4d83bd42befa983c Mon Sep 17 00:00:00 2001 From: Georgy S Date: Wed, 19 Apr 2023 08:15:55 +0300 Subject: [PATCH 81/84] refactor: Correct code style. --- lib/src/main/kotlin/dbSave/DrawVertex.kt | 2 +- .../dbSave/jsonFormat/JsonRepository.kt | 19 ++- .../kotlin/dbSave/sqlite/DrawAVLVertex.kt | 2 +- .../kotlin/dbSave/sqlite/SQLiteRepository.kt | 6 +- .../main/kotlin/treelib/abstractTree/Tree.kt | 2 +- .../kotlin/treelib/abstractTree/TreeStruct.kt | 28 +++-- .../kotlin/treelib/abstractTree/Vertex.kt | 2 +- .../balanced/BalancedTreeStruct.kt | 8 +- .../abstractTree/balanced/BalancerParent.kt | 3 +- .../main/kotlin/treelib/avlTree/AVLStruct.kt | 5 +- .../main/kotlin/treelib/avlTree/AVLVertex.kt | 2 +- .../main/kotlin/treelib/binTree/BINStruct.kt | 4 +- .../main/kotlin/treelib/binTree/BINVertex.kt | 2 +- .../main/kotlin/treelib/rbTree/RBStruct.kt | 4 +- .../main/kotlin/treelib/rbTree/RBVertex.kt | 4 +- .../exceptions/IllegalBaseNodeException.kt | 2 +- .../exceptions/IncorrectUsage.kt | 2 +- lib/src/test/kotlin/treeTests/RBTreeTest.kt | 16 --- .../test/kotlin/treelib/AVLBalancerTest.kt | 17 ++- lib/src/test/kotlin/treelib/AVLStructTest.kt | 1 + lib/src/test/kotlin/treelib/AVLTreeTest.kt | 28 +++-- lib/src/test/kotlin/treelib/BINStructTest.kt | 4 +- lib/src/test/kotlin/treelib/BINTreeTest.kt | 18 ++- lib/src/test/kotlin/treelib/RBBalancerTest.kt | 24 ++-- lib/src/test/kotlin/treelib/RBStructTest.kt | 25 +++- lib/src/test/kotlin/treelib/TestModelAVL.kt | 90 ++++++++------ lib/src/test/kotlin/treelib/TestModelRBT.kt | 112 +++++++++++++----- lib/src/test/kotlin/utils/AVLAnalyzer.kt | 2 +- lib/src/test/kotlin/utils/RBAnalyzer.kt | 2 +- .../test/kotlin/utils/TreeStructWrapper.kt | 9 +- lib/src/test/kotlin/utils/TreeWrapper.kt | 12 +- .../kotlin/utils/fuzzers/BINStructFuzzer.kt | 4 +- .../kotlin/utils/fuzzers/RBStructFuzzer.kt | 4 +- .../kotlin/utils/fuzzers/TreeStructFuzzer.kt | 6 +- 34 files changed, 287 insertions(+), 184 deletions(-) delete mode 100644 lib/src/test/kotlin/treeTests/RBTreeTest.kt diff --git a/lib/src/main/kotlin/dbSave/DrawVertex.kt b/lib/src/main/kotlin/dbSave/DrawVertex.kt index ab0ed41..4108556 100644 --- a/lib/src/main/kotlin/dbSave/DrawVertex.kt +++ b/lib/src/main/kotlin/dbSave/DrawVertex.kt @@ -1,6 +1,6 @@ package dbSave -interface DrawVertex> { +interface DrawVertex> { val value: Pack val x: Double val y: Double diff --git a/lib/src/main/kotlin/dbSave/jsonFormat/JsonRepository.kt b/lib/src/main/kotlin/dbSave/jsonFormat/JsonRepository.kt index 7f58420..c2ca1c1 100644 --- a/lib/src/main/kotlin/dbSave/jsonFormat/JsonRepository.kt +++ b/lib/src/main/kotlin/dbSave/jsonFormat/JsonRepository.kt @@ -1,15 +1,20 @@ package dbSave.jsonFormat + import com.google.common.reflect.TypeToken import com.google.gson.GsonBuilder import java.io.File -class JsonRepository(private val dirPath: String) { +class JsonRepository>(private val dirPath: String) { init { File(dirPath).mkdirs() } - fun >saveChanges(preOrder: Array>, fileName: String) { + fun saveChanges( + preOrder: Array>, + typeToken: TypeToken>>, + fileName: String + ) { val gson = GsonBuilder().setPrettyPrinting().create() val json = gson.toJson(preOrder) @@ -19,14 +24,16 @@ class JsonRepository(private val dirPath: String) { writeText(json) } + val preOrd = gson.fromJson>>(json, typeToken.type) + } - fun> exportTree(fileName: String, typeToken: TypeToken>>): Array> { + fun exportTree(fileName: String) { val gson = GsonBuilder().setPrettyPrinting().create() - val json = File(dirPath, fileName).readText() - val preOrder = gson.fromJson>>(json, typeToken.type) + //val json = gson.fromJson(File(dirPath, fileName).readText(), ArrayVertices::class.java) + - return preOrder } + } \ No newline at end of file diff --git a/lib/src/main/kotlin/dbSave/sqlite/DrawAVLVertex.kt b/lib/src/main/kotlin/dbSave/sqlite/DrawAVLVertex.kt index 6b773db..e6feb46 100644 --- a/lib/src/main/kotlin/dbSave/sqlite/DrawAVLVertex.kt +++ b/lib/src/main/kotlin/dbSave/sqlite/DrawAVLVertex.kt @@ -2,7 +2,7 @@ package dbSave.sqlite import dbSave.DrawVertex -class DrawAVLVertex>( +class DrawAVLVertex>( override val value: Pack, override val x: Double, override val y: Double, diff --git a/lib/src/main/kotlin/dbSave/sqlite/SQLiteRepository.kt b/lib/src/main/kotlin/dbSave/sqlite/SQLiteRepository.kt index f12f015..1d4cf20 100644 --- a/lib/src/main/kotlin/dbSave/sqlite/SQLiteRepository.kt +++ b/lib/src/main/kotlin/dbSave/sqlite/SQLiteRepository.kt @@ -83,7 +83,7 @@ class SQLiteRepository>( while (result.next()) { info.add(result.getString(avlTreeName)) } - logInfoMethod("") + logInfoMethod("Available tree is given") } catch (ex: SQLException) { logErrorMethod(ex) } finally { @@ -110,7 +110,7 @@ class SQLiteRepository>( } } - private fun getTreeId(treeName: String): Int { + fun getTreeId(treeName: String): Int { var id: Int? = null try { val statement = connection.prepareStatement("SELECT id FROM $treeTable WHERE name=?;") @@ -147,7 +147,7 @@ class SQLiteRepository>( } - fun addVertexes(list: List>, treeName: String) { + fun addVertexes(list: MutableList>, treeName: String) { for (el in list) addVertex(el, treeName) } diff --git a/lib/src/main/kotlin/treelib/abstractTree/Tree.kt b/lib/src/main/kotlin/treelib/abstractTree/Tree.kt index 1116ad6..fb0976a 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/Tree.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/Tree.kt @@ -8,7 +8,7 @@ abstract class Tree< V, NodeType : Node, NodeType>, State : StateContainer, NodeType>, - VertexType: Vertex> + VertexType : Vertex> > { protected abstract val treeStruct: TreeStruct, NodeType, State, VertexType> diff --git a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt index d9b223b..fa403bc 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt @@ -10,7 +10,7 @@ abstract class TreeStruct< Pack : Comparable, NodeType : Node, State : StateContainer, - VertexType: Vertex + VertexType : Vertex > { protected abstract var root: NodeType? @@ -52,7 +52,8 @@ abstract class TreeStruct< else currentNode = it.left } } - } ?: throw BugInImplementException("getParentByValue shouldn't be used with value doesn't exist in tree")// (1)l -> + } + ?: throw BugInImplementException("getParentByValue shouldn't be used with value doesn't exist in tree")// (1)l -> } } @@ -75,7 +76,8 @@ abstract class TreeStruct< private fun getRightMinNode(localRoot: NodeType): NodeType { var currentNode: NodeType? - localRoot.right ?: throw BugInImplementException("Incorrect usage of the getRightMinNode: right node doesn't exist") + localRoot.right + ?: throw BugInImplementException("Incorrect usage of the getRightMinNode: right node doesn't exist") currentNode = localRoot.right @@ -227,11 +229,11 @@ abstract class TreeStruct< for (child in listOf(deleteNode.right, deleteNode.left)) child?.let { connectUnlinkedSubTreeWithParent(deleteNode, parentDeleteNode, it) - if (parentDeleteNode != null) { - return@deleteItem generateStateDelete(deletedNodeWithoutLinks, parentDeleteNode) - } else { - return@deleteItem generateStateDelete(deletedNodeWithoutLinks, root) - } + if (parentDeleteNode != null) { + return@deleteItem generateStateDelete(deletedNodeWithoutLinks, parentDeleteNode) + } else { + return@deleteItem generateStateDelete(deletedNodeWithoutLinks, root) + } } } } @@ -285,13 +287,13 @@ abstract class TreeStruct< current = it.right } else { if (parents.isEmpty()) - return@inOrder arrayNodes.map {toVertex(it)} + return@inOrder arrayNodes.map { toVertex(it) } flagVisited = 1 current = parents.removeLast() } } } - return arrayNodes.map{toVertex(it)} + return arrayNodes.map { toVertex(it) } } abstract fun toVertex(node: NodeType): VertexType @@ -321,7 +323,7 @@ abstract class TreeStruct< } else { arrayNodes.add(it) if (parents.isEmpty()) - return@postOrder arrayNodes.map{toVertex(it)} + return@postOrder arrayNodes.map { toVertex(it) } val parent = parents.removeLast() if (parent.right == it) { flagVisited = 2 @@ -330,7 +332,7 @@ abstract class TreeStruct< } } ?: throw MultithreadingException(ImpossibleCaseException()) } - return arrayNodes.map{toVertex(it)} + return arrayNodes.map { toVertex(it) } } fun preOrder(): List { @@ -354,7 +356,7 @@ abstract class TreeStruct< } ?: throw MultithreadingException(ImpossibleCaseException()) } } - return arrayNodes.map {toVertex(it)} + return arrayNodes.map { toVertex(it) } } diff --git a/lib/src/main/kotlin/treelib/abstractTree/Vertex.kt b/lib/src/main/kotlin/treelib/abstractTree/Vertex.kt index abbb7a5..68f3726 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/Vertex.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/Vertex.kt @@ -1,5 +1,5 @@ package treelib.abstractTree -abstract class Vertex>{ +abstract class Vertex> { abstract val value: Pack } \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/abstractTree/balanced/BalancedTreeStruct.kt b/lib/src/main/kotlin/treelib/abstractTree/balanced/BalancedTreeStruct.kt index 96e8458..5172f71 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/balanced/BalancedTreeStruct.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/balanced/BalancedTreeStruct.kt @@ -9,22 +9,22 @@ abstract class BalancedTreeStruct< Pack : Comparable, NodeType : Node, State : StateContainer, - VertexType: Vertex, + VertexType : Vertex, BalancerType : Balancer, > : TreeStruct() { protected abstract val balancer: BalancerType - override fun insert(item: Pack){ + override fun insert(item: Pack) { val currentState = insertItem(item) if (currentState.contentNode != null) { root = balancer.balance(currentState) } } - override fun delete(item: Pack){ + override fun delete(item: Pack) { val currentState = deleteItem(item) - if (root == null){ + if (root == null) { return } if (currentState.contentNode != null) { diff --git a/lib/src/main/kotlin/treelib/abstractTree/balanced/BalancerParent.kt b/lib/src/main/kotlin/treelib/abstractTree/balanced/BalancerParent.kt index afaf5d5..6cf9537 100644 --- a/lib/src/main/kotlin/treelib/abstractTree/balanced/BalancerParent.kt +++ b/lib/src/main/kotlin/treelib/abstractTree/balanced/BalancerParent.kt @@ -4,7 +4,8 @@ import treelib.abstractTree.NodeParent import treelib.abstractTree.StateContainer import treelib.singleObjects.exceptions.IllegalNodeStateException -abstract class BalancerParent, NodeType : NodeParent, StateContainerType: StateContainer>: Balancer { +abstract class BalancerParent, NodeType : NodeParent, StateContainerType : StateContainer> : + Balancer { override fun rightRotate(currentNode: NodeType): NodeType { val leftChild = currentNode.left ?: throw IllegalNodeStateException() diff --git a/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt b/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt index b0ee0ae..6d89668 100644 --- a/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt +++ b/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt @@ -57,9 +57,10 @@ class AVLStruct> : } return node } - fun > restoreStruct(preOrder: List){ + + fun > restoreStruct(preOrder: MutableList) { if (root != null) throw IncorrectUsage("The tree already exists") - for (vertex in preOrder){ + for (vertex in preOrder) { val currentNode = toNode(vertex) val leaf = getLeafForInsert(currentNode.value) linkNewNode(currentNode, leaf) diff --git a/lib/src/main/kotlin/treelib/avlTree/AVLVertex.kt b/lib/src/main/kotlin/treelib/avlTree/AVLVertex.kt index a43ea26..774d064 100644 --- a/lib/src/main/kotlin/treelib/avlTree/AVLVertex.kt +++ b/lib/src/main/kotlin/treelib/avlTree/AVLVertex.kt @@ -5,4 +5,4 @@ import treelib.abstractTree.Vertex class AVLVertex>( override val value: Pack, val height: UInt, -) : Vertex() \ No newline at end of file +) : Vertex() diff --git a/lib/src/main/kotlin/treelib/binTree/BINStruct.kt b/lib/src/main/kotlin/treelib/binTree/BINStruct.kt index ea03cb6..c033266 100644 --- a/lib/src/main/kotlin/treelib/binTree/BINStruct.kt +++ b/lib/src/main/kotlin/treelib/binTree/BINStruct.kt @@ -71,9 +71,9 @@ class BINStruct> : private fun toNode(vertex: BINVertex): BINNode = BINNode(value = vertex.value) - fun > restoreStruct(preOrder: List){ + fun > restoreStruct(preOrder: List) { if (root != null) throw IncorrectUsage("The tree already exists") - for (vertex in preOrder){ + for (vertex in preOrder) { val currentNode = toNode(vertex) val leaf = getLeafForInsert(currentNode.value) linkNewNode(currentNode, leaf) diff --git a/lib/src/main/kotlin/treelib/binTree/BINVertex.kt b/lib/src/main/kotlin/treelib/binTree/BINVertex.kt index 8939461..cb489a0 100644 --- a/lib/src/main/kotlin/treelib/binTree/BINVertex.kt +++ b/lib/src/main/kotlin/treelib/binTree/BINVertex.kt @@ -2,4 +2,4 @@ package treelib.binTree import treelib.abstractTree.Vertex -open class BINVertex>(override val value: Pack): Vertex() \ No newline at end of file +open class BINVertex>(override val value: Pack) : Vertex() \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt b/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt index 999c113..a3cbe34 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBStruct.kt @@ -76,7 +76,7 @@ class RBStruct> : return node } - fun > restoreStruct(preOrder: List, inOrder: List) { + fun > restoreStruct(preOrder: List, inOrder: List) { var inOrderIndex = 0 var preOrderIndex = 0 val set = HashSet>() @@ -119,7 +119,7 @@ class RBStruct> : } } - private fun > createRBNode(drawNode: RBVertexType): RBNode { + private fun > createRBNode(drawNode: RBVertexType): RBNode { val node = RBNode(value = drawNode.value, color = drawNode.color) return node } diff --git a/lib/src/main/kotlin/treelib/rbTree/RBVertex.kt b/lib/src/main/kotlin/treelib/rbTree/RBVertex.kt index 5d9d161..aee1d95 100644 --- a/lib/src/main/kotlin/treelib/rbTree/RBVertex.kt +++ b/lib/src/main/kotlin/treelib/rbTree/RBVertex.kt @@ -3,7 +3,7 @@ package treelib.rbTree import treelib.abstractTree.Vertex import treelib.singleObjects.Markers -open class RBVertex>( +open class RBVertex>( override val value: Pack, val color: Markers, -):Vertex() \ No newline at end of file +) : Vertex() \ No newline at end of file diff --git a/lib/src/main/kotlin/treelib/singleObjects/exceptions/IllegalBaseNodeException.kt b/lib/src/main/kotlin/treelib/singleObjects/exceptions/IllegalBaseNodeException.kt index 4744fc7..3303817 100644 --- a/lib/src/main/kotlin/treelib/singleObjects/exceptions/IllegalBaseNodeException.kt +++ b/lib/src/main/kotlin/treelib/singleObjects/exceptions/IllegalBaseNodeException.kt @@ -1,6 +1,6 @@ package treelib.singleObjects.exceptions -class IllegalBaseNodeException : Exception { +class IllegalBaseNodeException : Exception { constructor() : super( "A non-existent node (null) was passed to the method" ) diff --git a/lib/src/main/kotlin/treelib/singleObjects/exceptions/IncorrectUsage.kt b/lib/src/main/kotlin/treelib/singleObjects/exceptions/IncorrectUsage.kt index 9fce7ef..3f16415 100644 --- a/lib/src/main/kotlin/treelib/singleObjects/exceptions/IncorrectUsage.kt +++ b/lib/src/main/kotlin/treelib/singleObjects/exceptions/IncorrectUsage.kt @@ -1,6 +1,6 @@ package treelib.singleObjects.exceptions -class IncorrectUsage : Exception { +class IncorrectUsage : Exception { constructor() : super( "Incorrect use of the tree" ) diff --git a/lib/src/test/kotlin/treeTests/RBTreeTest.kt b/lib/src/test/kotlin/treeTests/RBTreeTest.kt deleted file mode 100644 index fa56cc6..0000000 --- a/lib/src/test/kotlin/treeTests/RBTreeTest.kt +++ /dev/null @@ -1,16 +0,0 @@ -package treeTests - -import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.Test -import treelib.rbTree.RBTree - -@DisplayName("Test: Red-Black Tree") -class RBTreeTest { - private var rbTree = RBTree() - - @Test - fun `insert two elements`(){ - rbTree.putItem(Pair(25, 1)) - rbTree.putItem(Pair(15, 1)) - } -} \ No newline at end of file diff --git a/lib/src/test/kotlin/treelib/AVLBalancerTest.kt b/lib/src/test/kotlin/treelib/AVLBalancerTest.kt index 3ee5452..43b6978 100644 --- a/lib/src/test/kotlin/treelib/AVLBalancerTest.kt +++ b/lib/src/test/kotlin/treelib/AVLBalancerTest.kt @@ -126,7 +126,6 @@ class AVLBalancerTest { } - } @DisplayName("Tests to check the operation of the balancer after insertion") @@ -174,8 +173,8 @@ class AVLBalancerTest { { assertEquals(2, root.right?.left?.height?.toInt()) }, { assertEquals(3, root.left?.left?.height?.toInt()) }, { assertEquals(2, root.left?.left?.right?.height?.toInt()) }, - { assertEquals(1, root.left?.left?.right?.right?.height?.toInt())}, - { assertEquals(1, root.left?.left?.left?.height?.toInt())} + { assertEquals(1, root.left?.left?.right?.right?.height?.toInt()) }, + { assertEquals(1, root.left?.left?.left?.height?.toInt()) } ) assertAll( "Grouped Assertions of values", @@ -183,8 +182,8 @@ class AVLBalancerTest { { assertEquals(205, root.right?.left?.value) }, { assertEquals(44, root.left?.left?.value) }, { assertEquals(46, root.left?.left?.right?.value) }, - { assertEquals(47, root.left?.left?.right?.right?.value)}, - { assertEquals(null, root.left?.left?.right?.left?.left?.value)} + { assertEquals(47, root.left?.left?.right?.right?.value) }, + { assertEquals(null, root.left?.left?.right?.left?.left?.value) } ) /** Second insert **/ @@ -205,7 +204,7 @@ class AVLBalancerTest { { assertEquals(46, root.left?.left?.value) }, { assertEquals(1, root.left?.left?.left?.left?.value) }, { assertEquals(null, root.left?.left?.right?.left?.value) }, - { assertEquals(null, root.left?.left?.right?.right?.left?.value)} + { assertEquals(null, root.left?.left?.right?.right?.left?.value) } ) /** Third insert **/ @@ -225,11 +224,11 @@ class AVLBalancerTest { { assertEquals(101, root.value) }, { assertEquals(205, root.right?.left?.value) }, { assertEquals(46, root.left?.left?.value) }, - { assertEquals(49, root.left?.left?.right?.value)}, + { assertEquals(49, root.left?.left?.right?.value) }, { assertEquals(1, root.left?.left?.left?.left?.value) }, { assertEquals(47, root.left?.left?.right?.left?.value) }, - { assertEquals(null, root.left?.left?.right?.right?.left?.value)}, - { assertEquals(null, root.left?.left?.right?.right?.right?.value)} + { assertEquals(null, root.left?.left?.right?.right?.left?.value) }, + { assertEquals(null, root.left?.left?.right?.right?.right?.value) } ) } } diff --git a/lib/src/test/kotlin/treelib/AVLStructTest.kt b/lib/src/test/kotlin/treelib/AVLStructTest.kt index f003b60..433618a 100644 --- a/lib/src/test/kotlin/treelib/AVLStructTest.kt +++ b/lib/src/test/kotlin/treelib/AVLStructTest.kt @@ -18,6 +18,7 @@ class AVLStructTest { private var treeStruct = AVLStruct() private fun testAssert(msg: String): Nothing = fail(msg) + @BeforeEach fun reInitClassUnderTest() { treeStruct = AVLStruct() diff --git a/lib/src/test/kotlin/treelib/AVLTreeTest.kt b/lib/src/test/kotlin/treelib/AVLTreeTest.kt index 5915d99..63073da 100644 --- a/lib/src/test/kotlin/treelib/AVLTreeTest.kt +++ b/lib/src/test/kotlin/treelib/AVLTreeTest.kt @@ -20,7 +20,7 @@ class AVLTreeTest { @ParameterizedTest @ValueSource(strings = ["5 3 8 9", "1 2 3 4", "4 3 5 2", "4 3 2 1", "2 3 1 4"]) fun `test check root`(str: String) { - val numbers = str.split(" ").map{ it.toInt() }.toMutableList() + val numbers = str.split(" ").map { it.toInt() }.toMutableList() val num = mutableListOf>() for (i in numbers) { num.add(Pair(i, 1)) @@ -31,8 +31,7 @@ class AVLTreeTest { val root = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key if (root == numbers[1]) { assertEquals(expected = root, actual = numbers[1]) - } - else { + } else { assertEquals(expected = root, actual = numbers[2]) } } @@ -40,8 +39,8 @@ class AVLTreeTest { @ParameterizedTest @ValueSource(strings = ["1 1000", "1 10000", "1 100000", "1 1000000"]) fun `test add many args and delete root`(str: String) { - val numbers = str.split(" ").map{ it.toInt() }.toMutableList() - for (i in numbers[0] .. numbers[1]) { + val numbers = str.split(" ").map { it.toInt() }.toMutableList() + for (i in numbers[0]..numbers[1]) { tree.putItem(Pair(i, i)) } val root = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key @@ -51,16 +50,27 @@ class AVLTreeTest { when (numbers[1]) { 1000 -> assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, actual = 513) - 10000 -> assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, actual = 4097) - 100000 -> assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, actual = 65537) - else -> assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, actual = 524289) + 10000 -> assertEquals( + expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, + actual = 4097 + ) + + 100000 -> assertEquals( + expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, + actual = 65537 + ) + + else -> assertEquals( + expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, + actual = 524289 + ) } } @ParameterizedTest @ValueSource(strings = ["5", "0"]) fun `test delete root one arg`(str: String) { - val numbers = str.split(" ").map{ it.toInt() }.toMutableList() + val numbers = str.split(" ").map { it.toInt() }.toMutableList() val num = mutableListOf>() for (i in numbers) { num.add(Pair(i, 1)) diff --git a/lib/src/test/kotlin/treelib/BINStructTest.kt b/lib/src/test/kotlin/treelib/BINStructTest.kt index 1075631..bab0d2d 100644 --- a/lib/src/test/kotlin/treelib/BINStructTest.kt +++ b/lib/src/test/kotlin/treelib/BINStructTest.kt @@ -14,7 +14,7 @@ import kotlin.test.assertEquals @DisplayName("Test: Binary Search Tree Struct") class BINStructTest { - val treeW = TreeStructWrapper, BINVertex, BINStateContainer, BINStruct>() + val treeW = TreeStructWrapper, BINVertex, BINStateContainer, BINStruct>() var treeStruct = BINStruct() private fun testAssert(msg: String): Nothing = fail(msg) @@ -481,7 +481,7 @@ class BINStructTest { } @Test - fun `test analyzer`(){ + fun `test analyzer`() { val num = mutableListOf(6, 8, 10, 7, 12, 9) for (i in num) { treeStruct.insert(i) diff --git a/lib/src/test/kotlin/treelib/BINTreeTest.kt b/lib/src/test/kotlin/treelib/BINTreeTest.kt index 5157c95..a13d174 100644 --- a/lib/src/test/kotlin/treelib/BINTreeTest.kt +++ b/lib/src/test/kotlin/treelib/BINTreeTest.kt @@ -17,7 +17,7 @@ class BINTreeTest { TreeStructWrapper, BINNode>, BINVertex>, BINStateContainer>, BINStruct>>() -// line - 0.6, branch - 0.5, methods = 0.9 + // line - 0.6, branch - 0.5, methods = 0.9 @ParameterizedTest @ValueSource(ints = [1, 2, 0, 6, 4]) fun `test putItem`(str: Int) { @@ -27,14 +27,17 @@ class BINTreeTest { @ParameterizedTest @ValueSource(strings = ["1 2 3 4", "5 6 7 8 9"]) fun `test putItems`(str: String) { - val numbers = str.split(" ").map{ it.toInt() }.toMutableList() + val numbers = str.split(" ").map { it.toInt() }.toMutableList() val num = mutableListOf>() for (i in numbers) { num.add(Pair(i, 1)) } tree.putItems(num) assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, actual = numbers[0]) - assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.right?.value?.key, actual = numbers[1]) + assertEquals( + expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.right?.value?.key, + actual = numbers[1] + ) } @Test @@ -52,7 +55,7 @@ class BINTreeTest { @ParameterizedTest @ValueSource(strings = ["5 2 3", "5 6 7", "5 6 13", "5 6 1", "192 5 6"]) fun `test putItems and delete`(str: String) { - val numbers = str.split(" ").map{ it.toInt() }.toMutableList() + val numbers = str.split(" ").map { it.toInt() }.toMutableList() val num = mutableListOf>() for (i in numbers) { num.add(Pair(i, 1)) @@ -67,7 +70,7 @@ class BINTreeTest { @ParameterizedTest @ValueSource(strings = ["5 2 3 9", "5 6 7 1", "5 6 13 4", "5 6 1", "192 5 6 222"]) fun `test putItems and delete root`(str: String) { - val numbers = str.split(" ").map{ it.toInt() }.toMutableList() + val numbers = str.split(" ").map { it.toInt() }.toMutableList() val num = mutableListOf>() for (i in numbers) { num.add(Pair(i, 1)) @@ -78,6 +81,9 @@ class BINTreeTest { val index = numbers.indexOf(root) tree.deleteItem(root) - assertEquals(expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, actual = numbers[index + 1]) + assertEquals( + expected = treeSW.getPrivateNode(treeW.getPrivateNode(tree))?.value?.key, + actual = numbers[index + 1] + ) } } \ No newline at end of file diff --git a/lib/src/test/kotlin/treelib/RBBalancerTest.kt b/lib/src/test/kotlin/treelib/RBBalancerTest.kt index d18134e..41f8bdd 100644 --- a/lib/src/test/kotlin/treelib/RBBalancerTest.kt +++ b/lib/src/test/kotlin/treelib/RBBalancerTest.kt @@ -9,10 +9,11 @@ import treelib.rbTree.RBBalancer import treelib.rbTree.RBNode import treelib.rbTree.RBStateContainer import treelib.singleObjects.Markers + class RBBalancerTest { val testModel = TestModelRBT() - fun > countBlackNodes(node: RBNode) = testModel.countBlackNodes(node) + fun > countBlackNodes(node: RBNode) = testModel.countBlackNodes(node) @DisplayName("Tests to check the operation of the balancer after removal") @Nested @@ -22,7 +23,10 @@ class RBBalancerTest { val firstBalancer = RBBalancer(null) assertEquals(15, firstBalancer.balance(RBStateContainer(RBNode(15, null, null, null, Markers.BLACK))).value) val secondBalancer = RBBalancer(null) - assertEquals("Test", secondBalancer.balance(RBStateContainer(RBNode("Test", null, null, null, Markers.BLACK))).value) + assertEquals( + "Test", + secondBalancer.balance(RBStateContainer(RBNode("Test", null, null, null, Markers.BLACK))).value + ) } @Test @@ -100,7 +104,7 @@ class RBBalancerTest { { assertEquals(10, root?.left?.left?.value) }, { assertEquals(12, root?.left?.left?.right?.value) }, { assertEquals(14, nodes[17]?.right?.value) }, - { assertEquals(null, nodes[17]?.left)} + { assertEquals(null, nodes[17]?.left) } ) } @@ -118,7 +122,7 @@ class RBBalancerTest { { assertEquals(Markers.BLACK, root.color) }, { assertEquals(null, root.parent) }, { assertEquals(nodes[28]?.value, root.left?.value) }, - { assertEquals( nodes[29]?.value, root.right?.value ) } + { assertEquals(nodes[29]?.value, root.right?.value) } ) assertAll( @@ -137,7 +141,7 @@ class RBBalancerTest { { assertEquals(42, root.right?.left?.right?.value) }, { assertEquals(37, root.right?.left?.left?.value) }, { assertEquals(38, nodes[20]?.right?.value) }, - { assertEquals(null, nodes[20]?.left)} + { assertEquals(null, nodes[20]?.left) } ) } @@ -155,8 +159,8 @@ class RBBalancerTest { { assertEquals(Markers.BLACK, root.color) }, { assertEquals(29, root.value) }, { assertEquals(null, root.parent) }, - { assertEquals(null, root.left)}, - { assertEquals(null, root.right)} + { assertEquals(null, root.left) }, + { assertEquals(null, root.right) } ) } @@ -166,7 +170,7 @@ class RBBalancerTest { val root = nodes[30]!! nodes[13]?.value = 68 val rightBrotherSon = RBNode(70, null, null, nodes[13], Markers.RED) - val leftBrotherSon= RBNode(65, null, null, nodes[13], Markers.RED) + val leftBrotherSon = RBNode(65, null, null, nodes[13], Markers.RED) nodes[13]?.right = rightBrotherSon nodes[13]?.left = leftBrotherSon val balancer = RBBalancer(nodes[30]) @@ -190,8 +194,8 @@ class RBBalancerTest { { assertEquals(68, root.right?.right?.left?.value) }, { assertEquals(70, root.right?.right?.left?.right?.value) }, { assertEquals(63, root.right?.right?.left?.left?.value) }, - { assertEquals(65, nodes[22]?.right?.value)}, - { assertEquals(null, nodes[22]?.left)}, + { assertEquals(65, nodes[22]?.right?.value) }, + { assertEquals(null, nodes[22]?.left) }, ) diff --git a/lib/src/test/kotlin/treelib/RBStructTest.kt b/lib/src/test/kotlin/treelib/RBStructTest.kt index 3196207..9f0b39e 100644 --- a/lib/src/test/kotlin/treelib/RBStructTest.kt +++ b/lib/src/test/kotlin/treelib/RBStructTest.kt @@ -117,7 +117,30 @@ class RBStructTest { @Test fun `fazzer test`() { - val fazzer = RBStructFuzzer(arrayOf(1, 2, 3, 4, 5, 6, 7,8,9,20,100,123,234,556,345677,88765,43,364,23456,2754), ::testAssert) + val fazzer = RBStructFuzzer( + arrayOf( + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 20, + 100, + 123, + 234, + 556, + 345677, + 88765, + 43, + 364, + 23456, + 2754 + ), ::testAssert + ) fazzer.saveNextTestSets("TEST_TEST") assertAll( diff --git a/lib/src/test/kotlin/treelib/TestModelAVL.kt b/lib/src/test/kotlin/treelib/TestModelAVL.kt index 8a3ba26..9b4823a 100644 --- a/lib/src/test/kotlin/treelib/TestModelAVL.kt +++ b/lib/src/test/kotlin/treelib/TestModelAVL.kt @@ -4,69 +4,81 @@ import treelib.avlTree.AVLNode class TestModelAVL { val firstTreeValues = - listOf(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, - 1, null, null, null, - 14, null, - 23) + listOf( + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, + 1, null, null, null, + 14, null, + 23 + ) val secondTreeValues = - listOf(null, null, 45, null, null, null, null, null, null, null, null, null, null, null, null, null, - 1, 47, 63, 90, 163, 208, 315, 999, - 44, 72, 205, 507, - 57, 230, - 101) + listOf( + null, null, 45, null, null, null, null, null, null, null, null, null, null, null, null, null, + 1, 47, 63, 90, 163, 208, 315, 999, + 44, 72, 205, 507, + 57, 230, + 101 + ) val thirdTreeValues = - listOf(null, 33, null, null, 69, 72, null, null, null, null, 174, null, null, null, 293, 370, - 10, 63, 70, 93, 139, 180, 240, 351, - 59, 74, 163, 285, - 67, 192, - 104) + listOf( + null, 33, null, null, 69, 72, null, null, null, null, 174, null, null, null, 293, 370, + 10, 63, 70, 93, 139, 180, 240, 351, + 59, 74, 163, 285, + 67, 192, + 104 + ) val thirdTreeValuesCase2 = - listOf(null, 33, null, null, 69, 72, null, null, null, null, 174, null, null, 293, null, null, - 10, 63, 70, 93, 139, 180, 285, 370, - 59, 74, 163, 351, - 67, 192, - 104) + listOf( + null, 33, null, null, 69, 72, null, null, null, null, 174, null, null, 293, null, null, + 10, 63, 70, 93, 139, 180, 285, 370, + 59, 74, 163, 351, + 67, 192, + 104 + ) val thirdTreeValuesCase3 = - listOf(null, 33, null, null, 69, 72, null, null, null, null, 174, null, null, null, null, null, - 10, 63, 70, 93, 139, 180, 285, 351, - 59, 74, 163, 293, - 67, 192, - 104) + listOf( + null, 33, null, null, 69, 72, null, null, null, null, 174, null, null, null, null, null, + 10, 63, 70, 93, 139, 180, 285, 351, + 59, 74, 163, 293, + 67, 192, + 104 + ) val thirdTreeValuesCase4 = - listOf(null, 33, null, null, 69, 72, null, null, null, null, null, null, null, null, null, null, - 10, 63, 70, 93, 163, 180, 285, 351, - 59, 74, 174, 293, - 67, 192, - 104) + listOf( + null, 33, null, null, 69, 72, null, null, null, null, null, null, null, null, null, null, + 10, 63, 70, 93, 163, 180, 285, 351, + 59, 74, 174, 293, + 67, 192, + 104 + ) - fun >getTree(values: List): AVLNode { + fun > getTree(values: List): AVLNode { val nodes = mutableListOf?>() for (i in 0..15) { if (values[i] != null) { nodes.add(AVLNode(values[i]!!, null, null)) - } - else + } else nodes.add(null) } for (i in 16..29) { if (values[i] != null) { - nodes.add(AVLNode(values[i]!!, nodes[2*(i-16)], nodes[2*(i-16)+1])) + nodes.add(AVLNode(values[i]!!, nodes[2 * (i - 16)], nodes[2 * (i - 16) + 1])) updateHeight(nodes[i]) - } - else + } else nodes.add(null) } nodes.add(AVLNode(values[30]!!, nodes[28], nodes[29])) return nodes[30]!! } - private fun >updateHeight(currentNode: AVLNode?) { + + private fun > updateHeight(currentNode: AVLNode?) { if (currentNode != null) - currentNode.height = ( maxOf(getHeight(currentNode.left), getHeight(currentNode.right)) + 1u) + currentNode.height = (maxOf(getHeight(currentNode.left), getHeight(currentNode.right)) + 1u) } - private fun >getHeight(currentNode: AVLNode?): UInt { + + private fun > getHeight(currentNode: AVLNode?): UInt { return currentNode?.height ?: 0u } diff --git a/lib/src/test/kotlin/treelib/TestModelRBT.kt b/lib/src/test/kotlin/treelib/TestModelRBT.kt index ca7efe7..9e5a0ad 100644 --- a/lib/src/test/kotlin/treelib/TestModelRBT.kt +++ b/lib/src/test/kotlin/treelib/TestModelRBT.kt @@ -4,17 +4,17 @@ import treelib.rbTree.RBNode import treelib.singleObjects.Markers class TestModelRBT { - fun >countBlackNodes(node: RBNode): Int { + fun > countBlackNodes(node: RBNode): Int { var count = 0 var currentNode: RBNode? = node while (currentNode != null) { - count = if (currentNode.color == Markers.BLACK) count+1 else count + count = if (currentNode.color == Markers.BLACK) count + 1 else count currentNode = currentNode.parent } return count } - fun >deleteNode(remoteNode: RBNode, newNode: RBNode): RBNode { + fun > deleteNode(remoteNode: RBNode, newNode: RBNode): RBNode { remoteNode.left?.parent = newNode remoteNode.right?.parent = newNode newNode.left = remoteNode.left @@ -32,8 +32,7 @@ class TestModelRBT { else -> parent.right = newNode } newNode.parent = parent - } - else { + } else { newNode.parent = null } @@ -86,17 +85,42 @@ class TestModelRBT { fun getFirstTree(): MutableList?> { val values = listOf( 1, 7, 11, 14, 16, 20, 21, null, 29, 38, null, 45, 52, 70, null, null, - 4, 12, 18, 24, 37, 42, 63, 90, - 10, 19, 40, 71, - 15, 50, + 4, 12, 18, 24, 37, 42, 63, 90, + 10, 19, 40, 71, + 15, 50, 25 ) val markers = listOf( - Markers.BLACK, Markers.BLACK, Markers.BLACK, Markers.BLACK, Markers.RED, Markers.RED, Markers.RED, null, - Markers.RED, Markers.RED, null, Markers.RED, Markers.BLACK, Markers.BLACK, Markers.RED, Markers.RED, - Markers.RED, Markers.RED, Markers.BLACK, Markers.BLACK, Markers.BLACK, Markers.BLACK, Markers.RED, Markers.BLACK, - Markers.BLACK, Markers.BLACK, Markers.BLACK, Markers.BLACK, - Markers.RED, Markers.RED, + Markers.BLACK, + Markers.BLACK, + Markers.BLACK, + Markers.BLACK, + Markers.RED, + Markers.RED, + Markers.RED, + null, + Markers.RED, + Markers.RED, + null, + Markers.RED, + Markers.BLACK, + Markers.BLACK, + Markers.RED, + Markers.RED, + Markers.RED, + Markers.RED, + Markers.BLACK, + Markers.BLACK, + Markers.BLACK, + Markers.BLACK, + Markers.RED, + Markers.BLACK, + Markers.BLACK, + Markers.BLACK, + Markers.BLACK, + Markers.BLACK, + Markers.RED, + Markers.RED, Markers.BLACK ) @@ -104,38 +128,66 @@ class TestModelRBT { for (i in 1..31) { when (i) { in 1..16 -> { - if (values[i-1] != null ) - nodes.add(RBNode(values[i-1]!!, null, null, null, markers[i-1]!!)) + if (values[i - 1] != null) + nodes.add(RBNode(values[i - 1]!!, null, null, null, markers[i - 1]!!)) else nodes.add(null) } + in 17..24 -> { val delta = i - 17 - if (values[i-1] != null) - nodes.add(RBNode(values[i-1]!!, nodes[i-17+delta], nodes[i-17+delta+1], null, markers[i-1]!!)) + if (values[i - 1] != null) + nodes.add( + RBNode( + values[i - 1]!!, + nodes[i - 17 + delta], + nodes[i - 17 + delta + 1], + null, + markers[i - 1]!! + ) + ) else nodes.add(null) - nodes[i-17+delta]?.parent = nodes[i-1] - nodes[i-17+delta+1]?.parent = nodes[i-1] + nodes[i - 17 + delta]?.parent = nodes[i - 1] + nodes[i - 17 + delta + 1]?.parent = nodes[i - 1] } + in 25..28 -> { - val delta = i-25 - nodes.add( RBNode(values[i-1]!!, nodes[i-9+delta], nodes[i-9+delta+1], null, markers[i-1]!!)) - nodes[i-9+delta]?.parent = nodes[i-1] - nodes[i-9+delta+1]?.parent = nodes[i-1] + val delta = i - 25 + nodes.add( + RBNode( + values[i - 1]!!, + nodes[i - 9 + delta], + nodes[i - 9 + delta + 1], + null, + markers[i - 1]!! + ) + ) + nodes[i - 9 + delta]?.parent = nodes[i - 1] + nodes[i - 9 + delta + 1]?.parent = nodes[i - 1] } + in 29..30 -> { - val delta = i-29 - nodes.add(RBNode(values[i-1]!!, nodes[i-5+delta], nodes[i-5+delta+1], null, markers[i-1]!!)) - nodes[i-5+delta]?.parent = nodes[i-1] - nodes[i-5+delta+1]?.parent = nodes[i-1] + val delta = i - 29 + nodes.add( + RBNode( + values[i - 1]!!, + nodes[i - 5 + delta], + nodes[i - 5 + delta + 1], + null, + markers[i - 1]!! + ) + ) + nodes[i - 5 + delta]?.parent = nodes[i - 1] + nodes[i - 5 + delta + 1]?.parent = nodes[i - 1] } + else -> { - nodes.add(RBNode(values[i-1]!!, nodes[28], nodes[29], null, markers[i-1]!!)) - nodes[28]?.parent = nodes[i-1] - nodes[29]?.parent = nodes[i-1] + nodes.add(RBNode(values[i - 1]!!, nodes[28], nodes[29], null, markers[i - 1]!!)) + nodes[28]?.parent = nodes[i - 1] + nodes[29]?.parent = nodes[i - 1] } } } diff --git a/lib/src/test/kotlin/utils/AVLAnalyzer.kt b/lib/src/test/kotlin/utils/AVLAnalyzer.kt index 15e7825..3d1a6fd 100644 --- a/lib/src/test/kotlin/utils/AVLAnalyzer.kt +++ b/lib/src/test/kotlin/utils/AVLAnalyzer.kt @@ -4,7 +4,7 @@ import treelib.avlTree.AVLNode import kotlin.math.abs import kotlin.math.max -class AVLAnalyzer>(override val assertMethod: (input: String) -> Unit) : Analyzer>() { +class AVLAnalyzer>(override val assertMethod: (input: String) -> Unit) : Analyzer>() { private var heightL = 0 private var heightR = 0 private var heightMax = 0 diff --git a/lib/src/test/kotlin/utils/RBAnalyzer.kt b/lib/src/test/kotlin/utils/RBAnalyzer.kt index 1b04aff..9b6b6db 100644 --- a/lib/src/test/kotlin/utils/RBAnalyzer.kt +++ b/lib/src/test/kotlin/utils/RBAnalyzer.kt @@ -79,7 +79,7 @@ class RBAnalyzer>( return errorMagicNumber } - if(node.color == Markers.BLACK) return leftBlackCount + 1 + if (node.color == Markers.BLACK) return leftBlackCount + 1 else return rightBlackCount } } \ No newline at end of file diff --git a/lib/src/test/kotlin/utils/TreeStructWrapper.kt b/lib/src/test/kotlin/utils/TreeStructWrapper.kt index 64fea41..ba9fb10 100644 --- a/lib/src/test/kotlin/utils/TreeStructWrapper.kt +++ b/lib/src/test/kotlin/utils/TreeStructWrapper.kt @@ -5,7 +5,7 @@ import treelib.abstractTree.StateContainer import treelib.abstractTree.TreeStruct import treelib.abstractTree.Vertex -class TreeStructWrapper, NodeType : Node, VertexType: Vertex, State: StateContainer, TStruct : TreeStruct> { +class TreeStructWrapper, NodeType : Node, VertexType : Vertex, State : StateContainer, TStruct : TreeStruct> { fun getPrivateNode(tree: TStruct, name: String = "root"): NodeType? { val field = tree.javaClass.getDeclaredField(name) @@ -15,7 +15,12 @@ class TreeStructWrapper, NodeType : Node, VertexT else root as? NodeType } - fun executePrivateMethod(tree: TStruct, name: String, parameterValues: Array?=null, vararg parameterTypes: Class<*>):Any? { + fun executePrivateMethod( + tree: TStruct, + name: String, + parameterValues: Array? = null, + vararg parameterTypes: Class<*> + ): Any? { val method = tree.javaClass.getDeclaredMethod(name, *parameterTypes) method.isAccessible = true return if (parameterValues != null) method.invoke(tree, *parameterValues) diff --git a/lib/src/test/kotlin/utils/TreeWrapper.kt b/lib/src/test/kotlin/utils/TreeWrapper.kt index 47858d9..a0abe1c 100644 --- a/lib/src/test/kotlin/utils/TreeWrapper.kt +++ b/lib/src/test/kotlin/utils/TreeWrapper.kt @@ -4,14 +4,14 @@ import treelib.abstractTree.* import treelib.singleObjects.Container -class TreeWrapper < +class TreeWrapper< V : Comparable, Value, - NodeType: Node, NodeType>, - VertexType: Vertex>, - State: StateContainer, NodeType>, - TStruct: TreeStruct, NodeType, State, VertexType>, - Wood : Tree> { + NodeType : Node, NodeType>, + VertexType : Vertex>, + State : StateContainer, NodeType>, + TStruct : TreeStruct, NodeType, State, VertexType>, + Wood : Tree> { fun getPrivateNode(tree: Wood, name: String = "treeStruct"): TStruct { val treeS = tree.javaClass.getDeclaredField(name) treeS.isAccessible = true diff --git a/lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt b/lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt index bc79507..720789c 100644 --- a/lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt +++ b/lib/src/test/kotlin/utils/fuzzers/BINStructFuzzer.kt @@ -6,10 +6,10 @@ import treelib.binTree.BINStruct import treelib.binTree.BINVertex import utils.BINAnalyzer -class BINStructFuzzer>( +class BINStructFuzzer>( override val baseInput: Array, override val assertMethod: (input: String) -> Unit -): TreeStructFuzzer, BINVertex, BINAnalyzer, BINStateContainer, BINStruct>() { +) : TreeStructFuzzer, BINVertex, BINAnalyzer, BINStateContainer, BINStruct>() { override fun createTreeStruct(): BINStruct = BINStruct() diff --git a/lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt b/lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt index 2a6bb7f..81d5278 100644 --- a/lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt +++ b/lib/src/test/kotlin/utils/fuzzers/RBStructFuzzer.kt @@ -6,10 +6,10 @@ import treelib.rbTree.RBStruct import treelib.rbTree.RBVertex import utils.RBAnalyzer -class RBStructFuzzer>( +class RBStructFuzzer>( override val baseInput: Array, override val assertMethod: (input: String) -> Unit -): TreeStructFuzzer, RBVertex, RBAnalyzer, RBStateContainer, RBStruct>() { +) : TreeStructFuzzer, RBVertex, RBAnalyzer, RBStateContainer, RBStruct>() { override fun createTreeStruct(): RBStruct = RBStruct() diff --git a/lib/src/test/kotlin/utils/fuzzers/TreeStructFuzzer.kt b/lib/src/test/kotlin/utils/fuzzers/TreeStructFuzzer.kt index 7d5e0d6..69421d8 100644 --- a/lib/src/test/kotlin/utils/fuzzers/TreeStructFuzzer.kt +++ b/lib/src/test/kotlin/utils/fuzzers/TreeStructFuzzer.kt @@ -43,7 +43,6 @@ abstract class TreeStructFuzzer< for (iterations in 0 until testNumbers) { val treeStruct = createTreeStruct() - println(dataSize) val testSetIndexes = getInputSetIndexes(dataSize) val testID = "${Instant.now().toEpochMilli() + iterations}-insert" val analyzer = createAnalyzer() @@ -119,12 +118,9 @@ abstract class TreeStructFuzzer< private fun saveCurrentTestSet(testId: String, testSet: List) { val file = File("./$dirPath/$testId.txt") file.createNewFile() -// println("./$dirPath/$testId.txt") for (index in testSet) { -// print("${baseInput[index]} ") file.appendText("${baseInput[index]} \n") } -// println() } -} \ No newline at end of file +} From 28f3c3a1a3020dd05d184ec46b3b105d14ba63bd Mon Sep 17 00:00:00 2001 From: Artem-Rzhankoff <113193908+Artem-Rzhankoff@users.noreply.github.com> Date: Wed, 19 Apr 2023 08:22:19 +0300 Subject: [PATCH 82/84] feat: Create LICENCE --- LICENCE | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 LICENCE diff --git a/LICENCE b/LICENCE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENCE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. From 2045d29e62b4e7aeaabe4360d2624db0b35aa5bc Mon Sep 17 00:00:00 2001 From: Artem-Rzhankoff <113193908+Artem-Rzhankoff@users.noreply.github.com> Date: Wed, 19 Apr 2023 08:25:22 +0300 Subject: [PATCH 83/84] Update README.md --- README.md | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6530b63..b073019 100644 --- a/README.md +++ b/README.md @@ -1 +1,43 @@ -Hi there +# Tree Structure + +This project will help the user to build an RBT, AVL or binary tree. Add, delete, or search for elements in it. + + +## Overview + +- You can create any tree of your choice (AVL, RB, Binary Tree) +- Insert, delete, check for any element +- Support for different types of elements + +## Setup + +To connect a project from Github using Gradle, you need to follow these steps: + +1. Open the build file.gradle your project +2. Find the "dependencies" block and add the dependency line to it: +```sh +dependencies { + implementation 'com.github.spbu-coding-2022:trees-1:1.0.0' +} +``` +3. Save the changes in the build file.gradle +4. Synchronize the project using Gradle + + + +## Project Status +Project is: _in progress_ + +## Room for Improvement +Room for improvement: +- preserving trees so that you can turn to history + +## Contacts +For all questions: [Click](http://telegram.me/LesokSupportbot) + + +## License +This project uses the APACHE LICENSE, VERSION 2.0. + +
+ From 14ea8b8ea377a2b5be5fae44e94f2a73f5df344f Mon Sep 17 00:00:00 2001 From: Georgy S Date: Wed, 19 Apr 2023 08:34:03 +0300 Subject: [PATCH 84/84] fix: Fix bugs after pull. --- .../main/kotlin/dbSave/jsonFormat/JsonRepository.kt | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/src/main/kotlin/dbSave/jsonFormat/JsonRepository.kt b/lib/src/main/kotlin/dbSave/jsonFormat/JsonRepository.kt index c2ca1c1..41a5971 100644 --- a/lib/src/main/kotlin/dbSave/jsonFormat/JsonRepository.kt +++ b/lib/src/main/kotlin/dbSave/jsonFormat/JsonRepository.kt @@ -4,15 +4,14 @@ import com.google.common.reflect.TypeToken import com.google.gson.GsonBuilder import java.io.File -class JsonRepository>(private val dirPath: String) { +class JsonRepository(private val dirPath: String) { init { File(dirPath).mkdirs() } - fun saveChanges( + fun >saveChanges( preOrder: Array>, - typeToken: TypeToken>>, fileName: String ) { @@ -24,13 +23,13 @@ class JsonRepository>(private val dirPath: String) { writeText(json) } - val preOrd = gson.fromJson>>(json, typeToken.type) - } - fun exportTree(fileName: String) { + fun >exportTree(fileName: String, typeToken: TypeToken>>) { val gson = GsonBuilder().setPrettyPrinting().create() - //val json = gson.fromJson(File(dirPath, fileName).readText(), ArrayVertices::class.java) + val json = File(dirPath, fileName).readText() + + val preOrd = gson.fromJson>>(json, typeToken.type) }