diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml
index ae15aca..243bd23 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
@@ -19,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/.gitignore b/.gitignore
index 7061064..16cba14 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
/.gradle/
/.idea/
/build/
-/lib/build/
\ No newline at end of file
+/lib/build/
+/lib/TEST_TEST/
+/gradle/
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.
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.
+
+
+
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..080c014 100644
--- a/lib/build.gradle.kts
+++ b/lib/build.gradle.kts
@@ -1,3 +1,4 @@
+val sqliteJdbcVersion: String by project
plugins {
java
kotlin("jvm") version "1.8.10"
@@ -19,11 +20,25 @@ 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")
+
+ 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")
- api("org.apache.commons:commons-math3:3.6.1")
- implementation("com.google.guava:guava:31.1-jre")
+ testImplementation("org.junit.jupiter:junit-jupiter-params:5.9.2")
+ implementation(kotlin("stdlib-jdk8"))
+
}
tasks.test {
@@ -76,7 +91,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 {
@@ -84,7 +99,7 @@ tasks.jacocoTestCoverageVerification {
element = "CLASS"
limit {
counter = "BRANCH"
- minimum = 0.4.toBigDecimal()
+ minimum = 0.5.toBigDecimal()
}
}
rule {
@@ -98,7 +113,7 @@ tasks.jacocoTestCoverageVerification {
element = "CLASS"
limit {
counter = "METHOD"
- minimum = 1.0.toBigDecimal()
+ minimum = 0.9.toBigDecimal()
}
}
}
@@ -113,4 +128,4 @@ publishing {
from(components["java"])
}
}
-}
\ No newline at end of file
+}
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/RBTreeManager.kt b/lib/src/main/kotlin/controller/RBTreeManager.kt
new file mode 100644
index 0000000..0d3456e
--- /dev/null
+++ b/lib/src/main/kotlin/controller/RBTreeManager.kt
@@ -0,0 +1,40 @@
+package controller
+
+import dbSave.neo4j.DrawRBVertex
+import dbSave.neo4j.Neo4jRepository
+import treelib.rbTree.RBStruct
+import treelib.singleObjects.Container
+
+class RBTreeManager {
+
+ /*** using neo4j ***/
+
+ fun initTree(treeName: String): RBStruct>> {
+ 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.restoreStruct(orders.first, orders.second)
+ neo4jDB.close()
+
+ return RBtree
+ }
+
+ 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/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()
+}
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/DrawVertex.kt b/lib/src/main/kotlin/dbSave/DrawVertex.kt
new file mode 100644
index 0000000..4108556
--- /dev/null
+++ b/lib/src/main/kotlin/dbSave/DrawVertex.kt
@@ -0,0 +1,7 @@
+package dbSave
+
+interface DrawVertex> {
+ val value: Pack
+ val x: Double
+ val y: Double
+}
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..41a5971
--- /dev/null
+++ b/lib/src/main/kotlin/dbSave/jsonFormat/JsonRepository.kt
@@ -0,0 +1,38 @@
+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>,
+ fileName: String
+ ) {
+
+ val gson = GsonBuilder().setPrettyPrinting().create()
+ val json = gson.toJson(preOrder)
+
+ File(dirPath, fileName).run {
+ createNewFile()
+ writeText(json)
+ }
+
+ }
+
+ fun >exportTree(fileName: String, typeToken: TypeToken>>) {
+ val gson = GsonBuilder().setPrettyPrinting().create()
+ val json = File(dirPath, fileName).readText()
+
+ val preOrd = gson.fromJson>>(json, typeToken.type)
+
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/lib/src/main/kotlin/dbSave/neo4j/CONTAINER.conf b/lib/src/main/kotlin/dbSave/neo4j/CONTAINER.conf
new file mode 100644
index 0000000..9b9fb0a
--- /dev/null
+++ b/lib/src/main/kotlin/dbSave/neo4j/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/dbSave/neo4j/DrawRBVertex.kt b/lib/src/main/kotlin/dbSave/neo4j/DrawRBVertex.kt
new file mode 100644
index 0000000..37100de
--- /dev/null
+++ b/lib/src/main/kotlin/dbSave/neo4j/DrawRBVertex.kt
@@ -0,0 +1,11 @@
+package dbSave.neo4j
+
+import treelib.rbTree.RBVertex
+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/dbSave/neo4j/Neo4jRepository.kt b/lib/src/main/kotlin/dbSave/neo4j/Neo4jRepository.kt
new file mode 100644
index 0000000..f04cf8c
--- /dev/null
+++ b/lib/src/main/kotlin/dbSave/neo4j/Neo4jRepository.kt
@@ -0,0 +1,209 @@
+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.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>>>> {
+
+ /*** Плохо, что передаем Container с четко привязанными типами (K, V), потому что может быть так, что вместо контейнера будет просто инт ***/
+
+ 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/dbSave/neo4j/testNeo4j.sh b/lib/src/main/kotlin/dbSave/neo4j/testNeo4j.sh
new file mode 100644
index 0000000..6b07269
--- /dev/null
+++ b/lib/src/main/kotlin/dbSave/neo4j/testNeo4j.sh
@@ -0,0 +1,13 @@
+
+BASEDIR=$(realpath "$(dirname "$0")")
+
+. "${BASEDIR}/CONTAINER.conf"
+
+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 \
diff --git a/lib/src/main/kotlin/dbSave/sqlite/DrawAVLVertex.kt b/lib/src/main/kotlin/dbSave/sqlite/DrawAVLVertex.kt
new file mode 100644
index 0000000..e6feb46
--- /dev/null
+++ b/lib/src/main/kotlin/dbSave/sqlite/DrawAVLVertex.kt
@@ -0,0 +1,10 @@
+package dbSave.sqlite
+
+import dbSave.DrawVertex
+
+class DrawAVLVertex>(
+ override val value: Pack,
+ override val x: Double,
+ override val y: Double,
+ val height: Int,
+) : DrawVertex
diff --git a/lib/src/main/kotlin/dbSave/sqlite/SQLiteRepository.kt b/lib/src/main/kotlin/dbSave/sqlite/SQLiteRepository.kt
new file mode 100644
index 0000000..1d4cf20
--- /dev/null
+++ b/lib/src/main/kotlin/dbSave/sqlite/SQLiteRepository.kt
@@ -0,0 +1,227 @@
+package dbSave.sqlite
+
+import java.io.Closeable
+import java.sql.DriverManager
+import java.sql.SQLException
+
+class SQLiteRepository>(
+ 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("Available tree is given")
+ } 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()
+ }
+ }
+ }
+
+ 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: DrawAVLVertex, 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: MutableList>, 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(
+ DrawAVLVertex(
+ 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: DrawAVLVertex, 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()
+ }
+}
diff --git a/lib/src/main/kotlin/treelib/abstractTree/Tree.kt b/lib/src/main/kotlin/treelib/abstractTree/Tree.kt
index b64cca1..fb0976a 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.pair)
+ 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 2f21c10..fa403bc 100644
--- a/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt
+++ b/lib/src/main/kotlin/treelib/abstractTree/TreeStruct.kt
@@ -6,11 +6,16 @@ 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,
+ VertexType : Vertex
+ > {
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) {
@@ -47,7 +52,8 @@ abstract class TreeStruct, NodeType : Node
+ }
+ ?: throw BugInImplementException("getParentByValue shouldn't be used with value doesn't exist in tree")// (1)l ->
}
}
@@ -70,7 +76,8 @@ abstract class TreeStruct, NodeType : Node, NodeType : Node it.value) currentNode = it.right
else currentNode = it.left
- } ?: return generateStateFind(null)
+ }
+ if (currentNode == null) return generateStateFind(null, null)
}
}
}
@@ -158,11 +166,12 @@ abstract class TreeStruct, NodeType : Node, NodeType : Node, NodeType : Node {
- val arrayNodes = mutableListOf()
+ fun inOrder(): List {
+ val arrayNodes = mutableListOf()
var flagVisited = 0
var current = root
val parents = ArrayDeque()
@@ -268,24 +281,26 @@ abstract class TreeStruct, NodeType : Node {
+ abstract fun toVertex(node: NodeType): VertexType
+
+ fun postOrder(): List {
val parents = ArrayDeque()
- val arrayNodes = mutableListOf()
+ val arrayNodes = mutableListOf()
var flagVisited = 0
var current = root
@@ -306,9 +321,9 @@ abstract class TreeStruct, NodeType : Node, NodeType : Node {
- val arrayNodes = mutableListOf()
+ fun preOrder(): List {
+ val arrayNodes = mutableListOf()
var current: NodeType
val queue = ArrayDeque()
@@ -329,7 +344,7 @@ abstract class TreeStruct, NodeType : Node, NodeType : Node> {
+ 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..5172f71 100644
--- a/lib/src/main/kotlin/treelib/abstractTree/balanced/BalancedTreeStruct.kt
+++ b/lib/src/main/kotlin/treelib/abstractTree/balanced/BalancedTreeStruct.kt
@@ -3,26 +3,28 @@ 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
- 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/AVLBalancer.kt b/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt
index 703ea69..1a3afb9 100644
--- a/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt
+++ b/lib/src/main/kotlin/treelib/avlTree/AVLBalancer.kt
@@ -1,8 +1,6 @@
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>() {
@@ -19,16 +17,17 @@ class AVLBalancer>(private var root: AVLNode?) :
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 +37,8 @@ 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 +48,8 @@ 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 +59,5 @@ class AVLBalancer>(private var root: AVLNode?) :
}
return currentNode
}
+
}
diff --git a/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt b/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt
index f275439..6d89668 100644
--- a/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt
+++ b/lib/src/main/kotlin/treelib/avlTree/AVLStruct.kt
@@ -1,9 +1,10 @@
package treelib.avlTree
import treelib.abstractTree.balanced.BalancedTreeStruct
+import treelib.singleObjects.exceptions.IncorrectUsage
class AVLStruct> :
- BalancedTreeStruct, AVLStateContainer, AVLBalancer>() {
+ BalancedTreeStruct, AVLStateContainer, AVLVertex, AVLBalancer>() {
override var root: AVLNode? = null
override val balancer = AVLBalancer(root)
@@ -40,6 +41,10 @@ class AVLStruct> :
}
}
+ 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)
override fun getNodeKernel(node: AVLNode): AVLNode = AVLNode(node.value, height = node.height)
@@ -52,4 +57,13 @@ class AVLStruct> :
}
return node
}
+
+ fun > restoreStruct(preOrder: MutableList) {
+ 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/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..774d064
--- /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()
diff --git a/lib/src/main/kotlin/treelib/binTree/BINStruct.kt b/lib/src/main/kotlin/treelib/binTree/BINStruct.kt
index e555924..c033266 100644
--- a/lib/src/main/kotlin/treelib/binTree/BINStruct.kt
+++ b/lib/src/main/kotlin/treelib/binTree/BINStruct.kt
@@ -1,9 +1,11 @@
package treelib.binTree
import treelib.abstractTree.TreeStruct
+import treelib.abstractTree.Vertex
+import treelib.singleObjects.exceptions.IncorrectUsage
class BINStruct> :
- TreeStruct, BINStateContainer>() {
+ TreeStruct, BINStateContainer, BINVertex>() {
override var root: BINNode? = null
@@ -53,6 +55,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) {
@@ -62,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/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..cb489a0
--- /dev/null
+++ b/lib/src/main/kotlin/treelib/binTree/BINVertex.kt
@@ -0,0 +1,5 @@
+package treelib.binTree
+
+import treelib.abstractTree.Vertex
+
+open class BINVertex>(override val value: Pack) : Vertex()
\ 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 fe73c5b..c8c4cf6 100644
--- a/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt
+++ b/lib/src/main/kotlin/treelib/rbTree/RBBalancer.kt
@@ -4,9 +4,9 @@ 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>() {
+class RBBalancer>(private var root: RBNode?) :
+ BalancerParent, RBStateContainer>() {
init {
root?.color = Markers.BLACK
@@ -30,7 +30,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,17 +38,17 @@ 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 IllegalBaseNodeException()
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,52 +58,57 @@ 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 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 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) ->
- {
+ 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) ||
@@ -112,16 +117,16 @@ 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 IllegalNodeStateException()
+ else -> throw IllegalStateException()
}
}
}
- throw ImpossibleCaseException()
+ throw IllegalStateException()
}
private fun afterInsert(node: RBNode): RBNode {
@@ -133,8 +138,7 @@ class RBBalancer>(private var root: RBNode?): Balan
currentNode = currentNode.parent?.parent ?: throw IllegalNodeStateException()
currentNode.color = Markers.RED
uncle.color = Markers.BLACK
- }
- else if(uncle != null){
+ } else if (uncle != null) {
return currentNode
}
}
@@ -145,7 +149,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 +158,13 @@ class RBBalancer>(private var root: RBNode?): Balan
getRoot(parent)
}
- else -> getRoot(node ?: throw IllegalBaseNodeException())
+ else -> getRoot(node ?: throw IllegalNodeStateException())
}
}
/** parent is red **/
private fun secondCase(parent: RBNode, node: RBNode?) {
- var brother = getBrother(parent, node) ?: throw IllegalBaseNodeException()
+ var brother = getBrother(parent, node) ?: throw IllegalNodeStateException()
if (brother.color == Markers.RED)
throw NullPointerException()
@@ -171,52 +175,48 @@ class RBBalancer>(private var root: RBNode