diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 25f9bf2..c2df060 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,10 +5,12 @@ on: branches: - main - develop + - fixes-after-1st-review push: branches: - main - develop + - fixes-after-1st-review workflow_dispatch: jobs: @@ -17,15 +19,19 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + - name: Set up Java JDK uses: actions/setup-java@v4 with: java-version: 17 cache: gradle distribution: "temurin" + - name: Set up Gradle uses: gradle/actions/setup-gradle@v3 + - name: Build with Gradle run: ./gradlew build + - name: Run tests run: ./gradlew test diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 0000000..8e40a86 --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,56 @@ +name: Jacoco coverage + +on: + pull_request: + branches: + - main + - develop + - fixes-after-1st-review + push: + branches: + - main + - develop + - fixes-after-1st-review + workflow_dispatch: + +jobs: + coverage: + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Java JDK + uses: actions/setup-java@v4 + with: + java-version: 17 + distribution: "temurin" + + - name: Set up Gradle + uses: gradle/actions/setup-gradle@v3 + + - name: Run Coverage + run: ./gradlew jacocoTestReport + + - name: Generate JaCoCo Report + uses: cicirello/jacoco-badge-generator@v2 + with: + generate-branches-badge: true + jacoco-csv-file: lib/build/reports/jacoco/test/jacocoTestReport.csv + + - name: Add coverage to PR + id: jacoco + uses: madrapps/jacoco-report@v1.6.1 + with: + paths: | + ${{ github.workspace }}/lib/build/reports/jacoco/test/jacocoTestReport.xml, + ${{ github.workspace }}/**/build/reports/jacoco/**/debugCoverage.xml + token: ${{ secrets.GITHUB_TOKEN }} + title: '# 🇷🇺 Coverage Report' + update-comment: true + min-coverage-overall: 40 + min-coverage-changed-files: 60 + pass-emoji: '🥳' + fail-emoji: '🤡' diff --git a/.github/workflows/ktlint.yml b/.github/workflows/ktlint.yml index 8fcfbd4..f58f9f6 100644 --- a/.github/workflows/ktlint.yml +++ b/.github/workflows/ktlint.yml @@ -5,10 +5,12 @@ on: branches: - main - develop + - fixes-after-1st-review push: branches: - main - develop + - fixes-after-1st-review workflow_dispatch: jobs: diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index dcb7919..50adebb 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -14,6 +14,9 @@ plugins { // Code coverage plugin jacoco + + // Documentation generation + id("org.jetbrains.dokka") version "1.9.20" } repositories { @@ -31,6 +34,8 @@ dependencies { testImplementation(libs.junit.jupiter.engine) testRuntimeOnly("org.junit.platform:junit-platform-launcher") + + compileOnly("org.jetbrains.dokka:dokka-core:1.9.20") } // Apply a specific Java toolchain to ease working on different environments. @@ -48,8 +53,28 @@ tasks.named("test") { tasks.named("jacocoTestReport") { dependsOn(tasks.test) reports { - csv.required = false - xml.required = false + csv.required = true + xml.required = true html.outputLocation = layout.buildDirectory.dir("jacocoHtml") } } + +tasks.dokkaHtml { + outputDirectory.set(layout.buildDirectory.dir("documentation/html")) +} + +tasks.dokkaGfm { + outputDirectory.set(layout.buildDirectory.dir("documentation/markdown")) +} + +tasks.register("dokkaHtmlJar") { + dependsOn(tasks.dokkaHtml) + from(tasks.dokkaHtml.flatMap { it.outputDirectory }) + archiveClassifier.set("html-docs") +} + +tasks.register("dokkaJavadocJar") { + dependsOn(tasks.dokkaJavadoc) + from(tasks.dokkaJavadoc.flatMap { it.outputDirectory }) + archiveClassifier.set("javadoc") +} diff --git a/lib/src/main/kotlin/iterator/TreeIterator.kt b/lib/src/main/kotlin/iterator/TreeIterator.kt index f58f3bf..1365945 100644 --- a/lib/src/main/kotlin/iterator/TreeIterator.kt +++ b/lib/src/main/kotlin/iterator/TreeIterator.kt @@ -1,11 +1,13 @@ -package main.iterator +package iterator -import main.vertexes.InterfaceBSTVertex -import java.util.LinkedList +import vertexes.InterfaceBSTVertex +import java.util.Stack /** * Iterator iterates over the vertices of the tree, visiting each vertex in the order of a depth-first traversal. - * Iterator interface implementation. + * + * [Iterator] interface implementation. + * * @param K the type of keys in the tree * @param V the type of values associated with the keys * @param N the type of tree vertices implementing InterfaceBSTVertex @@ -13,7 +15,7 @@ import java.util.LinkedList open class TreeIterator>( vertex: N?, ) : Iterator> { - protected val stack = LinkedList() + protected val stack = Stack() init { // Initialize the iterator with the given vertex by adding it to the stack @@ -22,7 +24,9 @@ open class TreeIterator>( /** * Returns true if the iterator has more elements. + * * This method checks if there are more vertices to traverse in the tree. + * * @return true if the iterator has more elements, otherwise false */ override fun hasNext(): Boolean { @@ -31,11 +35,13 @@ open class TreeIterator>( /** * Returns the next element in the iteration. + * * This method returns the next vertex in the depth-first traversal of the tree. + * * @return the next element in the iteration as a Pair containing the key and value of the vertex */ override fun next(): Pair { - val nextVertex: N = stack.removeLast() + val nextVertex: N = stack.pop() nextVertex.leftSon?.let { stack.add(it) } nextVertex.rightSon?.let { stack.add(it) } return Pair(nextVertex.key, nextVertex.value) diff --git a/lib/src/main/kotlin/trees/AVLSearchTree.kt b/lib/src/main/kotlin/trees/AVLSearchTree.kt index 506b569..0fb1771 100644 --- a/lib/src/main/kotlin/trees/AVLSearchTree.kt +++ b/lib/src/main/kotlin/trees/AVLSearchTree.kt @@ -1,44 +1,37 @@ -package main.trees +package trees -import main.vertexes.AVLVertex +import vertexes.AVLVertex /** * An implementation of a binary search tree that automatically balances itself using AVL rotations. - * It extends AbstractBinarySearchTree and uses AVLVertex as vertices. - * This class extends AbstractBinarySearchTree and provides methods to put, remove for key-value pairs. * - * When attempting to perform insertion, removal, or search operations on a non-empty binary search tree with a key that - * is incomparable with the keys in the tree, the behavior is as follows: + * It extends [AbstractBinarySearchTree] and uses [AVLVertex] as vertices. * - * **Put**: If an attempt is made to put a key-value pair with a key that is incomparable with the existing - * keys in the tree, the insertion operation will fail and the tree will remain unchanged. + * If the tree has an incomparable key type and comparator is `null`, if the tree + * is non-empty, when trying to call the search, insert and delete methods, the tree + * will remain unchanged, the operation throws an exception with the message "Key's + * type is incomparable and comparator was not given". * - * **Remove**: If an attempt is made to remove a key-value pair with a key that is incomparable with the existing keys - * in the tree, the removal operation will fail and the tree will remain unchanged. - * - * **Get**: When getting for a key that is incomparable with the keys in the tree, the search operation will not - * find any matching key-value pair the get operation will fail. - * - * @param K the type of keys in the tree - * @param V the type of values associated with the keys - * @property comparator The comparator used to order the keys. If null, keys are expected to be comparable. - * @property size The number of elements in the tree. - * @property root The root vertex of the tree. + * @param K key type + * @param V value type + * @property comparator `Comparator?` type; used optionally to compare keys in a tree. If `null`, it is expected that keys of comparable type. + * @property size `Long` type; number of key-value pairs in this tree + * @property root `AVLVertex?` type, `null` by default */ open class AVLSearchTree : AbstractBinarySearchTree> { /** - * Associates the specified value with the specified key in this tree. - * If parameter replaceIfExists is true and the key already exists, the value is replaced; otherwise, the value is ignored. - * @param key the key with which the specified value is to be associated - * @param value the value to be associated with the specified key - * @param replaceIfExists if true, replaces the value if the key already exists, otherwise ignores it + * Puts a new vertex of a certain type into the tree with a given key and value + * + * @param key `K` type + * @param value `V` type, associated with this key + * @param replaceIfExists `Boolean` type; If `true` - replaces the value if the key already exists. If `false` - ignores it. */ override fun put( key: K, value: V, replaceIfExists: Boolean, ) { - if (!isEmpty()) { + if (isNotEmpty()) { when (val putRecReturned = putRec(key, value, replaceIfExists, root as AVLVertex)) { null, root -> {} else -> root = putRecReturned @@ -50,13 +43,13 @@ open class AVLSearchTree : AbstractBinarySearchTree> } /** - * Associates the specified value with the specified key in this tree. - * If replaceIfExists is true and the key already exists, the value is replaced; otherwise, the value is ignored. - * @param key the key with which the specified value is to be associated - * @param value the value to be associated with the specified key - * @param replaceIfExists if true, replaces the value if the key already exists, otherwise ignores it - * @param vertex the current vertex in the recursion - * @return the root vertex of the tree after the operation + * Associates the specified value with the specified key in this tree + * + * @param key `K` type + * @param value `V` type + * @param replaceIfExists `Boolean` type; If `true` - replaces the value if the key already exists. If `false` - ignores it. + * @param vertex `AVLVertex` type; current vertex in the recursion + * @return root vertex of the tree after the operation */ private fun putRec( key: K, @@ -64,8 +57,8 @@ open class AVLSearchTree : AbstractBinarySearchTree> replaceIfExists: Boolean, vertex: AVLVertex, ): AVLVertex? { - fun putRecShort(vrtx: AVLVertex): AVLVertex? { - return putRec(key, value, replaceIfExists, vrtx) + fun putRecShort(vertex: AVLVertex): AVLVertex? { + return putRec(key, value, replaceIfExists, vertex) } val nextCallReturned: AVLVertex? @@ -102,15 +95,13 @@ open class AVLSearchTree : AbstractBinarySearchTree> fun doBalanceChoreWhenLeftSubTreeChanged(): AVLVertex? { if (nextCallReturned.sonsHeightDiff == 0) return null - if (vertex.sonsHeightDiff + 1 == 2) return balance(vertex) - vertex.sonsHeightDiff++ + if (++vertex.sonsHeightDiff == 2) return balance(vertex) return vertex } fun doBalanceChoreWhenRightSubTreeChanged(): AVLVertex? { if (nextCallReturned.sonsHeightDiff == 0) return null - if (vertex.sonsHeightDiff - 1 == -2) return balance(vertex) - vertex.sonsHeightDiff-- + if (--vertex.sonsHeightDiff == -2) return balance(vertex) return vertex } when (nextCallReturned) { @@ -128,12 +119,13 @@ open class AVLSearchTree : AbstractBinarySearchTree> } /** - * Removes the mapping for a key from this tree if it is present. - * @param key the key whose mapping is to be removed from the tree - * @return the previous value associated with key, or null if there was no mapping for key + * Removes the mapping for a key from this tree if it is present + * + * @param key `K` type + * @return the previous value associated with key, or `null` if there was no mapping for key */ override fun remove(key: K): V? { - if (!isEmpty()) { + if (isNotEmpty()) { val removeRecReturned = removeRec(key, root as AVLVertex) when (removeRecReturned.first) { RemovalStage.B -> { @@ -143,7 +135,6 @@ open class AVLSearchTree : AbstractBinarySearchTree> } RemovalStage.C -> root = null - RemovalStage.D -> root = removeRecReturned.component2() else -> {} } return removeRecReturned.component3() @@ -161,24 +152,20 @@ open class AVLSearchTree : AbstractBinarySearchTree> A, /** - * Probably need some tree changes, but not nulling + * Probably need some tree changes, but not make the son of the vertex `null` */ B, /** - * Need to null due "Son" property of (if exists) the parent of removed vertex + b + * Need to `null` due "Son" property of (if exists) the parent of removed vertex + b */ C, - - /** - * Need only to change due "Son" property of (if exists) the parent - */ - D, } /** - * Recursively removes a key-value pair from the subtree rooted at the given vertex. - * @param key the key to remove + * Recursively removes a key-value pair from the subtree rooted at the given vertex + * + * @param key `K` type * @param vertex the root of the subtree to remove from * @return Triple that consists of: * @@ -190,7 +177,7 @@ open class AVLSearchTree : AbstractBinarySearchTree> * * if RemovalStage == c : the removed vertex; * - * 3) a value of the removed vertex (or null if key not exists). */ + * 3) a value of the removed vertex (or `null` if key not exists). */ private fun removeRec( key: K, vertex: AVLVertex, @@ -204,7 +191,7 @@ open class AVLSearchTree : AbstractBinarySearchTree> * if RemovalStage == b : the root of the changed subtree; * if RemovalStage == c : the removed vertex; * - * 3) a value of the removed vertex (or null if key not exists). + * 3) a value of the removed vertex (or `null` if key not exists). */ val nextCallReturned: Triple?, V?> when (compareKeys(key, vertex.key)) { @@ -235,12 +222,14 @@ open class AVLSearchTree : AbstractBinarySearchTree> Triple(RemovalStage.B, vertex.leftSon as AVLVertex, vertex.value) } - else -> + else -> { + val valueOfVertex = vertex.value Triple( - RemovalStage.D, - prepareLargestLowerToReplaceVertex(vertex), - vertex.value, + RemovalStage.B, + replaceSubtreeSRootByLargestInItsLeftSubtree(vertex), + valueOfVertex, ) + } } } } @@ -249,10 +238,9 @@ open class AVLSearchTree : AbstractBinarySearchTree> if (nextCallReturned.component2().sonsHeightDiff in listOf(-1, 1)) { return Triple(RemovalStage.A, vertex, nextCallReturned.component3()) } - if (vertex.sonsHeightDiff - 1 == -2) { + if (--vertex.sonsHeightDiff == -2) { return Triple(RemovalStage.B, balance(vertex), nextCallReturned.component3()) } - vertex.sonsHeightDiff-- return Triple(RemovalStage.B, vertex, nextCallReturned.third) } @@ -260,10 +248,9 @@ open class AVLSearchTree : AbstractBinarySearchTree> if (nextCallReturned.component2().sonsHeightDiff in listOf(-1, 1)) { return Triple(RemovalStage.A, vertex, nextCallReturned.component3()) } - if (vertex.sonsHeightDiff + 1 == 2) { + if (++vertex.sonsHeightDiff == 2) { return Triple(RemovalStage.B, balance(vertex), nextCallReturned.component3()) } - vertex.sonsHeightDiff++ return Triple(RemovalStage.B, vertex, nextCallReturned.component3()) } when (nextCallReturned.component1()) { @@ -298,41 +285,38 @@ open class AVLSearchTree : AbstractBinarySearchTree> return doBalanceChoreWhenRightSubTreeChanged() } } - - RemovalStage.D -> { - if (compareKeys(nextCallReturned.component2().key, vertex.key) == -1) { - vertex.leftSon = nextCallReturned.component2() - } else { - vertex.rightSon = nextCallReturned.component2() - } - return Triple(RemovalStage.A, vertex, nextCallReturned.component3()) - } } } /** - * Prepares the largest lower vertex to replace the specified vertex. - * @param vertex the vertex to be replaced - * @return the substitute vertex prepared to replace the specified vertex + * Replaces the initially subtree's root by the its left subtree's vertex with largest key, + * having previously removed that vertex + * + * @param subtreeSInitiallyRoot `AVLVertex` type; initially root of the subtree + * @return vertex that is the subtree's root after function was executed */ - private fun prepareLargestLowerToReplaceVertex(vertex: AVLVertex): AVLVertex { - val substitute = getMaxKeyNodeRec(vertex.leftSon) as AVLVertex - remove(substitute.key) - substitute.leftSon = vertex.leftSon - substitute.rightSon = vertex.rightSon - substitute.sonsHeightDiff = vertex.sonsHeightDiff - return substitute + private fun replaceSubtreeSRootByLargestInItsLeftSubtree(subtreeSInitiallyRoot: AVLVertex): AVLVertex { + val substitute = getMaxKeyNodeRec(subtreeSInitiallyRoot.leftSon) as AVLVertex + val removeRecReturned = removeRec(substitute.key, subtreeSInitiallyRoot) + subtreeSInitiallyRoot.key = substitute.key + subtreeSInitiallyRoot.value = substitute.value + return if (removeRecReturned.component1() == RemovalStage.A) { + subtreeSInitiallyRoot + } else { + removeRecReturned.component2() + } } /** - * Balances the subtree. - * @param curVertex the root vertex of subtree to be balanced - * @return the root vertex of the subtree after balancing + * Balances the subtree + * + * @param curVertex `AVLVertex` type; the root vertex of subtree to be balanced + * @return root vertex of the subtree after balancing */ private fun balance(curVertex: AVLVertex): AVLVertex { var (rightSon, leftSon) = List?>(2) { null } - fun setSonSHeightDiffsOfTwoVerteces(values: Pair) { + fun setSonSHeightDiffsOfTwoVertices(values: Pair) { curVertex.sonsHeightDiff = values.component1() if (rightSon != null) { (rightSon as AVLVertex).sonsHeightDiff = values.component2() @@ -341,12 +325,12 @@ open class AVLSearchTree : AbstractBinarySearchTree> (leftSon as AVLVertex).sonsHeightDiff = values.component2() } - if (curVertex.sonsHeightDiff == -1) { + if (curVertex.sonsHeightDiff == -2) { rightSon = curVertex.rightSon as AVLVertex return if (rightSon.sonsHeightDiff == 1) { val rightSonSLeftSon = rightSon.leftSon as AVLVertex val subtreeRoot = bigRotateLeft(curVertex, rightSon) - setSonSHeightDiffsOfTwoVerteces( + setSonSHeightDiffsOfTwoVertices( when (rightSonSLeftSon.sonsHeightDiff) { 1 -> 0 to -1 -1 -> 1 to 0 @@ -357,7 +341,7 @@ open class AVLSearchTree : AbstractBinarySearchTree> subtreeRoot } else { val subtreeRoot = rotateLeft(curVertex, rightSon) - setSonSHeightDiffsOfTwoVerteces( + setSonSHeightDiffsOfTwoVertices( if (rightSon.sonsHeightDiff == 0) { -1 to 1 } else { @@ -371,7 +355,7 @@ open class AVLSearchTree : AbstractBinarySearchTree> return if (leftSon.sonsHeightDiff == -1) { val leftSonSRightSon = leftSon.rightSon as AVLVertex val subtreeRoot = bigRotateRight(curVertex, leftSon) - setSonSHeightDiffsOfTwoVerteces( + setSonSHeightDiffsOfTwoVertices( when (leftSonSRightSon.sonsHeightDiff) { -1 -> 0 to 1 1 -> -1 to 0 @@ -382,7 +366,7 @@ open class AVLSearchTree : AbstractBinarySearchTree> subtreeRoot } else { val subtreeRoot = rotateRight(curVertex, leftSon) - setSonSHeightDiffsOfTwoVerteces( + setSonSHeightDiffsOfTwoVertices( if (leftSon.sonsHeightDiff == 0) { 1 to -1 } else { @@ -394,9 +378,10 @@ open class AVLSearchTree : AbstractBinarySearchTree> } /** - * Performs a single left rotation of the subtree. - * @param curVertex the current vertex to rotate around (the subtree's root) - * @param rightSon the right son of the subtree's root + * Performs a single left rotation of the subtree + * + * @param curVertex `AVLVertex` type; the current vertex to rotate around (the subtree's root) + * @param rightSon `AVLVertex` type; the right son of the subtree's root * @return the new root of the subtree after rotation */ private fun rotateLeft( @@ -409,9 +394,10 @@ open class AVLSearchTree : AbstractBinarySearchTree> } /** - * Performs a single right rotation of the subtree. - * @param curVertex the current vertex to rotate around (the subtree's root) - * @param leftSon the left son of the subtree's root + * Performs a single right rotation of the subtree + * + * @param curVertex `AVLVertex` type; the current vertex to rotate around (the subtree's root) + * @param leftSon `AVLVertex` type; the left son of the subtree's root * @return the new root of the subtree after rotation */ private fun rotateRight( @@ -424,9 +410,10 @@ open class AVLSearchTree : AbstractBinarySearchTree> } /** - * Performs a big left rotation of the subtree. - * @param curVertex the current vertex to rotate around (the subtree's root) - * @param rightSon the right son of the subtree's root + * Performs a big left rotation of the subtree + * + * @param curVertex `AVLVertex` type; the current vertex to rotate around (the subtree's root) + * @param rightSon `AVLVertex` type; the right son of the subtree's root * @return the new root of the subtree after rotation */ private fun bigRotateLeft( @@ -439,10 +426,11 @@ open class AVLSearchTree : AbstractBinarySearchTree> } /** - * Performs a big right rotation of the subtree. - * @param curVertex the current vertex to rotate around (the subtree's root) - * @param leftSon the left son vertex of the subtree's root - * @return the new root root of the subtree after rotation + * Performs a big right rotation of the subtree + * + * @param curVertex `AVLVertex` type; the current vertex to rotate around (the subtree's root) + * @param leftSon `AVLVertex` type; the left son vertex of the subtree's root + * @return the new root of the subtree after rotation */ private fun bigRotateRight( curVertex: AVLVertex, @@ -454,16 +442,21 @@ open class AVLSearchTree : AbstractBinarySearchTree> } /** - * Constructs a new binary search tree with the specified comparator. - * @param comparator the comparator to use for comparing keys, or null to use natural ordering + * Constructs a new binary search tree with the specified comparator + * + * @param comparator `Comparator?` type, `null `by default; used optionally to compare keys in a tree. If `null`, it is expected that keys of comparable type. */ constructor (comparator: Comparator? = null) : super(comparator) /** - * Constructs a new binary search tree and initializes it with the mappings from the specified map. - * @param map the map whose mappings are to be added to this tree - * @param replaceIfExists if true, replaces the value if the key already exists, otherwise ignores it - * @param comparator the comparator to use for comparing keys, or null to use natural ordering + * Constructs a new binary search tree and puts all key-value pairs from the specified map to this tree + * + * @param map `Map` type + * @param replaceIfExists `Boolean` type. + * If `true` - replaces the value if the key already exists. If `false` - ignores it. + * Supplied only if a [comparator] is present. If comparator is `null`, the value is replaced + * by the last value from the key-value pair in the map, where the key is the one already existing in the tree. + * @param comparator `Comparator?` type, `null `by default; used optionally to compare keys in a tree. If `null`, it is expected that keys of comparable type. */ constructor(map: Map, replaceIfExists: Boolean = true, comparator: Comparator? = null) : super( map, diff --git a/lib/src/main/kotlin/trees/AbstractBinarySearchTree.kt b/lib/src/main/kotlin/trees/AbstractBinarySearchTree.kt index 76c04ef..c16753c 100644 --- a/lib/src/main/kotlin/trees/AbstractBinarySearchTree.kt +++ b/lib/src/main/kotlin/trees/AbstractBinarySearchTree.kt @@ -1,79 +1,72 @@ -package main.trees +package trees -import main.iterator.TreeIterator -import main.vertexes.InterfaceBSTVertex +import iterator.TreeIterator +import vertexes.InterfaceBSTVertex /** * An abstract class representing a binary search tree. * - * When attempting to perform insertion, removal, or search operations on a non-empty binary search tree with a key that - * is incomparable with the keys in the tree, the behavior is as follows: + * If the tree has an incomparable key type and comparator is `null`, if the tree + * is non-empty, when trying to call the search, insert and delete methods, the tree + * will remain unchanged, the operation throws an exception with the message "Key's + * type is incomparable and comparator was not given". * - * **Put**: If an attempt is made to insert a key-value pair with a key that is incomparable with the existing - * keys in the tree, the insertion operation will fail and the tree will remain unchanged. - * - * **Remove**: If an attempt is made to remove a key-value pair with a key that is incomparable with the existing keys - * in the tree, the removal operation will fail and the tree will remain unchanged. - * - * **Get**: When searching for a key that is incomparable with the keys in the tree, the search operation will not - * find any matching key-value pair. - * - * @param K The type of keys. - * @param V The type of values. - * @param N The type of vertices implementing the [InterfaceBSTVertex] interface. - * @property comparator The comparator used to order the keys. If null, keys are expected to be comparable. - * @property size The number of elements in the tree. - * @property root The root vertex of the tree. + * @param K key type + * @param V value type + * @param N vertex type implementing the [InterfaceBSTVertex] interface + * @property comparator `Comparator?` type; used optionally to compare keys in a tree. If `null`, it is expected that keys of comparable type. + * @property size `Long` type; number of key-value pairs in this tree + * @property root `N?` type, `null` by default */ abstract class AbstractBinarySearchTree> { - /** Comparator used for comparing keys. */ protected var comparator: Comparator? = null - - /** The number of elements in the tree. */ protected var size: Long = 0L - - /** The root vertex of the tree. */ protected var root: N? = null /** - * Returns an iterator over the elements in this tree in proper sequence. - * @return an iterator over the elements in this tree in proper sequence + * Returns an iterator over the elements of this tree in a certain sequence */ operator fun iterator(): Iterator> { return TreeIterator(root) } /** - * Returns the number of key-value pairs in this tree. - * @return the number of key-value pairs in this tree + * Returns the number of key-value pairs in this tree */ fun size(): Long { return size } /** - * Returns true if this tree contains no key-value pairs. - * @return true if this tree contains no key-value pairs + * Returns `true` if this tree contains no key-value pairs, and `false` otherwise */ fun isEmpty(): Boolean { return size == 0L } /** - * Returns the value associated with the specified key in this tree. - * If the key is not found, returns null. - * @param key the key whose associated value is to be returned - * @return the value associated with the specified key, or null if the key is not found + * Returns `true` if this tree contains at least one key-value pair, and `false` otherwise + */ + fun isNotEmpty(): Boolean { + return size != 0L + } + + /** + * Returns the value associated with the specified key in this tree + * + * @param key `K` type + * @return If the key exists - corresponding value + * If the key does not exist - `null` */ fun get(key: K): V? { return getRec(key) } /** - * Returns a Pair containing the specified key-value mapping, if found. - * If the key is not found, returns null. - * @param key the key whose associated value is to be returned - * @return a Pair containing the specified key-value mapping, or null if the key is not found + * Returns a pair containing the specified key-value mapping + * + * @param key `K` type + * @return If the key exists - pair. If the key does not exist - `null`. */ fun getPair(key: K): Pair? { val value = get(key) @@ -81,8 +74,9 @@ abstract class AbstractBinarySearchTree> { } /** - * Returns the minimum value in the tree, or null if the tree is empty. - * @return the minimum value in the tree, or null if the tree is empty + * Returns the minimum key in the tree + * + * @return If the tree is not empty - minimum key, and `null` otherwise */ fun getMin(): V? { val minKeyNode = getMinKeyNodeRec() @@ -90,8 +84,9 @@ abstract class AbstractBinarySearchTree> { } /** - * Returns the maximum value in the tree, or null if the tree is empty. - * @return the maximum value in the tree, or null if the tree is empty + * Returns the maximum key in the tree + * + * @return If the tree is not empty - maximum key, and `null` otherwise */ fun getMax(): V? { val maxKeyNode = getMaxKeyNodeRec() @@ -99,8 +94,9 @@ abstract class AbstractBinarySearchTree> { } /** - * Returns a Pair containing the minimum key-value mapping in the tree, or null if the tree is empty. - * @return a Pair containing the minimum key-value mapping in the tree, or null if the tree is empty + * Returns key-value pair with the minimum key in the tree + * + * @return If the tree is not empty - pair with minimum key, and `null` otherwise */ fun getMinKeyPair(): Pair? { val minKeyNode = getMinKeyNodeRec() @@ -108,8 +104,9 @@ abstract class AbstractBinarySearchTree> { } /** - * Returns a Pair containing the maximum key-value mapping in the tree, or null if the tree is empty. - * @return a Pair containing the maximum key-value mapping in the tree, or null if the tree is empty + * Returns key-value pair with the maximum key in the tree + * + * @return If the tree is not empty - pair with maximum key, and `null` otherwise */ fun getMaxKeyPair(): Pair? { val maxKeyNode = getMaxKeyNodeRec() @@ -117,11 +114,13 @@ abstract class AbstractBinarySearchTree> { } /** - * Associates the specified value with the specified key in this tree. - * If parameter replaceIfExists is true and the key already exists, the value is replaced; otherwise, the value is ignored. - * @param key the key with which the specified value is to be associated - * @param value the value to be associated with the specified key - * @param replaceIfExists if true, replaces the value if the key already exists, otherwise ignores it + * Puts a new vertex of a certain type into the tree with a given key and value + * + * @param key `K` type + * @param value `V` type, associated with this key + * @param replaceIfExists `Boolean` type, + * + * If `true` - replaces the value if the key already exists. If `false` - ignores it. */ abstract fun put( key: K, @@ -130,10 +129,13 @@ abstract class AbstractBinarySearchTree> { ) /** - * Put all pairs from the specified map to this tree. - * If parameter replaceIfExists is true and a key already exists, the value is replaced; otherwise, the value is ignored. - * @param map the map whose mappings are to be added to this tree - * @param replaceIfExists if true, replaces the value if the key already exists, otherwise ignores it + * Puts all key-value pairs from the specified map to this tree + * + * @param map `Map` type + * @param replaceIfExists `Boolean` type. + * If `true` - replaces the value if the key already exists. If `false` - ignores it. + * Supplied only if a [comparator] is present. If [comparator] is `null`, the value is replaced + * by the last value from the key-value pair in the map, where the key is the one already existing in the tree. */ fun putAll( map: Map, @@ -143,16 +145,18 @@ abstract class AbstractBinarySearchTree> { } /** - * Removes the mapping for a key from this tree if it is present. - * @param key the key whose mapping is to be removed from the tree - * @return the previous value associated with key, or null if there was no mapping for key + * Deletes a vertex by the entered key and returns the value stored in it + * + * @param key `K` type + * @return If a vertex with this key exists in the tree - the value stored in this vertex, otherwise `null` */ abstract fun remove(key: K): V? /** - * Removes the mapping for a key from this tree if it is present, and returns it as a Pair. - * @param key the key whose mapping is to be removed from the tree - * @return a Pair containing the removed key-value mapping, or null if the key was not found + * Deletes a vertex by the entered key and returns it as a key-value pair + * + * @param key `K` type + * @return If a vertex with such a key exists in the tree - the key-value pair corresponding to this vertex, otherwise `null` */ fun removeAndReturnPair(key: K): Pair? { val value = remove(key) @@ -160,10 +164,11 @@ abstract class AbstractBinarySearchTree> { } /** - * Recursively searches for the value associated with the specified key. - * @param key the key to search for - * @param vertex the current vertex being examined - * @return the value associated with the specified key, or null if not found + * Recursively searches for the value associated with the entered key + * + * @param key `K` type + * @param vertex `N?` type, `root` by default; current vertex being examined + * @return If a vertex with this key exists in the tree - the value stored in this vertex, otherwise `null` */ private fun getRec( key: K, @@ -178,9 +183,10 @@ abstract class AbstractBinarySearchTree> { } /** - * Recursively finds the vertex with the minimum key in the tree. - * @param vertex the current vertex being examined - * @return the vertex with the minimum key in the tree, or null if the tree is empty + * Recursively searches for the value associated with the minimum key in the tree + * + * @param vertex `N?` type, `root` by default; current vertex being examined + * @return If the tree is not empty - the vertex with the minimum key in the tree, otherwise `null` */ protected fun getMinKeyNodeRec(vertex: N? = root): N? { if (vertex == null) { @@ -195,9 +201,10 @@ abstract class AbstractBinarySearchTree> { } /** - * Recursively finds the vertex with the maximum key in the tree. - * @param vertex the current vertex being examined - * @return the vertex with the maximum key in the tree, or null if the tree is empty + * Recursively searches for the value associated with the maximum key in the tree + * + * @param vertex `N?` type, `root` by default; current vertex being examined + * @return If the tree is not empty - the vertex with the maximum key in the tree, otherwise `null` */ protected fun getMaxKeyNodeRec(vertex: N? = root): N? { if (vertex == null) { @@ -212,10 +219,17 @@ abstract class AbstractBinarySearchTree> { } /** - * Compares two keys. - * @param firstKey the first key to compare - * @param secondKey the second key to compare - * @return -1 if the first key is less than the second key, 0 if they are equal, or 1 if the first key is greater than the second key + * Compares two keys + * + * Comparing with a comparator if it is not `null`, or without one if the comparator is null and + * the keys are of comparable type + * + * @param firstKey `K` type + * @param secondKey `K` type + * @return + * -1 if the first key is less than the second key; + * 0 if they are equal; + * 1 if the first key is greater than the second key. */ protected fun compareKeys( firstKey: K, @@ -229,7 +243,9 @@ abstract class AbstractBinarySearchTree> { else -> 1 } } else { - val comparableKey = firstKey as Comparable + val comparableKey = + firstKey as? Comparable + ?: throw Exception("Key's type is incomparable and comparator wasn't given") when (comparableKey.compareTo(secondKey)) { in Int.MIN_VALUE..-1 -> -1 0 -> 0 @@ -239,18 +255,24 @@ abstract class AbstractBinarySearchTree> { } /** - * Constructs a new binary search tree with the specified comparator. - * @param comparator the comparator to use for comparing keys, or null to use natural ordering + * Constructs a new binary search tree with the specified comparator + * + * @param comparator `Comparator?` type, `null `by default; used optionally to compare keys in a tree. If `null`, it is expected that keys of comparable type. */ constructor(comparator: Comparator? = null) { this.comparator = comparator } /** - * Constructs a new binary search tree and initializes it with the mappings from the specified map. - * @param map the map whose mappings are to be added to this tree - * @param replaceIfExists if true, replaces the value if the key already exists, otherwise ignores it - * @param comparator the comparator to use for comparing keys, or null to use natural ordering + * Constructs a new binary search tree and puts all key-value pairs from the specified map to this tree + * + * @param map `Map` type + * @param replaceIfExists `Boolean` type. + * If `true` - replaces the value if the key already exists. If `false` - ignores it. + * Supplied only if a [comparator] is present. If comparator is `null`, the value is replaced + * by the last value from the key-value pair in the map, where the key is the one already existing in the tree. + * + * @param comparator `Comparator?` type, `null `by default; used optionally to compare keys in a tree. If `null`, it is expected that keys of comparable type. */ constructor(map: Map, replaceIfExists: Boolean = true, comparator: Comparator? = null) { this.comparator = comparator diff --git a/lib/src/main/kotlin/trees/RBSearchTree.kt b/lib/src/main/kotlin/trees/RBSearchTree.kt index dfaaa7e..96e16d1 100644 --- a/lib/src/main/kotlin/trees/RBSearchTree.kt +++ b/lib/src/main/kotlin/trees/RBSearchTree.kt @@ -1,57 +1,56 @@ -package main.trees +package trees -import main.vertexes.RBVertex +import vertexes.RBVertex /** - * Red-Black Tree implementation. It extends AbstractBinarySearchTree and uses RBVertex as vertices. + * Red-Black Tree implementation. + * + * It extends [AbstractBinarySearchTree] and uses [RBVertex] as vertices. * Red-Black Tree is a balanced binary search tree, where each vertex is colored either red or black. * This implementation ensures the following properties: * * - Every vertex is either red or black. * - The root is black. - * - Every leaf (NIL) is black. + * - Every leaf is black. * - If a vertex is red, then both its children are black. - * - Every simple path from a vertex to a descendant leaf (NIL) has the same number of black vertexes. - * - * When attempting to perform insertion, removal, or search operations on a non-empty binary search tree with a key that - * is incomparable with the keys in the tree, the behavior is as follows: - * - * **Put**: If an attempt is made to put a key-value pair with a key that is incomparable with the existing - * keys in the tree, the insertion operation will fail and the tree will remain unchanged. + * - Every simple path from a vertex to a descendant leaf has the same number of black vertexes. * - * **Remove**: If an attempt is made to remove a key-value pair with a key that is incomparable with the existing keys - * in the tree, the removal operation will fail and the tree will remain unchanged. + * If the tree has an incomparable key type and comparator is `null`, if the tree + * is non-empty, when trying to call the search, insert and delete methods, the tree + * will remain unchanged, the operation throws an exception with the message "Key's + * type is incomparable and comparator was not given". * - * **Get**: When getting for a key that is incomparable with the keys in the tree, the search operation will not - * find any matching key-value pair the get operation will fail. - * - * @param K the type of keys in the tree - * @param V the type of values associated with the keys - * @property comparator The comparator used to order the keys. If null, keys are expected to be comparable. - * @property size The number of elements in the tree. - * @property root The root vertex of the tree. + * @param K key type + * @param V value type + * @property comparator `Comparator?` type; used optionally to compare keys in a tree. If `null`, it is expected that keys of comparable type. + * @property size `Long` type; number of key-value pairs in this tree + * @property root `RBVertex?` type, `null` by default */ class RBSearchTree : AbstractBinarySearchTree> { + private val red = RBVertex.Color.RED + private val black = RBVertex.Color.BLACK + /** * This method removes the vertex with the given key from the tree and returns its associated value, * maintaining the properties of the red-black tree. * * 4 cases we need to look at: * - * 1) remove red vertex with 0 children -> just remove vetrex + * 1) remove red vertex with 0 children -> just remove vertex * * 2) remove red or black vertex with 2 children -> * find min vertex on the right subtree and swap it's key and value with * key and value of vertex that we need to remove. * Now we can work with vertex which has 1 or 0 children * - * 3) remove black vetrex with 1 child -> child can be only red + * 3) remove black vertex with 1 child -> child can be only red, * so we just swap child's key and value with key and value that we need to remove * and look at case 1) * * 4) remove black vertex with 0 children -> just remove vertex - * @param key the key of the vertex to be removed - * @return the value associated with the removed vertex, or null if the key is not found + * + * @param key `K` type + * @return value associated with the removed vertex, or `null` if the key is not found */ override fun remove(key: K): V? { val vertex: RBVertex = getVertex(key) ?: return null @@ -69,13 +68,14 @@ class RBSearchTree : AbstractBinarySearchTree> { /** * Determines whether balancing is required after removing a vertex from the Red-Black Search Tree. - * @param vertex The vertex to be checked for balancing. + * + * @param vertex `RBVertex` type; The vertex to be checked for balancing. * @return true if further balancing is required, false otherwise. */ private fun needToBalance(vertex: RBVertex): Boolean { when (countChildren(vertex)) { 0 -> { - if (vertex.isRed) { + if (vertex.color == red) { replaceVertexBy(vertex, null) return false } @@ -107,6 +107,7 @@ class RBSearchTree : AbstractBinarySearchTree> { /** * We need to balance tree after removal black vertex with 0 children. + * * In this fun we need to look at vertex's parent and brother: * 1) brother is black and brother's rightSon is red -> we paint * brother in parent's color, parent and brother's rightSon in black @@ -123,89 +124,81 @@ class RBSearchTree : AbstractBinarySearchTree> { * * 4) brother is red -> make brother black, parent red and * rotate left. We move conflict on level below, then we look at the previous cases - * @param vertex The child vertex of the removed vertex or null if the removed vertex had no children. + * + * @param vertex `RBVertex` type; The child vertex of the removed vertex or `null` if the removed vertex had no children. */ private fun balanceAfterRemove(vertex: RBVertex?) { var currentVertex = vertex - while (currentVertex != root && (currentVertex?.isRed == false || currentVertex == null)) { - var brother: RBVertex? - if (currentVertex == currentVertex?.parent?.leftSon) { - brother = currentVertex?.parent?.rightSon - - if (brother?.isRed == true) { - brother.isRed = false - currentVertex?.parent?.isRed = true - val vertexForRotate = currentVertex?.parent - vertexForRotate?.let { rotateLeft(vertexForRotate) } - brother = currentVertex?.parent?.rightSon - } - - if ((brother?.leftSon?.isRed == false || brother?.leftSon == null) && - (brother?.rightSon?.isRed == false || brother?.rightSon == null) - ) { - brother?.isRed = true - currentVertex = currentVertex?.parent - if (vertex == currentVertex?.leftSon) currentVertex?.leftSon = null - } else { - if (brother.rightSon?.isRed == false || brother.rightSon == null) { - brother.leftSon?.isRed = false - brother.isRed = true - rotateRight(brother) + while (currentVertex != root && (currentVertex?.color == black || currentVertex == null)) { + val isBrotherRightSon = (currentVertex == currentVertex?.parent?.leftSon) + var brother: RBVertex? = if (isBrotherRightSon) currentVertex?.parent?.rightSon else currentVertex?.parent?.leftSon + + if (brother?.color == red) { + brother.color = black + currentVertex?.parent?.color = red + val vertexForRotate = currentVertex?.parent + + when (isBrotherRightSon) { + true -> { + vertexForRotate?.let { rotateLeft(vertexForRotate) } brother = currentVertex?.parent?.rightSon + } else -> { + vertexForRotate?.let { rotateRight(vertexForRotate) } + brother = currentVertex?.parent?.leftSon } + } + } + + if ((brother?.leftSon?.color == black || brother?.leftSon == null) && + (brother?.rightSon?.color == black || brother?.rightSon == null) + ) { + brother?.color = red + currentVertex = currentVertex?.parent - val parentColor = currentVertex?.parent?.isRed - parentColor?.let { brother?.isRed = parentColor } - currentVertex?.parent?.isRed = false - brother?.rightSon?.isRed = false - val vertexForRotate = currentVertex?.parent - vertexForRotate?.let { rotateLeft(vertexForRotate) } - if (currentVertex == vertex) currentVertex?.parent?.leftSon = null - currentVertex = root + when (vertex) { + currentVertex?.leftSon -> currentVertex?.leftSon = null + currentVertex?.rightSon -> currentVertex?.rightSon = null } } else { - brother = currentVertex?.parent?.leftSon - - if (brother?.isRed == true) { - brother.isRed = false - currentVertex?.parent?.isRed = true - val vertexForRotate = currentVertex?.parent - vertexForRotate?.let { rotateRight(vertexForRotate) } + if ((isBrotherRightSon) && (brother.rightSon?.color == black || brother.rightSon == null)) { + brother.leftSon?.color = black + brother.color = red + rotateRight(brother) + brother = currentVertex?.parent?.rightSon + } else if ((!isBrotherRightSon) && (brother.leftSon?.color == black || brother.leftSon == null)) { + brother.rightSon?.color = black + brother.color = red + rotateLeft(brother) brother = currentVertex?.parent?.leftSon } - if ((brother?.leftSon?.isRed == false || brother?.leftSon == null) && - (brother?.rightSon?.isRed == false || brother?.rightSon == null) - ) { - brother?.isRed = true - currentVertex = currentVertex?.parent - if (vertex == currentVertex?.rightSon) currentVertex?.rightSon = null - } else { - if (brother.leftSon?.isRed == false || brother.leftSon == null) { - brother.rightSon?.isRed = false - brother.isRed = true - rotateLeft(brother) - brother = currentVertex?.parent?.leftSon + val parentColor = currentVertex?.parent?.color + parentColor?.let { brother?.color = parentColor } + currentVertex?.parent?.color = black + val vertexForRotate = currentVertex?.parent + + when (isBrotherRightSon) { + true -> { + brother?.rightSon?.color = black + vertexForRotate?.let { rotateLeft(vertexForRotate) } + if (currentVertex == vertex) currentVertex?.parent?.leftSon = null + } else -> { + brother?.leftSon?.color = black + vertexForRotate?.let { rotateRight(vertexForRotate) } + if (currentVertex == vertex) currentVertex?.parent?.rightSon = null } - - val parentColor = currentVertex?.parent?.isRed - parentColor?.let { brother?.isRed = parentColor } - currentVertex?.parent?.isRed = false - brother?.leftSon?.isRed = false - val vertexForRotate = currentVertex?.parent - vertexForRotate?.let { rotateRight(vertexForRotate) } - if (currentVertex == vertex) currentVertex?.parent?.rightSon = null - currentVertex = root } + currentVertex = root } } - currentVertex?.isRed = false + currentVertex?.color = black } /** - * Finds a vertex by corresponding key. If such vertex doesn't exist returns null. - * @param key The key to search for. - * @return The vertex with the corresponding key, or null if such vertex doesn't exist. + * Finds a vertex by corresponding key. If such vertex doesn't exist returns `null` + * + * @param key 'K` type + * @return vertex with the corresponding key, or `null` if such vertex doesn't exist */ private fun getVertex(key: K): RBVertex? { var currentVertex: RBVertex? = root @@ -227,10 +220,10 @@ class RBSearchTree : AbstractBinarySearchTree> { /** * Finds free place and inserts newVertex, colors it in red. - * If parameter replaceIfExists is true and the key already exists, the value is replaced; otherwise, the value is ignored. - * @param key the key with which the specified value is to be associated - * @param value the value to be associated with the specified key - * @param replaceIfExists if true, replaces the value if the key already exists, otherwise ignores it + * + * @param key 'K` type + * @param value `V` type + * @param replaceIfExists `Boolean` type; If `true` - replaces the value if the key already exists. If `false` - ignores it. */ override fun put( key: K, @@ -265,7 +258,7 @@ class RBSearchTree : AbstractBinarySearchTree> { } if (currentVertex == null) { - currentVertex = RBVertex(key, value, null, null, true, parent) + currentVertex = RBVertex(key, value, null, null, red, parent) if (root == null) { root = currentVertex } else if (isLeft) { @@ -280,6 +273,7 @@ class RBSearchTree : AbstractBinarySearchTree> { /** * Balances the tree after inserting a new vertex. + * * We need to balance tree in two cases: * 1) when newVertex is root, so our root is red * 2) when parent of our newVertex is red(because newVertex is also red) @@ -290,60 +284,44 @@ class RBSearchTree : AbstractBinarySearchTree> { * launch algorithm to grandfather because now it's color changed to red * if uncle is black we also make newVertex's parent black, grandparent red * and rotate it right - * @param vertex The newly inserted vertex. + * + * @param vertex `RBVertex` type; The newly inserted vertex. */ private fun balanceAfterPut(vertex: RBVertex) { var currentVertex = vertex - while (currentVertex.parent?.isRed == true) { + while (currentVertex.parent?.color == red) { val grandparent = currentVertex.parent?.parent - - if (currentVertex.parent == grandparent?.leftSon) { - val uncle = grandparent?.rightSon - - if (uncle?.isRed == true) { - currentVertex.parent?.isRed = false - uncle.isRed = false - grandparent.isRed = true - currentVertex = grandparent - } else { - if (currentVertex == currentVertex.parent?.rightSon) { - currentVertex = currentVertex.parent ?: currentVertex - rotateLeft(currentVertex) - } - - currentVertex.parent?.isRed = false - currentVertex.parent?.parent?.isRed = true - val vertexForRightRotate = currentVertex.parent?.parent - vertexForRightRotate?.let { rotateRight(vertexForRightRotate) } - } + val isUncleRightSon = (currentVertex.parent == grandparent?.leftSon) + val uncle = if (isUncleRightSon) grandparent?.rightSon else grandparent?.leftSon + + if (uncle?.color == red) { + currentVertex.parent?.color = black + uncle.color = black + grandparent?.color = red + currentVertex = grandparent ?: currentVertex } else { - val uncle = grandparent?.leftSon - - if (uncle?.isRed == true) { - currentVertex.parent?.isRed = false - uncle.isRed = false - grandparent.isRed = true - currentVertex = grandparent - } else { - if (currentVertex == currentVertex.parent?.leftSon) { - currentVertex = currentVertex.parent ?: currentVertex - rotateRight(currentVertex) - } - - currentVertex.parent?.isRed = false - currentVertex.parent?.parent?.isRed = true - val vertexForLeftRotate = currentVertex.parent?.parent - vertexForLeftRotate?.let { rotateLeft(vertexForLeftRotate) } + if ((isUncleRightSon) && (currentVertex == currentVertex.parent?.rightSon)) { + currentVertex = currentVertex.parent ?: currentVertex + rotateLeft(currentVertex) + } else if ((!isUncleRightSon) && (currentVertex == currentVertex.parent?.leftSon)) { + currentVertex = currentVertex.parent ?: currentVertex + rotateRight(currentVertex) } + + currentVertex.parent?.color = black + currentVertex.parent?.parent?.color = red + val vertexForRotate = currentVertex.parent?.parent + vertexForRotate?.let { if (isUncleRightSon) rotateRight(vertexForRotate) else rotateLeft(vertexForRotate) } } } - root?.isRed = false + root?.color = black } /** - * Counts the number of children of the given vertex. - * @param vertex The vertex whose children count is to be determined. + * Counts the number of children of the given vertex + * + * @param vertex `RBVertex` type; The vertex whose children count is to be determined. * @return The number of children of the given vertex. */ private fun countChildren(vertex: RBVertex): Int { @@ -354,16 +332,18 @@ class RBSearchTree : AbstractBinarySearchTree> { } /** - * Retrieves the child vertex of the given vertex. - * @param vertex The vertex whose child is to be retrieved. + * Retrieves the child vertex of the given vertex + * + * @param vertex `RBVertex` type; vertex The vertex whose child is to be retrieved. * @return The child vertex of the given vertex. */ private fun getChild(vertex: RBVertex) = if (vertex.leftSon != null) vertex.leftSon else vertex.rightSon /** - * Replaces the old vertex with the new vertex in the tree structure. - * @param oldVertex The old vertex to be replaced. - * @param newVertex The new vertex that replaces the old vertex. + * Replaces the old vertex with the new vertex in the tree structure + * + * @param oldVertex `RBVertex` type; The old vertex to be replaced. + * @param newVertex `RBVertex` type; The new vertex that replaces the old vertex. */ private fun replaceVertexBy( oldVertex: RBVertex, @@ -381,8 +361,10 @@ class RBSearchTree : AbstractBinarySearchTree> { /** * Performs a left rotation on the given vertex. + * * Suppose that vertex has a rightSon. Swap parent and rightSon, rightSon's leftSon becomes parent's rightSon. - * @param vertex The vertex on which the left rotation is to be performed. + * + * @param vertex `RBVertex` type; The vertex on which the left rotation is to be performed. */ private fun rotateLeft(vertex: RBVertex) { val rightVertex: RBVertex? = vertex.rightSon @@ -400,8 +382,9 @@ class RBSearchTree : AbstractBinarySearchTree> { /** * Performs a right rotation on the given vertex. + * * Suppose that vertex has a leftSon. Swap parent and leftSon, leftSon's rightSon becomes parent's leftSon. - * @param vertex The vertex on which the right rotation is to be performed. + * @param vertex `RBVertex` type; The vertex on which the right rotation is to be performed. */ private fun rotateRight(vertex: RBVertex) { val leftVertex: RBVertex? = vertex.leftSon @@ -418,20 +401,26 @@ class RBSearchTree : AbstractBinarySearchTree> { } /** - * Constructs a new binary search tree with the specified comparator. - * @param comparator the comparator to use for comparing keys, or null to use natural ordering + * Constructs a new binary search tree with the specified comparator + * + * @param comparator `Comparator?` type, `null `by default; used optionally to compare keys in a tree. If `null`, it is expected that keys of comparable type. */ - constructor(comparator: Comparator? = null) : super(comparator) + constructor(comparator: Comparator? = null) { + this.comparator = comparator + } /** - * Constructs a new binary search tree and initializes it with the mappings from the specified map. - * @param map the map whose mappings are to be added to this tree - * @param replaceIfExists if true, replaces the value if the key already exists, otherwise ignores it - * @param comparator the comparator to use for comparing keys, or null to use natural ordering + * Constructs a new binary search tree and puts all key-value pairs from the specified map to this tree + * + * @param map `Map` type + * @param replaceIfExists `Boolean` type. + * If `true` - replaces the value if the key already exists. If `false` - ignores it. + * Supplied only if a [comparator] is present. If comparator is `null`, the value is replaced + * by the last value from the key-value pair in the map, where the key is the one already existing in the tree. + * @param comparator `Comparator?` type, `null `by default; used optionally to compare keys in a tree. If `null`, it is expected that keys of comparable type. */ - constructor(map: Map, replaceIfExists: Boolean = true, comparator: Comparator? = null) : super( - map, - replaceIfExists, - comparator, - ) + constructor(map: Map, replaceIfExists: Boolean = true, comparator: Comparator? = null) { + this.comparator = comparator + putAll(map, replaceIfExists) + } } diff --git a/lib/src/main/kotlin/trees/SimpleBinarySearchTree.kt b/lib/src/main/kotlin/trees/SimpleBinarySearchTree.kt index 3d0e85a..b821a80 100644 --- a/lib/src/main/kotlin/trees/SimpleBinarySearchTree.kt +++ b/lib/src/main/kotlin/trees/SimpleBinarySearchTree.kt @@ -1,36 +1,32 @@ -package main.trees +package trees -import main.vertexes.SimpleBSTVertex +import vertexes.SimpleBSTVertex /** - * This class represents a simple implementation of a binary search tree. - * It extends AbstractBinarySearchTree and uses SimpleBSTVertex as vertices. + * Simple implementation of a binary search tree. * - * When attempting to perform insertion, removal, or search operations on a non-empty binary search tree with a key that - * is incomparable with the keys in the tree, the behavior is as follows: + * It extends [AbstractBinarySearchTree] and uses [SimpleBSTVertex] as vertices. * - * **Put**: If an attempt is made to put a key-value pair with a key that is incomparable with the existing - * keys in the tree, the insertion operation will fail and the tree will remain unchanged. + * If the tree has an incomparable key type and comparator is `null`, if the tree + * is non-empty, when trying to call the search, insert and delete methods, the tree + * will remain unchanged, the operation throws an exception with the message "Key's + * type is incomparable and comparator was not given". * - * **Remove**: If an attempt is made to remove a key-value pair with a key that is incomparable with the existing keys - * in the tree, the removal operation will fail and the tree will remain unchanged. - * - * **Get**: When getting for a key that is incomparable with the keys in the tree, the search operation will not - * find any matching key-value pair the get operation will fail. - * - * @param K The type of keys in the tree. - * @param V The type of values in the tree. - * @property comparator The comparator used to order the keys. If null, keys are expected to be comparable. - * @property size The number of elements in the tree. - * @property root The root vertex of the tree. + * @param K key type + * @param V value type + * @property comparator `Comparator?` type; used optionally to compare keys in a tree. If `null`, it is expected that keys of comparable type. + * @property size `Long` type; number of key-value pairs in this tree + * @property root `SimpleBSTVertex?` type, `null` by default */ open class SimpleBinarySearchTree : AbstractBinarySearchTree> { /** - * Associates the specified value with the specified key in this tree. - * If parameter replaceIfExists is true and the key already exists, the value is replaced; otherwise, the value is ignored. - * @param key the key with which the specified value is to be associated - * @param value the value to be associated with the specified key - * @param replaceIfExists if true, replaces the value if the key already exists, otherwise ignores it + * Puts a new vertex of a certain type into the tree with a given key and value + * + * @param key `K` type + * @param value `V` type + * @param replaceIfExists `Boolean` type, + * + * If `true` - replaces the value if the key already exists. If `false` - ignores it. */ override fun put( key: K, @@ -42,10 +38,12 @@ open class SimpleBinarySearchTree : AbstractBinarySearchTree?` type, `root` by default; The current vertex in the recursion. */ private fun putRec( key: K, @@ -82,7 +80,8 @@ open class SimpleBinarySearchTree : AbstractBinarySearchTree : AbstractBinarySearchTree?` type, `root` by default; The current vertex being examined in the recursion. * @return A pair containing the updated vertex and the value associated with the removed key, or null if the key is not found. */ private fun removeRec( @@ -144,16 +145,21 @@ open class SimpleBinarySearchTree : AbstractBinarySearchTree?` type, `null `by default; used optionally to compare keys in a tree. If `null`, it is expected that keys of comparable type. */ constructor(comparator: Comparator? = null) : super(comparator) /** - * Constructs a new binary search tree and initializes it with the mappings from the specified map. - * @param map the map whose mappings are to be added to this tree - * @param replaceIfExists if true, replaces the value if the key already exists, otherwise ignores it - * @param comparator the comparator to use for comparing keys, or null to use natural ordering + * Constructs a new binary search tree and puts all key-value pairs from the specified map to this tree + * + * @param map `Map` type + * @param replaceIfExists `Boolean` type. + * If `true` - replaces the value if the key already exists. If `false` - ignores it. + * Supplied only if a [comparator] is present. If comparator is `null`, the value is replaced + * by the last value from the key-value pair in the map, where the key is the one already existing in the tree. + * @param comparator `Comparator?` type, `null `by default; used optionally to compare keys in a tree. If `null`, it is expected that keys of comparable type. */ constructor(map: Map, replaceIfExists: Boolean = true, comparator: Comparator? = null) : super( map, diff --git a/lib/src/main/kotlin/vertexes/AVLVertex.kt b/lib/src/main/kotlin/vertexes/AVLVertex.kt index 64f0a9a..05c298a 100644 --- a/lib/src/main/kotlin/vertexes/AVLVertex.kt +++ b/lib/src/main/kotlin/vertexes/AVLVertex.kt @@ -1,14 +1,15 @@ -package main.vertexes +package vertexes /** - * Represents a vertex in an AVL tree. - * @param K Type of keys. - * @param V Type of values. - * @property key The key associated with this vertex. - * @property value The value associated with this vertex. - * @property leftSon The left child vertex of this vertex, of type [AVLVertex]. - * @property rightSon The right child vertex of this vertex, of type [AVLVertex]. - * @property sonsHeightDiff The difference in height between the left and right subtrees. + * Represents a vertex in an AVL tree + * + * @param K key type + * @param V value type + * @property key + * @property value + * @property leftSon `AVLVertex?` type, + * @property rightSon `AVLVertex?` type + * @property sonsHeightDiff 'Int' type, difference in height between the left and right subtrees */ class AVLVertex( @@ -24,12 +25,13 @@ class AVLVertex( var sonsHeightDiff: Int = 0 /** - * Constructs a vertex with the specified key and value. - * @param key The key associated with this vertex. - * @param value The value associated with this vertex. - * @param leftSon The left child vertex of this vertex. - * @param rightSon The right child vertex of this vertex. - * @param sonsHeightDiff The difference in height between the left and right subtrees. + * Constructs vertex for AVL tree with the specified key and value + * + * @param key `K` type + * @param value `V` type + * @param leftSon `AVLVertex?` type + * @param rightSon `AVLVertex?` type + * @param sonsHeightDiff 'Int' type, 0 by default; difference in height between the left and right subtrees */ constructor( key: K, diff --git a/lib/src/main/kotlin/vertexes/InterfaceBSTVertex.kt b/lib/src/main/kotlin/vertexes/InterfaceBSTVertex.kt index 41b7e85..bce3946 100644 --- a/lib/src/main/kotlin/vertexes/InterfaceBSTVertex.kt +++ b/lib/src/main/kotlin/vertexes/InterfaceBSTVertex.kt @@ -1,14 +1,15 @@ -package main.vertexes +package vertexes /** - * Represents a generic vertex in a Binary Search Tree (BST). - * @param K Type of keys. - * @param V Type of values. - * @param N Type of the child vertices. - * @property key The key associated with this vertex. - * @property value The value associated with this vertex. - * @property leftSon The left child vertex of this vertex, of type N. - * @property rightSon The right child vertex of this vertex, of type N. + * Represents a generic vertex in a binary search tree + * + * @param K key type + * @param V value type + * @param N child vertices type + * @property key + * @property value + * @property leftSon `N?` type + * @property rightSon `N?` type */ interface InterfaceBSTVertex { var key: K diff --git a/lib/src/main/kotlin/vertexes/RBVertex.kt b/lib/src/main/kotlin/vertexes/RBVertex.kt index 4a4e06c..af5602e 100644 --- a/lib/src/main/kotlin/vertexes/RBVertex.kt +++ b/lib/src/main/kotlin/vertexes/RBVertex.kt @@ -1,4 +1,4 @@ -package main.vertexes +package vertexes /** * Represents a vertex in a Red-Black Tree. @@ -6,7 +6,7 @@ package main.vertexes * @param V Type of values. * @property key The key associated with this vertex. * @property value The value associated with this vertex. - * @property isRed A boolean indicating whether this vertex is red. + * @property color The color of this vertex (red or black). * @property parent The parent vertex of this vertex. * @property leftSon The left child vertex of this vertex. * @property rightSon The right child vertex of this vertex. @@ -15,7 +15,12 @@ class RBVertex( override var key: K, override var value: V, ) : InterfaceBSTVertex> { - var isRed = true + enum class Color { + RED, + BLACK, + } + + var color: Color = Color.RED var parent: RBVertex? = null override var leftSon: RBVertex? = null override var rightSon: RBVertex? = null @@ -26,7 +31,7 @@ class RBVertex( * @param value The value associated with this vertex. * @param leftSon The left child vertex of this vertex. * @param rightSon The right child vertex of this vertex. - * @param isRed A boolean indicating whether this vertex is red. + * @param color The color of this vertex (red or black). * @param parent The parent vertex of this vertex. */ constructor( @@ -34,12 +39,12 @@ class RBVertex( value: V, leftSon: RBVertex?, rightSon: RBVertex?, - isRed: Boolean, + color: Color, parent: RBVertex?, ) : this(key, value) { this.leftSon = leftSon this.rightSon = rightSon this.parent = parent - this.isRed = isRed + this.color = color } } diff --git a/lib/src/main/kotlin/vertexes/SimpleBSTVertex.kt b/lib/src/main/kotlin/vertexes/SimpleBSTVertex.kt index 59dc7b9..2107434 100644 --- a/lib/src/main/kotlin/vertexes/SimpleBSTVertex.kt +++ b/lib/src/main/kotlin/vertexes/SimpleBSTVertex.kt @@ -1,13 +1,14 @@ -package main.vertexes +package vertexes /** - * Represents a simple vertex in a Binary Search Tree. - * @param K Type of keys. - * @param V Type of values. - * @property key The key associated with this vertex. - * @property value The value associated with this vertex. - * @property leftSon The left child vertex of this vertex, of type SimpleBSTVertex. - * @property rightSon The right child vertex of this vertex, of type SimpleBSTVertex. + * Represents a simple vertex in a binary search tree + * + * @param K key type + * @param V value type + * @property key + * @property value + * @property leftSon `SimpleBSTVertex?` type, `null` by default + * @property rightSon `SimpleBSTVertex?` type, `null` by default */ class SimpleBSTVertex( override var key: K, @@ -17,11 +18,12 @@ class SimpleBSTVertex( override var rightSon: SimpleBSTVertex? = null /** - * Constructs a simple vertex with the specified key and value. - * @param key The key associated with this vertex. - * @param value The value associated with this vertex. - * @param leftSon The left child vertex of this vertex. - * @param rightSon The right child vertex of this vertex. + * Constructs a simple vertex with the specified key and value + * + * @param key `K` type + * @param value `V` type + * @param leftSon `SimpleBSTVertex?` type + * @param rightSon `SimpleBSTVertex?` type */ constructor( key: K, diff --git a/lib/src/test/kotlin/iterator/IteratorTests.kt b/lib/src/test/kotlin/iterator/IteratorTests.kt index fb46e01..508d05b 100644 --- a/lib/src/test/kotlin/iterator/IteratorTests.kt +++ b/lib/src/test/kotlin/iterator/IteratorTests.kt @@ -1,8 +1,8 @@ package iterator -import main.trees.AVLSearchTree -import main.vertexes.SimpleBSTVertex import org.junit.jupiter.api.Assertions.assertEquals +import trees.AVLSearchTree +import vertexes.SimpleBSTVertex import kotlin.test.Test class IteratorTests { diff --git a/lib/src/test/kotlin/iterator/TestIterator.kt b/lib/src/test/kotlin/iterator/TestIterator.kt index 9f9b9ac..d42d08d 100644 --- a/lib/src/test/kotlin/iterator/TestIterator.kt +++ b/lib/src/test/kotlin/iterator/TestIterator.kt @@ -1,11 +1,10 @@ package iterator -import main.iterator.TreeIterator -import main.vertexes.InterfaceBSTVertex -import java.util.LinkedList +import vertexes.InterfaceBSTVertex +import java.util.Stack internal class TestIterator>(vertex: N?) : TreeIterator(vertex) { - fun getTreeStack(): LinkedList { + fun getTreeStack(): Stack { return stack } } diff --git a/lib/src/test/kotlin/trees/abstractTree/AbstractTreeTest.kt b/lib/src/test/kotlin/trees/abstractTree/AbstractTreeTest.kt index 5aded42..02e80d2 100644 --- a/lib/src/test/kotlin/trees/abstractTree/AbstractTreeTest.kt +++ b/lib/src/test/kotlin/trees/abstractTree/AbstractTreeTest.kt @@ -1,11 +1,10 @@ package trees.abstractTree -import main.vertexes.SimpleBSTVertex import org.junit.jupiter.api.Assertions.assertFalse import org.junit.jupiter.api.Assertions.assertNotNull import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.Test -import java.util.Comparator +import vertexes.SimpleBSTVertex class AbstractTreeTest { private fun makeEmptyTree(): TestTree { @@ -18,6 +17,12 @@ class AbstractTreeTest { assert(tree.isEmpty()) } + @Test + fun `isNotEmpty() returns false if tree is empty `() { + val tree = makeEmptyTree() + assertFalse(tree.isNotEmpty()) + } + @Test fun `size() returns 0 if tree is empty`() { val tree = makeEmptyTree() @@ -66,6 +71,12 @@ class AbstractTreeTest { assertFalse(tree.isEmpty()) } + @Test + fun `isNotEmpty() returns true if tree is not empty `() { + val tree = makeTreeWithBothRootSSons() + assert(tree.isNotEmpty()) + } + @Test fun `size() returns not 0 if tree is not empty`() { val tree = makeTreeWithBothRootSSons() @@ -73,13 +84,13 @@ class AbstractTreeTest { } @Test - fun `get() returns null when tree doesn'n contains given key`() { + fun `get() returns null when tree doesn't contains given key`() { val tree = makeTreeWithBothRootSSons() assertNull(tree.get('z')) } @Test - fun `getPair() returns null when tree doesn'n contains given key`() { + fun `getPair() returns null when tree doesn't contains given key`() { val tree = makeTreeWithBothRootSSons() assertNull(tree.getPair('z')) } @@ -236,7 +247,7 @@ class AbstractTreeTest { } @Test - fun `compareKeys fall when keys type doesn't implement compareble && comparator wasn't given`() { + fun `compareKeys fall when keys type doesn't implement comparable && comparator wasn't given`() { var didItFall = false val tree = TestTree() try { diff --git a/lib/src/test/kotlin/trees/abstractTree/TestTree.kt b/lib/src/test/kotlin/trees/abstractTree/TestTree.kt index 74963f8..9974358 100644 --- a/lib/src/test/kotlin/trees/abstractTree/TestTree.kt +++ b/lib/src/test/kotlin/trees/abstractTree/TestTree.kt @@ -1,7 +1,7 @@ package trees.abstractTree -import main.trees.AbstractBinarySearchTree -import main.vertexes.SimpleBSTVertex +import trees.AbstractBinarySearchTree +import vertexes.SimpleBSTVertex class TestTree : AbstractBinarySearchTree> { var removeShouldReturns: V? = null @@ -26,6 +26,7 @@ class TestTree : AbstractBinarySearchTree> { ): Int { return super.compareKeys(firstKey, secondKey) } + constructor (root: SimpleBSTVertex, size: Long, comparator: Comparator? = null) : super(comparator) { this.root = root diff --git a/lib/src/test/kotlin/trees/avlTree/AVLTreeForTest.kt b/lib/src/test/kotlin/trees/avlTree/AVLTreeForTest.kt index c12b9be..7266073 100644 --- a/lib/src/test/kotlin/trees/avlTree/AVLTreeForTest.kt +++ b/lib/src/test/kotlin/trees/avlTree/AVLTreeForTest.kt @@ -1,9 +1,7 @@ package trees.avlTree -import main.trees.AVLSearchTree -import main.vertexes.AVLVertex -import kotlin.collections.mutableListOf -import kotlin.collections.mutableMapOf +import trees.AVLSearchTree +import vertexes.AVLVertex import kotlin.math.max class AVLTreeForTest : AVLSearchTree { diff --git a/lib/src/test/kotlin/trees/avlTree/AVLTreeTest.kt b/lib/src/test/kotlin/trees/avlTree/AVLTreeTest.kt deleted file mode 100644 index 38b1df9..0000000 --- a/lib/src/test/kotlin/trees/avlTree/AVLTreeTest.kt +++ /dev/null @@ -1,1494 +0,0 @@ -package trees.avlTree - -import main.vertexes.AVLVertex -import org.junit.jupiter.api.Test -import kotlin.collections.hashMapOf - -class AVLTreeTest { - private fun makeEmptyTree(): AVLTreeForTest { - return AVLTreeForTest() - } - - // putTest - - @Test - fun `entry became root after it was added to empty tree`() { - val tree = makeEmptyTree() - tree.put(0, '0') - val root = tree.getRootT() - assert((root?.key to root?.value) == (0 to '0')) - } - - @Test - fun `size equals 1 after entry was added to empty tree`() { - val tree = makeEmptyTree() - tree.put(0, '0') - assert(tree.size() == 1L) - } - - private fun makeSize1Tree(): AVLTreeForTest { - return AVLTreeForTest(AVLVertex('b', '+'), 1L) // init tree by root and size (don't use put) - } - - @Test - fun `entry with larger key became right son after it was added to size 1 tree`() { - val tree = makeSize1Tree() - tree.put('c', '+') - val root = tree.getRootT() - assert((root?.rightSon?.key to root?.rightSon?.value) == ('c' to '+')) - } - - @Test - fun `entry with lesser key became left son after it was added to size 1 tree`() { - val tree = makeSize1Tree() - tree.put('a', '-') - val root = tree.getRootT() - assert((root?.leftSon?.key to root?.leftSon?.value) == ('a' to '-')) - } - - @Test - fun `root's sonsHeightDiff decreased by 1 after entry with larger key was added to size 1 tree`() { - val tree = makeSize1Tree() - tree.put('c', '+') - val root = tree.getRootT() - assert(root?.sonsHeightDiff == -1) - } - - @Test - fun `root's sonsHeightDiff increased by 1 after entry with lesser key was added to size 1 tree`() { - val tree = makeSize1Tree() - tree.put('a', '-') - val root = tree.getRootT() - assert(root?.sonsHeightDiff == 1) - } - - @Test - fun `size equals 2 after entry with larger key was added to size 1 tree`() { - val tree = makeSize1Tree() - tree.put('c', '+') - assert(tree.size() == 2L) - } - - @Test - fun `size equals 2 after entry with lesser key was added to size 1 tree`() { - val tree = makeSize1Tree() - tree.put('a', '-') - assert(tree.size() == 2L) - } - - private fun makeTreeForNeedNotBalanceingPutTest(): AVLTreeForTest { - return AVLTreeForTest(AVLVertex(4, 'A', AVLVertex(1, 'I'), AVLVertex(5, 'S')), 3L) - } - - private fun isTreeConsistsOf( - expectedContent: Set>, - tree: AVLTreeForTest, - ): Boolean { - val vertexes = tree.getVertexesInDFSOrder() - val pairsFromVertexes = (Array(vertexes.size) { i -> (vertexes[i].key to vertexes[i].value) }).toSet() - return pairsFromVertexes == expectedContent - } - - @Test - fun `content is correct after entry was added (needn't balancing)`() { - val tree = makeTreeForNeedNotBalanceingPutTest() - tree.put(0, 'O') - assert(isTreeConsistsOf(setOf(0 to 'O', 1 to 'I', 5 to 'S', 4 to 'A'), tree)) - } - - @Test - fun `size increased by 1 after added to 'size 2+' tree (needn't balancing)`() { - val tree = makeTreeForNeedNotBalanceingPutTest() - tree.put(0, 'O') - assert(tree.size() == 4L) - } - - private fun isTreeSStructureThat( - tree: AVLTreeForTest, - order: Array, - deps: List>, - ): Boolean { - // Tiple consists of indexes in order of (1)vertex, one's (2)leftSon and (3)RightSon - val vertexes = tree.getVertexesInDFSOrder() - if (vertexes.size != order.size) return false - for (i in order.indices) - if (order[i] != vertexes[i].key) return false - for (dep in deps) { - if (dep.component2() != null) { - if (vertexes[dep.component1()].leftSon != vertexes[dep.component2() as Int]) { - return false - } - } - if (dep.component3() != null) { - if (vertexes[dep.component1()].rightSon != vertexes[dep.component3() as Int]) { - return false - } - } - } - return true - } - - @Test - fun `structure is correct after added to 'size 2+' tree (needn't balancing)`() { - val tree = makeTreeForNeedNotBalanceingPutTest() - tree.put(0, 'O') - val expectedDependences = listOf(Triple(0, 1, 3), Triple(1, 2, null)) - assert(isTreeSStructureThat(tree, arrayOf(4, 1, 0, 5), expectedDependences)) - } - - private fun isSonsHeightDiffCorrect(tree: AVLTreeForTest): Boolean { - val vertexes = tree.getVertexesInDFSOrder() - val heights = tree.getHeights() - if (vertexes.size != heights.size) return false - for (vertex in vertexes) { - val expectedSonsHeightDiff = - when ((vertex.leftSon == null) to (vertex.rightSon == null)) { - true to true -> 0 - true to false -> -1 - (heights[(vertex.rightSon as AVLVertex).key] ?: return false) - false to true -> 1 + (heights[(vertex.leftSon as AVLVertex).key] ?: return false) - else -> { - val heightOfLeftSubtree = heights[(vertex.leftSon as AVLVertex).key] ?: return false - val heightOfRightSubtree = heights[(vertex.rightSon as AVLVertex).key] ?: return false - heightOfLeftSubtree - heightOfRightSubtree - } - } - if (expectedSonsHeightDiff != vertex.sonsHeightDiff) return false - } - return true - } - - @Test - fun `vertexes' sonsHeightDiff are correct after entry was added to 'size 2+' tree (needn't balancing)`() { - val tree = makeTreeForNeedNotBalanceingPutTest() - tree.put(0, 'O') - assert(isSonsHeightDiffCorrect(tree)) - } - - private fun makeTreeForHaveToRotateLeftPutTest(): AVLTreeForTest { - val rightSonSRightSon = AVLVertex('h', 'H', AVLVertex('f', 'F'), AVLVertex('i', 'I')) - val rightSon = AVLVertex('e', 'E', AVLVertex('d', 'D'), rightSonSRightSon, -1) - val root = AVLVertex('c', 'C', AVLVertex('b', 'B', AVLVertex('a', 'A'), null, 1), rightSon, -1) - return AVLTreeForTest(root, 8L) - } - - @Test - fun `content is correct after entry was added (have to rotate left)`() { - val tree = makeTreeForHaveToRotateLeftPutTest() - tree.put('j', 'J') - val expectedContent = - setOf( - 'a' to 'A', - 'b' to 'B', - 'c' to 'C', - 'd' to 'D', - 'e' to 'E', - 'h' to 'H', - 'f' to 'F', - 'i' to 'I', - 'j' to 'J', - ) - assert(isTreeConsistsOf(expectedContent, tree)) - } - - @Test - fun `size increased by 1 after added (have to rotate left)`() { - val tree = makeTreeForHaveToRotateLeftPutTest() - tree.put('j', 'J') - assert(tree.size() == 9L) - } - - @Test - fun `structure is correct after added (have to rotate left)`() { - val tree = makeTreeForHaveToRotateLeftPutTest() - tree.put('j', 'J') - val expectedDependences = - listOf( - Triple(0, 1, 3), - Triple(1, 2, null), - Triple(3, 4, 7), - Triple(4, 5, 6), - Triple(7, null, 8), - ) - val expectedOrder = arrayOf('c', 'b', 'a', 'h', 'e', 'd', 'f', 'i', 'j') - assert(isTreeSStructureThat(tree, expectedOrder, expectedDependences)) - } - - @Test - fun `vertexes' sonsHeightDiff are correct after added (have to rotate left)`() { - val tree = makeTreeForHaveToRotateLeftPutTest() - tree.put('j', 'J') - assert(isSonsHeightDiffCorrect(tree)) - } - - private fun makeTreeForHaveToRotateRightPutTest(): AVLTreeForTest { - val leftSonSLeftSon = AVLVertex('c', 'C', AVLVertex('b', 'B'), AVLVertex('d', 'D')) - val leftSon = AVLVertex('f', 'F', leftSonSLeftSon, AVLVertex('e', 'E'), 1) - val root = AVLVertex('h', 'H', leftSon, AVLVertex('i', 'I', null, AVLVertex('j', 'J'), -1), 1) - return AVLTreeForTest(root, 8L) - } - - @Test - fun `content is correct after entry was added (have to rotate right)`() { - val tree = makeTreeForHaveToRotateRightPutTest() - tree.put('a', 'A') - val expectedContent = - setOf( - 'a' to 'A', - 'b' to 'B', - 'c' to 'C', - 'd' to 'D', - 'e' to 'E', - 'h' to 'H', - 'f' to 'F', - 'i' to 'I', - 'j' to 'J', - ) - assert(isTreeConsistsOf(expectedContent, tree)) - } - - @Test - fun `size increased by 1 after added (have to rotate right)`() { - val tree = makeTreeForHaveToRotateRightPutTest() - tree.put('a', 'A') - assert(tree.size() == 9L) - } - - @Test - fun `structure is correct after added (have to rotate right)`() { - val tree = makeTreeForHaveToRotateRightPutTest() - tree.put('a', 'A') - val expectedDependences = - listOf( - Triple(0, 1, 7), - Triple(1, 2, 4), - Triple(2, 3, null), - Triple(4, 5, 6), - Triple(7, null, 8), - ) - val expectedOrder = arrayOf('h', 'c', 'b', 'a', 'f', 'd', 'e', 'i', 'j') - assert(isTreeSStructureThat(tree, expectedOrder, expectedDependences)) - } - - @Test - fun `vertexes' sonsHeightDiff are correct after added (have to rotate right)`() { - val tree = makeTreeForHaveToRotateRightPutTest() - tree.put('a', 'A') - assert(isSonsHeightDiffCorrect(tree)) - } - - private fun makeTreeForHaveToChangeRootByRotateLeftPutTest(): AVLTreeForTest { - val rightSon = AVLVertex('h', 'H', AVLVertex('f', 'F'), AVLVertex('i', 'I')) - val root = AVLVertex('e', 'E', AVLVertex('d', 'D'), rightSon, -1) - return AVLTreeForTest(root, 5L) - } - - @Test - fun `content is correct after entry was added (rotateLeft changes root)`() { - val tree = makeTreeForHaveToChangeRootByRotateLeftPutTest() - tree.put('j', 'J') - val expectedContent = setOf('d' to 'D', 'e' to 'E', 'h' to 'H', 'f' to 'F', 'i' to 'I', 'j' to 'J') - assert(isTreeConsistsOf(expectedContent, tree)) - } - - @Test - fun `size increased by 1 after added (rotateLeft changes root)`() { - val tree = makeTreeForHaveToChangeRootByRotateLeftPutTest() - tree.put('j', 'J') - assert(tree.size() == 6L) - } - - @Test - fun `structure is correct after added (rotateLeft changes root)`() { - val tree = makeTreeForHaveToChangeRootByRotateLeftPutTest() - tree.put('j', 'J') - val expectedDependences = listOf(Triple(0, 1, 4), Triple(1, 2, 3), Triple(4, null, 5)) - val expectedOrder = arrayOf('h', 'e', 'd', 'f', 'i', 'j') - assert(isTreeSStructureThat(tree, expectedOrder, expectedDependences)) - } - - @Test - fun `vertexes' sonsHeightDiff are correct after added (rotateLeft changes root)`() { - val tree = makeTreeForHaveToChangeRootByRotateLeftPutTest() - tree.put('j', 'J') - assert(isSonsHeightDiffCorrect(tree)) - } - - private fun makeTreeForHaveToChangeRootByRotateRightPutTest(): AVLTreeForTest { - val leftSon = AVLVertex('c', 'C', AVLVertex('b', 'B'), AVLVertex('d', 'D')) - val root = AVLVertex('f', 'F', leftSon, AVLVertex('e', 'E'), 1) - return AVLTreeForTest(root, 5L) - } - - @Test - fun `content is correct after entry was added (rotateRight changes root)`() { - val tree = makeTreeForHaveToChangeRootByRotateRightPutTest() - tree.put('a', 'A') - val expectedContent = setOf('a' to 'A', 'b' to 'B', 'c' to 'C', 'd' to 'D', 'e' to 'E', 'f' to 'F') - assert(isTreeConsistsOf(expectedContent, tree)) - } - - @Test - fun `size increased by 1 after added (rotateRight changes root)`() { - val tree = makeTreeForHaveToChangeRootByRotateRightPutTest() - tree.put('a', 'A') - assert(tree.size() == 6L) - } - - @Test - fun `structure is correct after added (rotateRight changes root)`() { - val tree = makeTreeForHaveToChangeRootByRotateRightPutTest() - tree.put('a', 'A') - val expectedDependences = listOf(Triple(0, 1, 3), Triple(1, 2, null), Triple(3, 4, 5)) - val expectedOrder = arrayOf('c', 'b', 'a', 'f', 'd', 'e') - assert(isTreeSStructureThat(tree, expectedOrder, expectedDependences)) - } - - @Test - fun `vertexes' sonsHeightDiff are correct after added (rotateRight changes root)`() { - val tree = makeTreeForHaveToChangeRootByRotateRightPutTest() - tree.put('a', 'A') - assert(isSonsHeightDiffCorrect(tree)) - } - - private fun makeTreeForHaveToBigRotateLeftPutTest(): AVLTreeForTest { - val rightSonSRightSon = AVLVertex('i', 'I', AVLVertex('g', 'G'), AVLVertex('j', 'J')) - val rightSon = AVLVertex('e', 'E', AVLVertex('d', 'D'), rightSonSRightSon, -1) - val root = AVLVertex('c', 'C', AVLVertex('b', 'B', AVLVertex('a', 'A'), null, 1), rightSon, -1) - return AVLTreeForTest(root, 8L) - } - - // (1) - add grandson's right son, (2) add grandson's left son - @Test - fun `content is correct after entry was added (have to big rotate left)(1)`() { - val tree = makeTreeForHaveToBigRotateLeftPutTest() - tree.put('f', 'F') - val expectedContent = - setOf( - 'a' to 'A', - 'b' to 'B', - 'c' to 'C', - 'd' to 'D', - 'e' to 'E', - 'g' to 'G', - 'f' to 'F', - 'i' to 'I', - 'j' to 'J', - ) - assert(isTreeConsistsOf(expectedContent, tree)) - } - - @Test - fun `content is correct after entry was added (have to big rotate left)(2)`() { - val tree = makeTreeForHaveToBigRotateLeftPutTest() - tree.put('h', 'H') - val expectedContent = - setOf( - 'a' to 'A', - 'b' to 'B', - 'c' to 'C', - 'd' to 'D', - 'e' to 'E', - 'h' to 'H', - 'g' to 'G', - 'i' to 'I', - 'j' to 'J', - ) - assert(isTreeConsistsOf(expectedContent, tree)) - } - - @Test - fun `size increased by 1 after added (have to big rotate left)(1)`() { - val tree = makeTreeForHaveToBigRotateLeftPutTest() - tree.put('f', 'F') - assert(tree.size() == 9L) - } - - @Test - fun `size increased by 1 after added (have to big rotate left)(2)`() { - val tree = makeTreeForHaveToBigRotateLeftPutTest() - tree.put('h', 'H') - assert(tree.size() == 9L) - } - - @Test - fun `structure is correct after added (have to big rotate left)(1)`() { - val tree = makeTreeForHaveToBigRotateLeftPutTest() - tree.put('f', 'F') - val expectedDependences = - listOf( - Triple(0, 1, 3), - Triple(1, 2, null), - Triple(3, 4, 7), - Triple(4, 5, 6), - Triple(7, null, 8), - ) - val expectedOrder = arrayOf('c', 'b', 'a', 'g', 'e', 'd', 'f', 'i', 'j') - assert(isTreeSStructureThat(tree, expectedOrder, expectedDependences)) - } - - @Test - fun `structure is correct after added (have to big rotate left)(2)`() { - val tree = makeTreeForHaveToBigRotateLeftPutTest() - tree.put('h', 'H') - val expectedDependences = - listOf( - Triple(0, 1, 3), - Triple(1, 2, null), - Triple(3, 4, 6), - Triple(4, 5, null), - Triple(6, 7, 8), - ) - val expectedOrder = arrayOf('c', 'b', 'a', 'g', 'e', 'd', 'i', 'h', 'j') - assert(isTreeSStructureThat(tree, expectedOrder, expectedDependences)) - } - - @Test - fun `vertexes' sonsHeightDiff are correct after added (have to big rotate left)(1)`() { - val tree = makeTreeForHaveToBigRotateLeftPutTest() - tree.put('f', 'F') - assert(isSonsHeightDiffCorrect(tree)) - } - - @Test - fun `vertexes' sonsHeightDiff are correct after added (have to big rotate left)(2)`() { - val tree = makeTreeForHaveToBigRotateLeftPutTest() - tree.put('h', 'H') - assert(isSonsHeightDiffCorrect(tree)) - } - - private fun makeTreeForHaveToBigRotateRightPutTest(): AVLTreeForTest { - val leftSonSLeftSon = AVLVertex('b', 'B', AVLVertex('a', 'A'), AVLVertex('d', 'D')) - val leftSon = AVLVertex('f', 'F', leftSonSLeftSon, AVLVertex('g', 'G'), 1) - val root = AVLVertex('h', 'H', leftSon, AVLVertex('i', 'I', null, AVLVertex('j', 'J'), -1), 1) - return AVLTreeForTest(root, 8L) - } - - // (1) - add grandson's left son, (2) add grandson's right son - @Test - fun `content is correct after entry was added (have to big rotate right)(1)`() { - val tree = makeTreeForHaveToBigRotateRightPutTest() - tree.put('c', 'C') - val expectedContent = - setOf( - 'a' to 'A', - 'b' to 'B', - 'c' to 'C', - 'd' to 'D', - 'h' to 'H', - 'g' to 'G', - 'f' to 'F', - 'i' to 'I', - 'j' to 'J', - ) - assert(isTreeConsistsOf(expectedContent, tree)) - } - - @Test - fun `content is correct after entry was added (have to big rotate right)(2)`() { - val tree = makeTreeForHaveToBigRotateRightPutTest() - tree.put('e', 'E') - val expectedContent = - setOf( - 'a' to 'A', - 'b' to 'B', - 'f' to 'F', - 'd' to 'D', - 'e' to 'E', - 'h' to 'H', - 'g' to 'G', - 'i' to 'I', - 'j' to 'J', - ) - assert(isTreeConsistsOf(expectedContent, tree)) - } - - @Test - fun `size increased by 1 after added (have to big rotate right)(1)`() { - val tree = makeTreeForHaveToBigRotateRightPutTest() - tree.put('c', 'C') - assert(tree.size() == 9L) - } - - @Test - fun `size increased by 1 after added (have to big rotate right)(2)`() { - val tree = makeTreeForHaveToBigRotateRightPutTest() - tree.put('e', 'E') - assert(tree.size() == 9L) - } - - @Test - fun `structure is correct after added (have to big rotate right)(1)`() { - val tree = makeTreeForHaveToBigRotateRightPutTest() - tree.put('c', 'C') - val expectedDependences = - listOf( - Triple(0, 1, 7), - Triple(7, null, 8), - Triple(1, 2, 5), - Triple(5, null, 6), - Triple(2, 3, 4), - ) - val expectedOrder = arrayOf('h', 'd', 'b', 'a', 'c', 'f', 'g', 'i', 'j') - assert(isTreeSStructureThat(tree, expectedOrder, expectedDependences)) - } - - @Test - fun `structure is correct after added (have to big rotate right)(2)`() { - val tree = makeTreeForHaveToBigRotateRightPutTest() - tree.put('e', 'E') - val expectedDependences = - listOf( - Triple(0, 1, 7), - Triple(7, null, 8), - Triple(1, 2, 4), - Triple(2, 3, null), - Triple(4, 5, 6), - ) - val expectedOrder = arrayOf('h', 'd', 'b', 'a', 'f', 'e', 'g', 'i', 'j') - assert(isTreeSStructureThat(tree, expectedOrder, expectedDependences)) - } - - @Test - fun `vertexes' sonsHeightDiff are correct after added (have to big rotate right)(1)`() { - val tree = makeTreeForHaveToBigRotateRightPutTest() - tree.put('c', 'C') - assert(isSonsHeightDiffCorrect(tree)) - } - - @Test - fun `vertexes' sonsHeightDiff are correct after added (have to big rotate right)(2)`() { - val tree = makeTreeForHaveToBigRotateLeftPutTest() - tree.put('e', 'E') - assert(isSonsHeightDiffCorrect(tree)) - } - - @Test - fun `tree has no changes after entry with existed key and param replaceIfExists = false was added`() { - val tree = makeSize1Tree() - tree.put('b', '-', false) - assert(tree.size() == 1L) - assert(tree.getRootT()?.value == '+') - } - - @Test - fun `content is correct after init by map`() { - val tree = AVLTreeForTest(hashMapOf('a' to 'A', 'b' to 'B')) - val expectedContent = setOf('a' to 'A', 'b' to 'B') - assert(isTreeConsistsOf(expectedContent, tree)) - } - - // remove test - - @Test - fun `delete from emptyTree returns null`() { - val tree = makeEmptyTree() - assert(tree.remove(0) == null) - } - - @Test - fun `tree is empty after deleted root of 'size 1' tree `() { - val tree = makeSize1Tree() - tree.remove('b') - assert(tree.getVertexesInDFSOrder().isEmpty()) - } - - @Test - fun `size equals 0 after deleted root of 'size 1' tree`() { - val tree = makeSize1Tree() - tree.remove('b') - assert(tree.size() == 0L) - } - - @Test - fun `remove fun return null if entry's key isn't exists(1)`() { - val tree = makeSize1Tree() - assert(tree.remove('a') == null) - } - - @Test - fun `tree has no changes after tried to delete by non existed larger key`() { - val tree = makeSize1Tree() - tree.remove('c') - assert(tree.size() == 1L) - assert(tree.getRootT()?.value == '+') - } - - @Test - fun `tree has no changes after tried to delete by non existed lesser key`() { - val tree = makeSize1Tree() - tree.remove('a') - assert(tree.size() == 1L) - assert(tree.getRootT()?.value == '+') - } - - private fun makeTreeForRemoveLeafWithoutBalanceingTest(): AVLTreeForTest { - return AVLTreeForTest(AVLVertex('r', "r", AVLVertex('n', "n"), AVLVertex('z', "z")), 3L) - } - - @Test - fun `right leaf deleted after remove with one's key was called (needn't balanceing)`() { - val tree = makeTreeForRemoveLeafWithoutBalanceingTest() - tree.remove('z') - val root = tree.getRootT() - if (root != null) { - assert(root.rightSon == null) - } else { - assert(false) - } - } - - @Test - fun `left leaf deleted after remove with one's key was called (needn't balanceing)`() { - val tree = makeTreeForRemoveLeafWithoutBalanceingTest() - tree.remove('n') - val root = tree.getRootT() - if (root != null) { - assert(root.leftSon == null) - } else { - assert(false) - } - } - - @Test - fun `remove by right leaf's key return due value (needn't balanceing)`() { - val tree = makeTreeForRemoveLeafWithoutBalanceingTest() - assert(tree.remove('z') == "z") - } - - @Test - fun `remove by left leaf's key return due value (needn't balanceing)`() { - val tree = makeTreeForRemoveLeafWithoutBalanceingTest() - assert(tree.remove('n') == "n") - } - - @Test - fun `vertex's sonsHeightDiff increased by 1 after deleted one's right leaf (needn't balanceing)`() { - val tree = makeTreeForRemoveLeafWithoutBalanceingTest() - tree.remove('z') - val root = tree.getRootT() - assert(root?.sonsHeightDiff == 1) - } - - @Test - fun `vertex's sonsHeightDiff decreased by 1 after deleted one's left son (needn't balanceing)`() { - val tree = makeTreeForRemoveLeafWithoutBalanceingTest() - tree.remove('n') - val root = tree.getRootT() - assert(root?.sonsHeightDiff == -1) - } - - @Test - fun `size decreased by 1 after deleted right leaf (needn't balanceing)`() { - val tree = makeTreeForRemoveLeafWithoutBalanceingTest() - tree.remove('z') - assert(tree.size() == 2L) - } - - @Test - fun `size decreased by 1 after deleted left leaf (needn't balanceing)`() { - val tree = makeTreeForRemoveLeafWithoutBalanceingTest() - tree.remove('n') - assert(tree.size() == 2L) - } - - private fun makeTreeForRemoveLeftSonWithOnlyLeftSonTest(): AVLTreeForTest { - val leftSon = AVLVertex('q', 9, AVLVertex('o', 0), null, 1) - val root = AVLVertex('s', 5, leftSon, AVLVertex('z', 2), 1) - return AVLTreeForTest(root, 4L) - } - - @Test - fun `remove left son with only left son returns due value (needn't balanceing)`() { - val tree = makeTreeForRemoveLeftSonWithOnlyRightSonTest() - assert(tree.remove('q') == 9) - } - - @Test - fun `content is correct after removed left son with only left son (needn't balanceing)`() { - val tree = makeTreeForRemoveLeftSonWithOnlyLeftSonTest() - tree.remove('q') - assert(isTreeConsistsOf(setOf('o' to 0, 's' to 5, 'z' to 2), tree)) - } - - @Test - fun `size decreased by 1 after removed left son with only left son (needn't balanceing)`() { - val tree = makeTreeForRemoveLeftSonWithOnlyLeftSonTest() - tree.remove('q') - assert(tree.size() == 3L) - } - - @Test - fun `structure is correct after removed left son with only leftt son (needn't balanceing)`() { - val tree = makeTreeForRemoveLeftSonWithOnlyLeftSonTest() - tree.remove('q') - assert(isTreeSStructureThat(tree, arrayOf('s', 'o', 'z'), listOf(Triple(0, 1, 2)))) - } - - @Test - fun `vertexes' sonsHeightDiff are correct after removed LSon with only LSon (needn't balanceing)`() { - val tree = makeTreeForRemoveLeftSonWithOnlyLeftSonTest() - tree.remove('q') - assert(isSonsHeightDiffCorrect(tree)) - } - - private fun makeTreeForRemoveLeftSonWithOnlyRightSonTest(): AVLTreeForTest { - val leftSon = AVLVertex('q', 9, null, AVLVertex('r', 7), -1) - val root = AVLVertex('s', 5, leftSon, AVLVertex('z', 2), 1) - return AVLTreeForTest(root, 4L) - } - - @Test - fun `remove left son with only right son returns due value (needn't balanceing)`() { - val tree = makeTreeForRemoveLeftSonWithOnlyRightSonTest() - assert(tree.remove('q') == 9) - } - - @Test - fun `content is correct after removed left son with only right son (needn't balanceing)`() { - val tree = makeTreeForRemoveLeftSonWithOnlyRightSonTest() - tree.remove('q') - assert(isTreeConsistsOf(setOf('r' to 7, 's' to 5, 'z' to 2), tree)) - } - - @Test - fun `size decreased by 1 after removed left son with only right son (needn't balanceing)`() { - val tree = makeTreeForRemoveLeftSonWithOnlyRightSonTest() - tree.remove('q') - assert(tree.size() == 3L) - } - - @Test - fun `structure is correct after removed left son with only right son (needn't balanceing)`() { - val tree = makeTreeForRemoveLeftSonWithOnlyRightSonTest() - tree.remove('q') - assert(isTreeSStructureThat(tree, arrayOf('s', 'r', 'z'), listOf(Triple(0, 1, 2)))) - } - - @Test - fun `vertexes' sonsHeightDiff are correct after removed LSon with only RSon (needn't balanceing)`() { - val tree = makeTreeForRemoveLeftSonWithOnlyRightSonTest() - tree.remove('q') - assert(isSonsHeightDiffCorrect(tree)) - } - - private fun makeTreeForRemoveRightSonWithOnlyLeftSonTest(): AVLTreeForTest { - val rightSon = AVLVertex('q', 9, AVLVertex('o', 0), null, 1) - val root = AVLVertex('i', 1, AVLVertex('b', 6), rightSon, -1) - return AVLTreeForTest(root, 4L) - } - - @Test - fun `remove right son with only left son returns due value (needn't balanceing)`() { - val tree = makeTreeForRemoveRightSonWithOnlyLeftSonTest() - assert(tree.remove('q') == 9) - } - - @Test - fun `content is correct after removed right son with only left son (needn't balanceing)`() { - val tree = makeTreeForRemoveRightSonWithOnlyLeftSonTest() - tree.remove('q') - assert(isTreeConsistsOf(setOf('o' to 0, 'b' to 6, 'i' to 1), tree)) - } - - @Test - fun `size decreased by 1 after removed right son with only left son (needn't balanceing)`() { - val tree = makeTreeForRemoveRightSonWithOnlyLeftSonTest() - tree.remove('q') - assert(tree.size() == 3L) - } - - @Test - fun `structure is correct after removed right son with only left son (needn't balanceing)`() { - val tree = makeTreeForRemoveRightSonWithOnlyLeftSonTest() - tree.remove('q') - assert(isTreeSStructureThat(tree, arrayOf('i', 'b', 'o'), listOf(Triple(0, 1, 2)))) - } - - @Test - fun `vertexes' sonsHeightDiff are correct after removed RSon with only LSon (needn't balanceing)`() { - val tree = makeTreeForRemoveRightSonWithOnlyLeftSonTest() - tree.remove('q') - assert(isSonsHeightDiffCorrect(tree)) - } - - private fun makeTreeForRemoveRightSonWithOnlyRightSonTest(): AVLTreeForTest { - val rightSon = AVLVertex('q', 9, null, AVLVertex('r', 7), -1) - val root = AVLVertex('i', 1, AVLVertex('b', 6), rightSon, -1) - return AVLTreeForTest(root, 4L) - } - - @Test - fun `remove right son with only right son returns due value (needn't balanceing)`() { - val tree = makeTreeForRemoveRightSonWithOnlyRightSonTest() - assert(tree.remove('q') == 9) - } - - @Test - fun `content is correct after removed right son with only right son (needn't balanceing)`() { - val tree = makeTreeForRemoveRightSonWithOnlyRightSonTest() - tree.remove('q') - assert(isTreeConsistsOf(setOf('r' to 7, 'b' to 6, 'i' to 1), tree)) - } - - @Test - fun `size decreased by 1 after removed right son with only right son (needn't balanceing)`() { - val tree = makeTreeForRemoveRightSonWithOnlyRightSonTest() - tree.remove('q') - assert(tree.size() == 3L) - } - - @Test - fun `structure is correct after removed right son with only right son (needn't balanceing)`() { - val tree = makeTreeForRemoveRightSonWithOnlyRightSonTest() - tree.remove('q') - assert(isTreeSStructureThat(tree, arrayOf('i', 'b', 'r'), listOf(Triple(0, 1, 2)))) - } - - @Test - fun `vertexes' sonsHeightDiff are correct after removed RSon with only RSon (needn't balanceing)`() { - val tree = makeTreeForRemoveRightSonWithOnlyRightSonTest() - tree.remove('q') - assert(isSonsHeightDiffCorrect(tree)) - } - - private fun makeTreeForRemoveRootWithOnlyLeftSon(): AVLTreeForTest { - return AVLTreeForTest(AVLVertex("be", "es", (AVLVertex("and", "et")), null, 1), 2L) - } - - @Test - fun `remove root with only left son returns due value (needn't balanceing)`() { - val tree = makeTreeForRemoveRootWithOnlyLeftSon() - assert(tree.remove("be") == "es") - } - - @Test - fun `content is correct after removed root with only left son (needn't balanceing)`() { - val tree = makeTreeForRemoveRootWithOnlyLeftSon() - tree.remove("be") - assert(isTreeConsistsOf(setOf("and" to "et"), tree)) - } - - @Test - fun `vertexes' sonsHeightDiff are correct after removed root with only LSon (needn't balanceing)`() { - val tree = makeTreeForRemoveRootWithOnlyLeftSon() - tree.remove("and") - assert(isSonsHeightDiffCorrect(tree)) - } - - private fun makeTreeForRemoveRootWithOnlyRightSon(): AVLTreeForTest { - return AVLTreeForTest(AVLVertex("and", "et", null, (AVLVertex("be", "es")), -1), 2L) - } - - @Test - fun `remove root with only right son returns due value (needn't balanceing)`() { - val tree = makeTreeForRemoveRootWithOnlyRightSon() - assert(tree.remove("and") == "et") - } - - @Test - fun `content is correct after removed root with only right son (needn't balanceing)`() { - val tree = makeTreeForRemoveRootWithOnlyRightSon() - tree.remove("and") - assert(isTreeConsistsOf(setOf("be" to "es"), tree)) - } - - @Test - fun `vertexes' sonsHeightDiff are correct after removed root with only RSon (needn't balanceing)`() { - val tree = makeTreeForRemoveRootWithOnlyRightSon() - tree.remove("and") - assert(isSonsHeightDiffCorrect(tree)) - } - - private fun makeTreeForRemoveSonWithBothSons(): AVLTreeForTest { - val eVrt = AVLVertex('e', 'E', AVLVertex('c', 'C'), null, 1) - val bVrt = AVLVertex('b', 'B', AVLVertex('a', 'A'), eVrt, -1) - val leftSon = AVLVertex('f', 'F', bVrt, AVLVertex('i', 'I', null, AVLVertex('k', 'K'), -1), 1) - val qVrt = AVLVertex('q', 'Q', null, AVLVertex('s', 'S'), -1) - val wVrt = AVLVertex('w', 'W', null, AVLVertex('z', 'Z'), -1) - val root = AVLVertex('n', 'N', leftSon, AVLVertex('u', 'U', qVrt, wVrt, 0), 1) - return AVLTreeForTest(root, 13L) - } - - @Test - fun `remove left son with both sons returns due value (needn't balanceing)`() { - val tree = makeTreeForRemoveSonWithBothSons() - assert(tree.remove('f') == 'F') - } - - @Test - fun `content is correct after removed left son with both sons (needn't balanceing)`() { - val tree = makeTreeForRemoveSonWithBothSons() - tree.remove('f') - val expectedContent = - setOf( - 'a' to 'A', - 'b' to 'B', - 'c' to 'C', - 'e' to 'E', - 'i' to 'I', - 'z' to 'Z', - 'k' to 'K', - 'n' to 'N', - 'u' to 'U', - 'q' to 'Q', - 's' to 'S', - 'w' to 'W', - ) - assert(isTreeConsistsOf(expectedContent, tree)) - } - - @Test - fun `size decreased by 1 after removed left son with both sons (needn't balanceing)`() { - val tree = makeTreeForRemoveSonWithBothSons() - tree.remove('f') - assert(tree.size() == 12L) - } - - @Test - fun `structure is correct after removed left son with both sons (needn't balanceing)`() { - val tree = makeTreeForRemoveSonWithBothSons() - tree.remove('f') - val expectedDependences = - listOf( - Triple(0, 1, 7), - Triple(1, 2, 5), - Triple(2, 3, 4), - Triple(5, null, 6), - Triple(7, 8, 10), - Triple(10, null, 11), - ) - val expectedOrder = arrayOf('n', 'e', 'b', 'a', 'c', 'i', 'k', 'u', 'q', 's', 'w', 'z') - assert(isTreeSStructureThat(tree, expectedOrder, expectedDependences)) - } - - @Test - fun `vertexes' sonsHeightDiff are correct after removed LSon with both sons (needn't balanceing)`() { - val tree = makeTreeForRemoveSonWithBothSons() - tree.remove('f') - assert(isSonsHeightDiffCorrect(tree)) - } - - @Test - fun `remove right son with both sons returns due value (needn't balanceing)`() { - val tree = makeTreeForRemoveSonWithBothSons() - assert(tree.remove('u') == 'U') - } - - @Test - fun `content is correct after removed right son with both sons (needn't balanceing)`() { - val tree = makeTreeForRemoveSonWithBothSons() - tree.remove('u') - val expectedContent = - setOf( - 'a' to 'A', - 'b' to 'B', - 'c' to 'C', - 'e' to 'E', - 'i' to 'I', - 'z' to 'Z', - 'k' to 'K', - 'n' to 'N', - 'f' to 'F', - 'q' to 'Q', - 's' to 'S', - 'w' to 'W', - ) - assert(isTreeConsistsOf(expectedContent, tree)) - } - - @Test - fun `size decreased by 1 after removed right son with both sons (needn't balanceing)`() { - val tree = makeTreeForRemoveSonWithBothSons() - tree.remove('u') - assert(tree.size() == 12L) - } - - @Test - fun `structure is correct after removed right son with both sons (needn't balanceing)`() { - val tree = makeTreeForRemoveSonWithBothSons() - tree.remove('u') - val expectedDependences = - listOf( - Triple(0, 1, 8), - Triple(1, 2, 6), - Triple(2, 3, 4), - Triple(6, null, 7), - Triple(4, 5, null), - Triple(8, 9, 10), - Triple(10, null, 11), - ) - val expectedOrder = arrayOf('n', 'f', 'b', 'a', 'e', 'c', 'i', 'k', 's', 'q', 'w', 'z') - assert(isTreeSStructureThat(tree, expectedOrder, expectedDependences)) - } - - @Test - fun `vertexes' sonsHeightDiff are correct after removed RSon with both sons (needn't balanceing)`() { - val tree = makeTreeForRemoveSonWithBothSons() - tree.remove('u') - assert(isSonsHeightDiffCorrect(tree)) - } - - @Test - fun `remove fun return null if entry's key isn't exists(2)`() { - val tree = makeTreeForRemoveSonWithBothSons() - assert(tree.remove('x') == null) - } - - private fun makeTreeForRemoveRootWithBothSonsTest(): AVLTreeForTest { - val leftSon = AVLVertex('b', 2, AVLVertex('a', 1), AVLVertex('e', 5), 0) - val rightSon = AVLVertex('i', 9, null, AVLVertex('k', 11), -1) - val root = AVLVertex('f', 6, leftSon, rightSon, 0) - return AVLTreeForTest(root, 6L) - } - - @Test - fun `remove root with both sons returns due value (needn't balanceing)`() { - val tree = makeTreeForRemoveRootWithBothSonsTest() - assert(tree.remove('f') == 6) - } - - @Test - fun `content is correct after removed root with both sons (needn't balanceing)`() { - val tree = makeTreeForRemoveRootWithBothSonsTest() - tree.remove('f') - val expectedContent = setOf('a' to 1, 'b' to 2, 'e' to 5, 'i' to 9, 'k' to 11) - assert(isTreeConsistsOf(expectedContent, tree)) - } - - @Test - fun `size decreased by 1 after removed root with both sons (needn't balanceing)`() { - val tree = makeTreeForRemoveRootWithBothSonsTest() - tree.remove('f') - assert(tree.size() == 5L) - } - - @Test - fun `structure is correct after removed root with both sons (needn't balanceing)`() { - val tree = makeTreeForRemoveRootWithBothSonsTest() - tree.remove('f') - val expectedDependences = listOf(Triple(0, 1, 3), Triple(1, 2, null), Triple(3, null, 4)) - val expectedOrder = arrayOf('e', 'b', 'a', 'i', 'k') - assert(isTreeSStructureThat(tree, expectedOrder, expectedDependences)) - } - - @Test - fun `vertexes' sonsHeightDiff are correct after removed root with both sons (needn't balanceing)`() { - val tree = makeTreeForRemoveRootWithBothSonsTest() - tree.remove('f') - assert(isSonsHeightDiffCorrect(tree)) - } - - private fun makeTreeForRemoveWithLeftRotate1Test(): AVLTreeForTest { - val rightSonSRightSon = AVLVertex('o', false, null, AVLVertex('p', true), -1) - val rightSon = AVLVertex('m', true, AVLVertex('l', true), rightSonSRightSon, -1) - val root = AVLVertex('k', true, AVLVertex('i', false, AVLVertex('a', false), null, 1), rightSon, -1) - return AVLTreeForTest(root, 7L) - } - - private fun makeTreeForRemoveWithLeftRotate2Test(): AVLTreeForTest { - val rightSonSRightSon = AVLVertex('o', false, AVLVertex('n', true), AVLVertex('p', true), 0) - val rightSon = AVLVertex('m', true, AVLVertex('l', true), rightSonSRightSon, -1) - val root = AVLVertex('k', true, AVLVertex('i', false, AVLVertex('a', false), null, 1), rightSon, -1) - return AVLTreeForTest(root, 8L) - } - - // new subroot initially had sonSHeightDiff == -1 in (1) and 0 in (2) - @Test - fun `returns due value after removed and rotated left(1)`() { - val tree = makeTreeForRemoveWithLeftRotate1Test() - assert(tree.remove('l') == true) - } - - @Test - fun `returns due value after removed and rotated left(2)`() { - val tree = makeTreeForRemoveWithLeftRotate2Test() - assert(tree.remove('l') == true) - } - - @Test - fun `content is correct after removed and rotated left (1)`() { - val tree = makeTreeForRemoveWithLeftRotate1Test() - tree.remove('l') - val expectedContent = - setOf( - 'k' to true, - 'i' to false, - 'm' to true, - 'o' to false, - 'p' to true, - 'a' to false, - ) - assert(isTreeConsistsOf(expectedContent, tree)) - } - - @Test - fun `content is correct after removed and rotated left (2)`() { - val tree = makeTreeForRemoveWithLeftRotate2Test() - tree.remove('l') - val expectedContent = - setOf( - 'k' to true, - 'i' to false, - 'm' to true, - 'o' to false, - 'p' to true, - 'n' to true, - 'a' to false, - ) - assert(isTreeConsistsOf(expectedContent, tree)) - } - - @Test - fun `size decreased by 1 after removed and rotated left (1)`() { - val tree = makeTreeForRemoveWithLeftRotate1Test() - tree.remove('l') - assert(tree.size() == 6L) - } - - @Test - fun `size decreased by 1 after removed and rotated left (2)`() { - val tree = makeTreeForRemoveWithLeftRotate2Test() - tree.remove('l') - assert(tree.size() == 7L) - } - - @Test - fun `structure is correct after removed and rotated left (1)`() { - val tree = makeTreeForRemoveWithLeftRotate1Test() - tree.remove('l') - val expectedDependences = listOf(Triple(0, 1, 3), Triple(3, 4, 5), Triple(1, 2, null)) - val expectedOrder = arrayOf('k', 'i', 'a', 'o', 'm', 'p') - assert(isTreeSStructureThat(tree, expectedOrder, expectedDependences)) - } - - @Test - fun `structure is correct after removed and rotated left (2)`() { - val tree = makeTreeForRemoveWithLeftRotate2Test() - tree.remove('l') - val expectedDependences = - listOf( - Triple(0, 1, 3), - Triple(3, 4, 6), - Triple(4, null, 5), - Triple(1, 2, null), - ) - val expectedOrder = arrayOf('k', 'i', 'a', 'o', 'm', 'n', 'p') - assert(isTreeSStructureThat(tree, expectedOrder, expectedDependences)) - } - - @Test - fun `vertexes' sonsHeightDiff are correct after removed and rotated left (1)`() { - val tree = makeTreeForRemoveWithLeftRotate1Test() - tree.remove('l') - assert(isSonsHeightDiffCorrect(tree)) - } - - @Test - fun `vertexes' sonsHeightDiff are correct after removed and rotated left (2)`() { - val tree = makeTreeForRemoveWithLeftRotate2Test() - tree.remove('l') - assert(isSonsHeightDiffCorrect(tree)) - } - - private fun makeTreeForRemoveWithRightRotate1Test(): AVLTreeForTest { - val leftSonSLeftSon = AVLVertex('b', true, AVLVertex('a', false), null, 1) - val leftSon = AVLVertex('d', true, leftSonSLeftSon, AVLVertex('e', false), 1) - val root = AVLVertex('k', true, leftSon, AVLVertex('m', true, null, AVLVertex('o', false), -1), 1) - return AVLTreeForTest(root, 7L) - } - - private fun makeTreeForRemoveWithRightRotate2Test(): AVLTreeForTest { - val leftSonSLeftSon = AVLVertex('b', true, AVLVertex('a', false), AVLVertex('c', true), 0) - val leftSon = AVLVertex('d', true, leftSonSLeftSon, AVLVertex('e', false), 1) - val root = AVLVertex('k', true, leftSon, AVLVertex('m', true, null, AVLVertex('o', false), -1), 1) - return AVLTreeForTest(root, 8L) - } - - // new subroot initially had sonSHeightDiff == 1 in (1) and 0 in (2) - @Test - fun `returns due value after removed and rotated right(1)`() { - val tree = makeTreeForRemoveWithRightRotate1Test() - assert(tree.remove('e') == false) - } - - @Test - fun `returns due value after removed and rotated right(2)`() { - val tree = makeTreeForRemoveWithRightRotate2Test() - assert(tree.remove('e') == false) - } - - @Test - fun `content is correct after removed and rotated right (1)`() { - val tree = makeTreeForRemoveWithRightRotate1Test() - tree.remove('e') - val expectedContent = - setOf( - 'k' to true, - 'b' to true, - 'm' to true, - 'o' to false, - 'd' to true, - 'a' to false, - ) - assert(isTreeConsistsOf(expectedContent, tree)) - } - - @Test - fun `content is correct after removed and rotated right (2)`() { - val tree = makeTreeForRemoveWithRightRotate2Test() - tree.remove('e') - val expectedContent = - setOf( - 'k' to true, - 'b' to true, - 'm' to true, - 'o' to false, - 'd' to true, - 'a' to false, - 'c' to true, - ) - assert(isTreeConsistsOf(expectedContent, tree)) - } - - @Test - fun `size decreased by 1 after removed and rotated right (1)`() { - val tree = makeTreeForRemoveWithRightRotate1Test() - tree.remove('e') - assert(tree.size() == 6L) - } - - @Test - fun `size decreased by 1 after removed and rotated right (2)`() { - val tree = makeTreeForRemoveWithRightRotate2Test() - tree.remove('e') - assert(tree.size() == 7L) - } - - @Test - fun `structure is correct after removed and rotated right (1)`() { - val tree = makeTreeForRemoveWithRightRotate1Test() - tree.remove('e') - val expectedDependences = listOf(Triple(0, 1, 4), Triple(1, 2, 3), Triple(4, null, 5)) - val expectedOrder = arrayOf('k', 'b', 'a', 'd', 'm', 'o') - assert(isTreeSStructureThat(tree, expectedOrder, expectedDependences)) - } - - @Test - fun `structure is correct after removed and rotated right (2)`() { - val tree = makeTreeForRemoveWithRightRotate2Test() - tree.remove('e') - val expectedDependences = - listOf( - Triple(0, 1, 5), - Triple(1, 2, 3), - Triple(5, null, 6), - Triple(3, 4, null), - ) - val expectedOrder = arrayOf('k', 'b', 'a', 'd', 'c', 'm', 'o') - assert(isTreeSStructureThat(tree, expectedOrder, expectedDependences)) - } - - @Test - fun `vertexes' sonsHeightDiff are correct after removed and rotated right (1)`() { - val tree = makeTreeForRemoveWithRightRotate1Test() - tree.remove('e') - assert(isSonsHeightDiffCorrect(tree)) - } - - @Test - fun `vertexes' sonsHeightDiff are correct after removed and rotated right (2)`() { - val tree = makeTreeForRemoveWithRightRotate2Test() - tree.remove('e') - assert(isSonsHeightDiffCorrect(tree)) - } - - private fun makeTreeForRotateLeftChangesRootRemoveTest(): AVLTreeForTest { - val root = AVLVertex(1, 1, AVLVertex(0, 0), AVLVertex(3, 3, AVLVertex(2, 2), AVLVertex(5, 5)), -1) - return AVLTreeForTest(root, 5L) - } - - @Test - fun `returns due value after removed and rotated right(rotateLeft changed root)`() { - val tree = makeTreeForRotateLeftChangesRootRemoveTest() - assert(tree.remove(0) == 0) - } - - @Test - fun `content is correct after removed (rotateLeft changed root)`() { - val tree = makeTreeForRotateLeftChangesRootRemoveTest() - tree.remove(0) - val expectedContent = setOf(1 to 1, 2 to 2, 3 to 3, 5 to 5) - assert(isTreeConsistsOf(expectedContent, tree)) - } - - @Test - fun `size decreased by 1 after removed (rotateLeft changed root)`() { - val tree = makeTreeForRotateLeftChangesRootRemoveTest() - tree.remove(0) - assert(tree.size() == 4L) - } - - @Test - fun `structure is correct after removed (rotateLeft changed root)`() { - val tree = makeTreeForRotateLeftChangesRootRemoveTest() - tree.remove(0) - val expectedDependences = listOf(Triple(0, 1, 3), Triple(1, null, 2)) - val expectedOrder = arrayOf(3, 1, 2, 5) - assert(isTreeSStructureThat(tree, expectedOrder, expectedDependences)) - } - - @Test - fun `vertexes' sonsHeightDiff are correct after removed (rotateLeft changed root)`() { - val tree = makeTreeForRotateLeftChangesRootRemoveTest() - tree.remove(0) - assert(isSonsHeightDiffCorrect(tree)) - } - - private fun makeTreeForRotateRightChangesRootRemoveTest(): AVLTreeForTest { - val root = AVLVertex(-1, 1, AVLVertex(-3, 3, AVLVertex(-5, 5), AVLVertex(-2, 2)), AVLVertex(0, 0), 1) - return AVLTreeForTest(root, 5L) - } - - @Test - fun `returns due value after removed and rotated right(rotateRight changed root)`() { - val tree = makeTreeForRotateRightChangesRootRemoveTest() - assert(tree.remove(0) == 0) - } - - @Test - fun `content is correct after removed (rotateRight changed root)`() { - val tree = makeTreeForRotateRightChangesRootRemoveTest() - tree.remove(0) - val expectedContent = setOf(-1 to 1, -2 to 2, -3 to 3, -5 to 5) - assert(isTreeConsistsOf(expectedContent, tree)) - } - - @Test - fun `size decreased by 1 after removed (rotateRight changed root)`() { - val tree = makeTreeForRotateRightChangesRootRemoveTest() - tree.remove(0) - assert(tree.size() == 4L) - } - - @Test - fun `structure is correct after removed (rotateRight changed root)`() { - val tree = makeTreeForRotateRightChangesRootRemoveTest() - tree.remove(0) - val expectedDependences = listOf(Triple(0, 1, 2), Triple(2, 3, null)) - val expectedOrder = arrayOf(-3, -5, -1, -2) - assert(isTreeSStructureThat(tree, expectedOrder, expectedDependences)) - } - - @Test - fun `vertexes' sonsHeightDiff are correct after removed (rotateRight changed root)`() { - val tree = makeTreeForRotateRightChangesRootRemoveTest() - tree.remove(0) - assert(isSonsHeightDiffCorrect(tree)) - } - - private fun makeTreeForBigRotateLeftChangesRootRemoveTest(): AVLTreeForTest { - val rightSonSLeftSon = AVLVertex('d', 'D', AVLVertex('c', 'C'), AVLVertex('e', 'E')) - val rightSon = AVLVertex('f', 'F', rightSonSLeftSon, AVLVertex('g', 'G'), 1) - val root = AVLVertex('b', 'B', AVLVertex('a', 'A', AVLVertex(' ', ' '), null, 1), rightSon, -1) - return AVLTreeForTest(root, 8L) - } - - @Test - fun `remove returns due value(bigRotateLeft changed root)`() { - val tree = makeTreeForBigRotateLeftChangesRootRemoveTest() - assert(tree.remove(' ') == ' ') - } - - @Test - fun `content is correct after removed (bigRotateLeft changed root)`() { - val tree = makeTreeForBigRotateLeftChangesRootRemoveTest() - tree.remove(' ') - val expectedContent = - setOf( - 'd' to 'D', - 'c' to 'C', - 'e' to 'E', - 'f' to 'F', - 'g' to 'G', - 'b' to 'B', - 'a' to 'A', - ) - assert(isTreeConsistsOf(expectedContent, tree)) - } - - @Test - fun `size decreased by 1 after removed (bigRotateLeft changed root)`() { - val tree = makeTreeForBigRotateLeftChangesRootRemoveTest() - tree.remove(' ') - assert(tree.size() == 7L) - } - - @Test - fun `structure is correct after removed (bigRotateLeft changed root)`() { - val tree = makeTreeForBigRotateLeftChangesRootRemoveTest() - tree.remove(' ') - val expectedDependences = listOf(Triple(0, 1, 4), Triple(1, 2, 3), Triple(4, 5, 6)) - val expectedOrder = arrayOf('d', 'b', 'a', 'c', 'f', 'e', 'g') - assert(isTreeSStructureThat(tree, expectedOrder, expectedDependences)) - } - - @Test - fun `vertexes' sonsHeightDiff are correct after removed (bigRotateLeft changed root)`() { - val tree = makeTreeForBigRotateLeftChangesRootRemoveTest() - tree.remove(' ') - assert(isSonsHeightDiffCorrect(tree)) - } - - private fun makeTreeForBigRotateRightChangesRootRemoveTest(): AVLTreeForTest { - val leftSonSRightSon = AVLVertex('e', 5, AVLVertex('c', 3), AVLVertex('d', 4)) - val leftSon = AVLVertex('b', 2, AVLVertex('a', 1), leftSonSRightSon, -1) - val root = AVLVertex('f', 8, leftSon, AVLVertex('i', 9, null, AVLVertex('k', 10), -1), 1) - return AVLTreeForTest(root, 8L) - } - - @Test - fun `remove returns due value(bigRotateRight changed root)`() { - val tree = makeTreeForBigRotateRightChangesRootRemoveTest() - assert(tree.remove('k') == 10) - } - - @Test - fun `content is correct after removed (bigRotateRight changed root)`() { - val tree = makeTreeForBigRotateRightChangesRootRemoveTest() - tree.remove('k') - val expectedContent = - setOf( - 'a' to 1, - 'b' to 2, - 'c' to 3, - 'd' to 4, - 'e' to 5, - 'i' to 9, - 'f' to 8, - ) - assert(isTreeConsistsOf(expectedContent, tree)) - } - - @Test - fun `size decreased by 1 after removed (bigRotateRight changed root)`() { - val tree = makeTreeForBigRotateRightChangesRootRemoveTest() - tree.remove('k') - assert(tree.size() == 7L) - } - - @Test - fun `structure is correct after removed (bigRotateRight changed root)`() { - val tree = makeTreeForBigRotateRightChangesRootRemoveTest() - tree.remove('k') - val expectedDependences = listOf(Triple(0, 1, 4), Triple(1, 2, 3), Triple(4, 5, 6)) - val expectedOrder = arrayOf('e', 'b', 'a', 'c', 'f', 'd', 'i') - assert(isTreeSStructureThat(tree, expectedOrder, expectedDependences)) - } - - @Test - fun `vertexes' sonsHeightDiff are correct after removed (bigRotateRight changed root)`() { - val tree = makeTreeForBigRotateRightChangesRootRemoveTest() - tree.remove('k') - assert(isSonsHeightDiffCorrect(tree)) - } -} diff --git a/lib/src/test/kotlin/trees/avlTree/AuxiliaryFunctions.kt b/lib/src/test/kotlin/trees/avlTree/AuxiliaryFunctions.kt new file mode 100644 index 0000000..3e932ea --- /dev/null +++ b/lib/src/test/kotlin/trees/avlTree/AuxiliaryFunctions.kt @@ -0,0 +1,60 @@ +package trees.avlTree + +import vertexes.AVLVertex + +object AuxiliaryFunctions { + fun isTreeConsistsOf( + expectedContent: Set>, + tree: AVLTreeForTest, + ): Boolean { + val vertexes = tree.getVertexesInDFSOrder() + val pairsFromVertexes = (Array(vertexes.size) { i -> (vertexes[i].key to vertexes[i].value) }).toSet() + return pairsFromVertexes == expectedContent + } + + fun isTreeSStructureThat( + tree: AVLTreeForTest, + order: Array, + deps: List>, + ): Boolean { + // Triple consists of indexes in order of (1)vertex, one's (2)leftSon and (3)RightSon + val vertexes = tree.getVertexesInDFSOrder() + if (vertexes.size != order.size) return false + for (i in order.indices) + if (order[i] != vertexes[i].key) return false + for (dep in deps) { + if (dep.component2() != null) { + if (vertexes[dep.component1()].leftSon != vertexes[dep.component2() as Int]) { + return false + } + } + if (dep.component3() != null) { + if (vertexes[dep.component1()].rightSon != vertexes[dep.component3() as Int]) { + return false + } + } + } + return true + } + + fun isSonsHeightDiffCorrect(tree: AVLTreeForTest): Boolean { + val vertexes = tree.getVertexesInDFSOrder() + val heights = tree.getHeights() + if (vertexes.size != heights.size) return false + for (vertex in vertexes) { + val expectedSonsHeightDiff = + when ((vertex.leftSon == null) to (vertex.rightSon == null)) { + true to true -> 0 + true to false -> -1 - (heights[(vertex.rightSon as AVLVertex).key] ?: return false) + false to true -> 1 + (heights[(vertex.leftSon as AVLVertex).key] ?: return false) + else -> { + val heightOfLeftSubtree = heights[(vertex.leftSon as AVLVertex).key] ?: return false + val heightOfRightSubtree = heights[(vertex.rightSon as AVLVertex).key] ?: return false + heightOfLeftSubtree - heightOfRightSubtree + } + } + if (expectedSonsHeightDiff != vertex.sonsHeightDiff) return false + } + return true + } +} diff --git a/lib/src/test/kotlin/trees/avlTree/putTest/HaveToDoBigRotation.kt b/lib/src/test/kotlin/trees/avlTree/putTest/HaveToDoBigRotation.kt new file mode 100644 index 0000000..7beabd4 --- /dev/null +++ b/lib/src/test/kotlin/trees/avlTree/putTest/HaveToDoBigRotation.kt @@ -0,0 +1,222 @@ +package trees.avlTree.putTest + +import org.junit.jupiter.api.Test +import trees.avlTree.AVLTreeForTest +import trees.avlTree.AuxiliaryFunctions.isSonsHeightDiffCorrect +import trees.avlTree.AuxiliaryFunctions.isTreeConsistsOf +import trees.avlTree.AuxiliaryFunctions.isTreeSStructureThat +import vertexes.AVLVertex + +class HaveToDoBigRotation { + private fun makeTreeForHaveToDoBigLeftRotationPutTest(): AVLTreeForTest { + val rightSonSRightSon = AVLVertex('i', 'I', AVLVertex('g', 'G'), AVLVertex('j', 'J')) + val rightSon = AVLVertex('e', 'E', AVLVertex('d', 'D'), rightSonSRightSon, -1) + val root = AVLVertex('c', 'C', AVLVertex('b', 'B', AVLVertex('a', 'A'), null, 1), rightSon, -1) + return AVLTreeForTest(root, 8L) + } + + // (1) - add grandson's right son, (2) add grandson's left son + @Test + fun `content is correct after entry was added (big left rotation) (1)`() { + val tree = makeTreeForHaveToDoBigLeftRotationPutTest() + tree.put('f', 'F') + val expectedContent = + setOf( + 'a' to 'A', + 'b' to 'B', + 'c' to 'C', + 'd' to 'D', + 'e' to 'E', + 'g' to 'G', + 'f' to 'F', + 'i' to 'I', + 'j' to 'J', + ) + assert(isTreeConsistsOf(expectedContent, tree)) + } + + @Test + fun `content is correct after entry was added (big left rotation) (2)`() { + val tree = makeTreeForHaveToDoBigLeftRotationPutTest() + tree.put('h', 'H') + val expectedContent = + setOf( + 'a' to 'A', + 'b' to 'B', + 'c' to 'C', + 'd' to 'D', + 'e' to 'E', + 'h' to 'H', + 'g' to 'G', + 'i' to 'I', + 'j' to 'J', + ) + assert(isTreeConsistsOf(expectedContent, tree)) + } + + @Test + fun `size increased by 1 after entry was added (big left rotation) (1)`() { + val tree = makeTreeForHaveToDoBigLeftRotationPutTest() + tree.put('f', 'F') + assert(tree.size() == 9L) + } + + @Test + fun `size increased by 1 after entry was added (big left rotation) (2)`() { + val tree = makeTreeForHaveToDoBigLeftRotationPutTest() + tree.put('h', 'H') + assert(tree.size() == 9L) + } + + @Test + fun `structure is correct after entry was added (big left rotation) (1)`() { + val tree = makeTreeForHaveToDoBigLeftRotationPutTest() + tree.put('f', 'F') + val expectedDependencies = + listOf( + Triple(0, 1, 3), + Triple(1, 2, null), + Triple(3, 4, 7), + Triple(4, 5, 6), + Triple(7, null, 8), + ) + val expectedOrder = arrayOf('c', 'b', 'a', 'g', 'e', 'd', 'f', 'i', 'j') + assert(isTreeSStructureThat(tree, expectedOrder, expectedDependencies)) + } + + @Test + fun `structure is correct after entry was added (big left rotation) (2)`() { + val tree = makeTreeForHaveToDoBigLeftRotationPutTest() + tree.put('h', 'H') + val expectedDependencies = + listOf( + Triple(0, 1, 3), + Triple(1, 2, null), + Triple(3, 4, 6), + Triple(4, 5, null), + Triple(6, 7, 8), + ) + val expectedOrder = arrayOf('c', 'b', 'a', 'g', 'e', 'd', 'i', 'h', 'j') + assert(isTreeSStructureThat(tree, expectedOrder, expectedDependencies)) + } + + @Test + fun `sonsHeightDiff values are correct after entry was added (big left rotation) (1)`() { + val tree = makeTreeForHaveToDoBigLeftRotationPutTest() + tree.put('f', 'F') + assert(isSonsHeightDiffCorrect(tree)) + } + + @Test + fun `sonsHeightDiff values are correct after entry was added (big left rotation) (2)`() { + val tree = makeTreeForHaveToDoBigLeftRotationPutTest() + tree.put('h', 'H') + assert(isSonsHeightDiffCorrect(tree)) + } + + private fun makeTreeForHaveToDoBigRightRotationPutTest(): AVLTreeForTest { + val leftSonSLeftSon = AVLVertex('b', 'B', AVLVertex('a', 'A'), AVLVertex('d', 'D')) + val leftSon = AVLVertex('f', 'F', leftSonSLeftSon, AVLVertex('g', 'G'), 1) + val root = AVLVertex('h', 'H', leftSon, AVLVertex('i', 'I', null, AVLVertex('j', 'J'), -1), 1) + return AVLTreeForTest(root, 8L) + } + + // (1) - add grandson's left son, (2) add grandson's right son + @Test + fun `content is correct after entry was added (big right rotation) (1)`() { + val tree = makeTreeForHaveToDoBigRightRotationPutTest() + tree.put('c', 'C') + val expectedContent = + setOf( + 'a' to 'A', + 'b' to 'B', + 'c' to 'C', + 'd' to 'D', + 'h' to 'H', + 'g' to 'G', + 'f' to 'F', + 'i' to 'I', + 'j' to 'J', + ) + assert(isTreeConsistsOf(expectedContent, tree)) + } + + @Test + fun `content is correct after entry was added (big right rotation) (2)`() { + val tree = makeTreeForHaveToDoBigRightRotationPutTest() + tree.put('e', 'E') + val expectedContent = + setOf( + 'a' to 'A', + 'b' to 'B', + 'f' to 'F', + 'd' to 'D', + 'e' to 'E', + 'h' to 'H', + 'g' to 'G', + 'i' to 'I', + 'j' to 'J', + ) + assert(isTreeConsistsOf(expectedContent, tree)) + } + + @Test + fun `size increased by 1 after entry was added (big right rotation) (1)`() { + val tree = makeTreeForHaveToDoBigRightRotationPutTest() + tree.put('c', 'C') + assert(tree.size() == 9L) + } + + @Test + fun `size increased by 1 after entry was added (big right rotation) (2)`() { + val tree = makeTreeForHaveToDoBigRightRotationPutTest() + tree.put('e', 'E') + assert(tree.size() == 9L) + } + + @Test + fun `structure is correct after entry was added (big right rotation) (1)`() { + val tree = makeTreeForHaveToDoBigRightRotationPutTest() + tree.put('c', 'C') + val expectedDependencies = + listOf( + Triple(0, 1, 7), + Triple(7, null, 8), + Triple(1, 2, 5), + Triple(5, null, 6), + Triple(2, 3, 4), + ) + val expectedOrder = arrayOf('h', 'd', 'b', 'a', 'c', 'f', 'g', 'i', 'j') + assert(isTreeSStructureThat(tree, expectedOrder, expectedDependencies)) + } + + @Test + fun `structure is correct after entry was added (big right rotation) (2)`() { + val tree = makeTreeForHaveToDoBigRightRotationPutTest() + tree.put('e', 'E') + val expectedDependencies = + listOf( + Triple(0, 1, 7), + Triple(7, null, 8), + Triple(1, 2, 4), + Triple(2, 3, null), + Triple(4, 5, 6), + ) + val expectedOrder = arrayOf('h', 'd', 'b', 'a', 'f', 'e', 'g', 'i', 'j') + assert(isTreeSStructureThat(tree, expectedOrder, expectedDependencies)) + } + + @Test + fun `sonsHeightDiff values are correct after entry was added (big right rotation) (1)`() { + val tree = makeTreeForHaveToDoBigRightRotationPutTest() + tree.put('c', 'C') + assert(isSonsHeightDiffCorrect(tree)) + } + + @Test + fun `sonsHeightDiff values are correct after entry was added (big right rotation) (2)`() { + val tree = makeTreeForHaveToDoBigLeftRotationPutTest() + tree.put('e', 'E') + assert(isSonsHeightDiffCorrect(tree)) + } +} diff --git a/lib/src/test/kotlin/trees/avlTree/putTest/HaveToRotateLeft.kt b/lib/src/test/kotlin/trees/avlTree/putTest/HaveToRotateLeft.kt new file mode 100644 index 0000000..afc2ac4 --- /dev/null +++ b/lib/src/test/kotlin/trees/avlTree/putTest/HaveToRotateLeft.kt @@ -0,0 +1,103 @@ +package trees.avlTree.putTest + +import org.junit.jupiter.api.Test +import trees.avlTree.AVLTreeForTest +import trees.avlTree.AuxiliaryFunctions.isSonsHeightDiffCorrect +import trees.avlTree.AuxiliaryFunctions.isTreeConsistsOf +import trees.avlTree.AuxiliaryFunctions.isTreeSStructureThat +import vertexes.AVLVertex + +class HaveToRotateLeft { + private fun makeTreeForHaveToRotateLeftPutTest(): AVLTreeForTest { + val rightSonSRightSon = AVLVertex('h', 'H', AVLVertex('f', 'F'), AVLVertex('i', 'I')) + val rightSon = AVLVertex('e', 'E', AVLVertex('d', 'D'), rightSonSRightSon, -1) + val root = AVLVertex('c', 'C', AVLVertex('b', 'B', AVLVertex('a', 'A'), null, 1), rightSon, -1) + return AVLTreeForTest(root, 8L) + } + + @Test + fun `content is correct after entry was added`() { + val tree = makeTreeForHaveToRotateLeftPutTest() + tree.put('j', 'J') + val expectedContent = + setOf( + 'a' to 'A', + 'b' to 'B', + 'c' to 'C', + 'd' to 'D', + 'e' to 'E', + 'h' to 'H', + 'f' to 'F', + 'i' to 'I', + 'j' to 'J', + ) + assert(isTreeConsistsOf(expectedContent, tree)) + } + + @Test + fun `size increased by 1 after entry was added`() { + val tree = makeTreeForHaveToRotateLeftPutTest() + tree.put('j', 'J') + assert(tree.size() == 9L) + } + + @Test + fun `structure is correct after entry was added`() { + val tree = makeTreeForHaveToRotateLeftPutTest() + tree.put('j', 'J') + val expectedDependencies = + listOf( + Triple(0, 1, 3), + Triple(1, 2, null), + Triple(3, 4, 7), + Triple(4, 5, 6), + Triple(7, null, 8), + ) + val expectedOrder = arrayOf('c', 'b', 'a', 'h', 'e', 'd', 'f', 'i', 'j') + assert(isTreeSStructureThat(tree, expectedOrder, expectedDependencies)) + } + + @Test + fun `sonsHeightDiff values are correct after entry was added`() { + val tree = makeTreeForHaveToRotateLeftPutTest() + tree.put('j', 'J') + assert(isSonsHeightDiffCorrect(tree)) + } + + private fun makeTreeForHaveToChangeRootByRotateLeftPutTest(): AVLTreeForTest { + val rightSon = AVLVertex('h', 'H', AVLVertex('f', 'F'), AVLVertex('i', 'I')) + val root = AVLVertex('e', 'E', AVLVertex('d', 'D'), rightSon, -1) + return AVLTreeForTest(root, 5L) + } + + @Test + fun `content is correct after entry was added (rotateLeft changes root)`() { + val tree = makeTreeForHaveToChangeRootByRotateLeftPutTest() + tree.put('j', 'J') + val expectedContent = setOf('d' to 'D', 'e' to 'E', 'h' to 'H', 'f' to 'F', 'i' to 'I', 'j' to 'J') + assert(isTreeConsistsOf(expectedContent, tree)) + } + + @Test + fun `size increased by 1 after entry was added (rotateLeft changes root)`() { + val tree = makeTreeForHaveToChangeRootByRotateLeftPutTest() + tree.put('j', 'J') + assert(tree.size() == 6L) + } + + @Test + fun `structure is correct after entry was added (rotateLeft changes root)`() { + val tree = makeTreeForHaveToChangeRootByRotateLeftPutTest() + tree.put('j', 'J') + val expectedDependencies = listOf(Triple(0, 1, 4), Triple(1, 2, 3), Triple(4, null, 5)) + val expectedOrder = arrayOf('h', 'e', 'd', 'f', 'i', 'j') + assert(isTreeSStructureThat(tree, expectedOrder, expectedDependencies)) + } + + @Test + fun `sonsHeightDiff values are correct after entry was added (rotateLeft changes root)`() { + val tree = makeTreeForHaveToChangeRootByRotateLeftPutTest() + tree.put('j', 'J') + assert(isSonsHeightDiffCorrect(tree)) + } +} diff --git a/lib/src/test/kotlin/trees/avlTree/putTest/HaveToRotateRight.kt b/lib/src/test/kotlin/trees/avlTree/putTest/HaveToRotateRight.kt new file mode 100644 index 0000000..a03fb71 --- /dev/null +++ b/lib/src/test/kotlin/trees/avlTree/putTest/HaveToRotateRight.kt @@ -0,0 +1,103 @@ +package trees.avlTree.putTest + +import org.junit.jupiter.api.Test +import trees.avlTree.AVLTreeForTest +import trees.avlTree.AuxiliaryFunctions.isSonsHeightDiffCorrect +import trees.avlTree.AuxiliaryFunctions.isTreeConsistsOf +import trees.avlTree.AuxiliaryFunctions.isTreeSStructureThat +import vertexes.AVLVertex + +class HaveToRotateRight { + private fun makeTreeForHaveToRotateRightPutTest(): AVLTreeForTest { + val leftSonSLeftSon = AVLVertex('c', 'C', AVLVertex('b', 'B'), AVLVertex('d', 'D')) + val leftSon = AVLVertex('f', 'F', leftSonSLeftSon, AVLVertex('e', 'E'), 1) + val root = AVLVertex('h', 'H', leftSon, AVLVertex('i', 'I', null, AVLVertex('j', 'J'), -1), 1) + return AVLTreeForTest(root, 8L) + } + + @Test + fun `content is correct after entry was added `() { + val tree = makeTreeForHaveToRotateRightPutTest() + tree.put('a', 'A') + val expectedContent = + setOf( + 'a' to 'A', + 'b' to 'B', + 'c' to 'C', + 'd' to 'D', + 'e' to 'E', + 'h' to 'H', + 'f' to 'F', + 'i' to 'I', + 'j' to 'J', + ) + assert(isTreeConsistsOf(expectedContent, tree)) + } + + @Test + fun `size increased by 1 after entry was added`() { + val tree = makeTreeForHaveToRotateRightPutTest() + tree.put('a', 'A') + assert(tree.size() == 9L) + } + + @Test + fun `structure is correct after entry was added`() { + val tree = makeTreeForHaveToRotateRightPutTest() + tree.put('a', 'A') + val expectedDependencies = + listOf( + Triple(0, 1, 7), + Triple(1, 2, 4), + Triple(2, 3, null), + Triple(4, 5, 6), + Triple(7, null, 8), + ) + val expectedOrder = arrayOf('h', 'c', 'b', 'a', 'f', 'd', 'e', 'i', 'j') + assert(isTreeSStructureThat(tree, expectedOrder, expectedDependencies)) + } + + @Test + fun `sonsHeightDiff values are correct after entry was added`() { + val tree = makeTreeForHaveToRotateRightPutTest() + tree.put('a', 'A') + assert(isSonsHeightDiffCorrect(tree)) + } + + private fun makeTreeForHaveToChangeRootByRotateRightPutTest(): AVLTreeForTest { + val leftSon = AVLVertex('c', 'C', AVLVertex('b', 'B'), AVLVertex('d', 'D')) + val root = AVLVertex('f', 'F', leftSon, AVLVertex('e', 'E'), 1) + return AVLTreeForTest(root, 5L) + } + + @Test + fun `content is correct after entry was added (rotateRight changes root)`() { + val tree = makeTreeForHaveToChangeRootByRotateRightPutTest() + tree.put('a', 'A') + val expectedContent = setOf('a' to 'A', 'b' to 'B', 'c' to 'C', 'd' to 'D', 'e' to 'E', 'f' to 'F') + assert(isTreeConsistsOf(expectedContent, tree)) + } + + @Test + fun `size increased by 1 after entry was added (rotateRight changes root)`() { + val tree = makeTreeForHaveToChangeRootByRotateRightPutTest() + tree.put('a', 'A') + assert(tree.size() == 6L) + } + + @Test + fun `structure is correct after entry was added (rotateRight changes root)`() { + val tree = makeTreeForHaveToChangeRootByRotateRightPutTest() + tree.put('a', 'A') + val expectedDependencies = listOf(Triple(0, 1, 3), Triple(1, 2, null), Triple(3, 4, 5)) + val expectedOrder = arrayOf('c', 'b', 'a', 'f', 'd', 'e') + assert(isTreeSStructureThat(tree, expectedOrder, expectedDependencies)) + } + + @Test + fun `sonsHeightDiff values are correct after entry was added (rotateRight changes root)`() { + val tree = makeTreeForHaveToChangeRootByRotateRightPutTest() + tree.put('a', 'A') + assert(isSonsHeightDiffCorrect(tree)) + } +} diff --git a/lib/src/test/kotlin/trees/avlTree/putTest/Other.kt b/lib/src/test/kotlin/trees/avlTree/putTest/Other.kt new file mode 100644 index 0000000..2793296 --- /dev/null +++ b/lib/src/test/kotlin/trees/avlTree/putTest/Other.kt @@ -0,0 +1,27 @@ +package trees.avlTree.putTest + +import org.junit.jupiter.api.Test +import trees.avlTree.AVLTreeForTest +import trees.avlTree.AuxiliaryFunctions.isTreeConsistsOf +import vertexes.AVLVertex + +class Other { + private fun makeSize1Tree(): AVLTreeForTest { + return AVLTreeForTest(AVLVertex('b', '+'), 1L) + } + + @Test + fun `tree has no changes after entry with existed key and param replaceIfExists = false was added`() { + val tree = makeSize1Tree() + tree.put('b', '-', false) + assert(tree.size() == 1L) + assert(tree.getRootT()?.value == '+') + } + + @Test + fun `content is correct after init by map`() { + val tree = AVLTreeForTest(hashMapOf('a' to 'A', 'b' to 'B')) + val expectedContent = setOf('a' to 'A', 'b' to 'B') + assert(isTreeConsistsOf(expectedContent, tree)) + } +} diff --git a/lib/src/test/kotlin/trees/avlTree/putTest/WithoutBalancing.kt b/lib/src/test/kotlin/trees/avlTree/putTest/WithoutBalancing.kt new file mode 100644 index 0000000..d8cbb0c --- /dev/null +++ b/lib/src/test/kotlin/trees/avlTree/putTest/WithoutBalancing.kt @@ -0,0 +1,112 @@ +package trees.avlTree.putTest + +import org.junit.jupiter.api.Test +import trees.avlTree.AVLTreeForTest +import trees.avlTree.AuxiliaryFunctions.isSonsHeightDiffCorrect +import trees.avlTree.AuxiliaryFunctions.isTreeConsistsOf +import trees.avlTree.AuxiliaryFunctions.isTreeSStructureThat +import vertexes.AVLVertex + +class WithoutBalancing { + private fun makeEmptyTree(): AVLTreeForTest { + return AVLTreeForTest() + } + + @Test + fun `entry became root after it was added to empty tree`() { + val tree = makeEmptyTree() + tree.put(0, '0') + val root = tree.getRootT() + assert((root?.key to root?.value) == (0 to '0')) + } + + @Test + fun `size equals 1 after entry was added to empty tree`() { + val tree = makeEmptyTree() + tree.put(0, '0') + assert(tree.size() == 1L) + } + + private fun makeSize1Tree(): AVLTreeForTest { + return AVLTreeForTest(AVLVertex('b', '+'), 1L) // init tree by root and size (don't use put) + } + + @Test + fun `entry with larger key became right son after it was added to size 1 tree`() { + val tree = makeSize1Tree() + tree.put('c', '+') + val root = tree.getRootT() + assert((root?.rightSon?.key to root?.rightSon?.value) == ('c' to '+')) + } + + @Test + fun `entry with lesser key became left son after it was added to size 1 tree`() { + val tree = makeSize1Tree() + tree.put('a', '-') + val root = tree.getRootT() + assert((root?.leftSon?.key to root?.leftSon?.value) == ('a' to '-')) + } + + @Test + fun `root's sonsHeightDiff decreased by 1 after entry with larger key was added to size 1 tree`() { + val tree = makeSize1Tree() + tree.put('c', '+') + val root = tree.getRootT() + assert(root?.sonsHeightDiff == -1) + } + + @Test + fun `root's sonsHeightDiff increased by 1 after entry with lesser key was added to size 1 tree`() { + val tree = makeSize1Tree() + tree.put('a', '-') + val root = tree.getRootT() + assert(root?.sonsHeightDiff == 1) + } + + @Test + fun `size equals 2 after entry with larger key was added to size 1 tree`() { + val tree = makeSize1Tree() + tree.put('c', '+') + assert(tree.size() == 2L) + } + + @Test + fun `size equals 2 after entry with lesser key was added to size 1 tree`() { + val tree = makeSize1Tree() + tree.put('a', '-') + assert(tree.size() == 2L) + } + + private fun makeTreeForNeedNotBalancingPutTest(): AVLTreeForTest { + return AVLTreeForTest(AVLVertex(4, 'A', AVLVertex(1, 'I'), AVLVertex(5, 'S')), 3L) + } + + @Test + fun `content is correct after entry was added`() { + val tree = makeTreeForNeedNotBalancingPutTest() + tree.put(0, 'O') + assert(isTreeConsistsOf(setOf(0 to 'O', 1 to 'I', 5 to 'S', 4 to 'A'), tree)) + } + + @Test + fun `size increased by 1 after entry was added to 'size 2+' tree`() { + val tree = makeTreeForNeedNotBalancingPutTest() + tree.put(0, 'O') + assert(tree.size() == 4L) + } + + @Test + fun `structure is correct after entry was added to 'size 2+' tree`() { + val tree = makeTreeForNeedNotBalancingPutTest() + tree.put(0, 'O') + val expectedDependencies = listOf(Triple(0, 1, 3), Triple(1, 2, null)) + assert(isTreeSStructureThat(tree, arrayOf(4, 1, 0, 5), expectedDependencies)) + } + + @Test + fun `vertexes' sonsHeightDiff are correct after entry was added to 'size 2+' tree`() { + val tree = makeTreeForNeedNotBalancingPutTest() + tree.put(0, 'O') + assert(isSonsHeightDiffCorrect(tree)) + } +} diff --git a/lib/src/test/kotlin/trees/avlTree/removeTest/HaveToDoBigRotation.kt b/lib/src/test/kotlin/trees/avlTree/removeTest/HaveToDoBigRotation.kt new file mode 100644 index 0000000..5ea88b7 --- /dev/null +++ b/lib/src/test/kotlin/trees/avlTree/removeTest/HaveToDoBigRotation.kt @@ -0,0 +1,116 @@ +package trees.avlTree.removeTest + +import org.junit.jupiter.api.Test +import trees.avlTree.AVLTreeForTest +import trees.avlTree.AuxiliaryFunctions.isSonsHeightDiffCorrect +import trees.avlTree.AuxiliaryFunctions.isTreeConsistsOf +import trees.avlTree.AuxiliaryFunctions.isTreeSStructureThat +import vertexes.AVLVertex + +class HaveToDoBigRotation { + private fun makeTreeForBigLeftRotationChangesRootRemoveTest(): AVLTreeForTest { + val rightSonSLeftSon = AVLVertex('d', 'D', AVLVertex('c', 'C'), AVLVertex('e', 'E')) + val rightSon = AVLVertex('f', 'F', rightSonSLeftSon, AVLVertex('g', 'G'), 1) + val root = AVLVertex('b', 'B', AVLVertex('a', 'A', AVLVertex(' ', ' '), null, 1), rightSon, -1) + return AVLTreeForTest(root, 8L) + } + + @Test + fun `remove returns due value after deletion (bigRotateLeft changes root)`() { + val tree = makeTreeForBigLeftRotationChangesRootRemoveTest() + assert(tree.remove(' ') == ' ') + } + + @Test + fun `content is correct after deletion (bigRotateLeft changes root)`() { + val tree = makeTreeForBigLeftRotationChangesRootRemoveTest() + tree.remove(' ') + val expectedContent = + setOf( + 'd' to 'D', + 'c' to 'C', + 'e' to 'E', + 'f' to 'F', + 'g' to 'G', + 'b' to 'B', + 'a' to 'A', + ) + assert(isTreeConsistsOf(expectedContent, tree)) + } + + @Test + fun `size decreased by 1 after deletion (bigRotateLeft changes root)`() { + val tree = makeTreeForBigLeftRotationChangesRootRemoveTest() + tree.remove(' ') + assert(tree.size() == 7L) + } + + @Test + fun `structure is correct after deletion (bigRotateLeft changes root)`() { + val tree = makeTreeForBigLeftRotationChangesRootRemoveTest() + tree.remove(' ') + val expectedDependencies = listOf(Triple(0, 1, 4), Triple(1, 2, 3), Triple(4, 5, 6)) + val expectedOrder = arrayOf('d', 'b', 'a', 'c', 'f', 'e', 'g') + assert(isTreeSStructureThat(tree, expectedOrder, expectedDependencies)) + } + + @Test + fun `sonsHeightDiff values are correct after deletion (bigRotateLeft changes root)`() { + val tree = makeTreeForBigLeftRotationChangesRootRemoveTest() + tree.remove(' ') + assert(isSonsHeightDiffCorrect(tree)) + } + + private fun makeTreeForBigRightRotationChangesRootRemoveTest(): AVLTreeForTest { + val leftSonSRightSon = AVLVertex('e', 5, AVLVertex('c', 3), AVLVertex('d', 4)) + val leftSon = AVLVertex('b', 2, AVLVertex('a', 1), leftSonSRightSon, -1) + val root = AVLVertex('f', 8, leftSon, AVLVertex('i', 9, null, AVLVertex('k', 10), -1), 1) + return AVLTreeForTest(root, 8L) + } + + @Test + fun `remove returns due value after deletion (bigRotateRight changes root)`() { + val tree = makeTreeForBigRightRotationChangesRootRemoveTest() + assert(tree.remove('k') == 10) + } + + @Test + fun `content is correct after deletion (bigRotateRight changes root)`() { + val tree = makeTreeForBigRightRotationChangesRootRemoveTest() + tree.remove('k') + val expectedContent = + setOf( + 'a' to 1, + 'b' to 2, + 'c' to 3, + 'd' to 4, + 'e' to 5, + 'i' to 9, + 'f' to 8, + ) + assert(isTreeConsistsOf(expectedContent, tree)) + } + + @Test + fun `size decreased by 1 after deletion (bigRotateRight changes root)`() { + val tree = makeTreeForBigRightRotationChangesRootRemoveTest() + tree.remove('k') + assert(tree.size() == 7L) + } + + @Test + fun `structure is correct after deletion (bigRotateRight changes root)`() { + val tree = makeTreeForBigRightRotationChangesRootRemoveTest() + tree.remove('k') + val expectedDependencies = listOf(Triple(0, 1, 4), Triple(1, 2, 3), Triple(4, 5, 6)) + val expectedOrder = arrayOf('e', 'b', 'a', 'c', 'f', 'd', 'i') + assert(isTreeSStructureThat(tree, expectedOrder, expectedDependencies)) + } + + @Test + fun `sonsHeightDiff values are correct after deletion (bigRotateRight changes root)`() { + val tree = makeTreeForBigRightRotationChangesRootRemoveTest() + tree.remove('k') + assert(isSonsHeightDiffCorrect(tree)) + } +} diff --git a/lib/src/test/kotlin/trees/avlTree/removeTest/HaveToRotateLeft.kt b/lib/src/test/kotlin/trees/avlTree/removeTest/HaveToRotateLeft.kt new file mode 100644 index 0000000..a56fbd9 --- /dev/null +++ b/lib/src/test/kotlin/trees/avlTree/removeTest/HaveToRotateLeft.kt @@ -0,0 +1,164 @@ +package trees.avlTree.removeTest + +import org.junit.jupiter.api.Test +import trees.avlTree.AVLTreeForTest +import trees.avlTree.AuxiliaryFunctions.isSonsHeightDiffCorrect +import trees.avlTree.AuxiliaryFunctions.isTreeConsistsOf +import trees.avlTree.AuxiliaryFunctions.isTreeSStructureThat +import vertexes.AVLVertex + +class HaveToRotateLeft { + private fun makeTreeForRemoveWithLeftRotation1Test(): AVLTreeForTest { + val rightSonSRightSon = AVLVertex('o', false, null, AVLVertex('p', true), -1) + val rightSon = AVLVertex('m', true, AVLVertex('l', true), rightSonSRightSon, -1) + val root = AVLVertex('k', true, AVLVertex('i', false, AVLVertex('a', false), null, 1), rightSon, -1) + return AVLTreeForTest(root, 7L) + } + + private fun makeTreeForRemoveWithLeftRotation2Test(): AVLTreeForTest { + val rightSonSRightSon = AVLVertex('o', false, AVLVertex('n', true), AVLVertex('p', true), 0) + val rightSon = AVLVertex('m', true, AVLVertex('l', true), rightSonSRightSon, -1) + val root = AVLVertex('k', true, AVLVertex('i', false, AVLVertex('a', false), null, 1), rightSon, -1) + return AVLTreeForTest(root, 8L) + } + + // new subtree's root initially had sonSHeightDiff == -1 in (1) and 0 in (2) + @Test + fun `returns due value after deletion (1)`() { + val tree = makeTreeForRemoveWithLeftRotation1Test() + assert(tree.remove('l') == true) + } + + @Test + fun `returns due value after deletion (2)`() { + val tree = makeTreeForRemoveWithLeftRotation2Test() + assert(tree.remove('l') == true) + } + + @Test + fun `content is correct after deletion (1)`() { + val tree = makeTreeForRemoveWithLeftRotation1Test() + tree.remove('l') + val expectedContent = + setOf( + 'k' to true, + 'i' to false, + 'm' to true, + 'o' to false, + 'p' to true, + 'a' to false, + ) + assert(isTreeConsistsOf(expectedContent, tree)) + } + + @Test + fun `content is correct after deletion (2)`() { + val tree = makeTreeForRemoveWithLeftRotation2Test() + tree.remove('l') + val expectedContent = + setOf( + 'k' to true, + 'i' to false, + 'm' to true, + 'o' to false, + 'p' to true, + 'n' to true, + 'a' to false, + ) + assert(isTreeConsistsOf(expectedContent, tree)) + } + + @Test + fun `size decreased by 1 after deletion (1)`() { + val tree = makeTreeForRemoveWithLeftRotation1Test() + tree.remove('l') + assert(tree.size() == 6L) + } + + @Test + fun `size decreased by 1 after deletion (2)`() { + val tree = makeTreeForRemoveWithLeftRotation2Test() + tree.remove('l') + assert(tree.size() == 7L) + } + + @Test + fun `structure is correct after deletion (1)`() { + val tree = makeTreeForRemoveWithLeftRotation1Test() + tree.remove('l') + val expectedDependencies = listOf(Triple(0, 1, 3), Triple(3, 4, 5), Triple(1, 2, null)) + val expectedOrder = arrayOf('k', 'i', 'a', 'o', 'm', 'p') + assert(isTreeSStructureThat(tree, expectedOrder, expectedDependencies)) + } + + @Test + fun `structure is correct after deletion (2)`() { + val tree = makeTreeForRemoveWithLeftRotation2Test() + tree.remove('l') + val expectedDependencies = + listOf( + Triple(0, 1, 3), + Triple(3, 4, 6), + Triple(4, null, 5), + Triple(1, 2, null), + ) + val expectedOrder = arrayOf('k', 'i', 'a', 'o', 'm', 'n', 'p') + assert(isTreeSStructureThat(tree, expectedOrder, expectedDependencies)) + } + + @Test + fun `sonsHeightDiff values are correct after deletion (1)`() { + val tree = makeTreeForRemoveWithLeftRotation1Test() + tree.remove('l') + assert(isSonsHeightDiffCorrect(tree)) + } + + @Test + fun `sonsHeightDiff values are correct after deletion (2)`() { + val tree = makeTreeForRemoveWithLeftRotation2Test() + tree.remove('l') + assert(isSonsHeightDiffCorrect(tree)) + } + + private fun makeTreeForLeftRotationChangesRootRemoveTest(): AVLTreeForTest { + val root = AVLVertex(1, 1, AVLVertex(0, 0), AVLVertex(3, 3, AVLVertex(2, 2), AVLVertex(5, 5)), -1) + return AVLTreeForTest(root, 5L) + } + + @Test + fun `returns due value after deletion (rotateLeft changes root)`() { + val tree = makeTreeForLeftRotationChangesRootRemoveTest() + assert(tree.remove(0) == 0) + } + + @Test + fun `content is correct after deletion (rotateLeft changes root)`() { + val tree = makeTreeForLeftRotationChangesRootRemoveTest() + tree.remove(0) + val expectedContent = setOf(1 to 1, 2 to 2, 3 to 3, 5 to 5) + assert(isTreeConsistsOf(expectedContent, tree)) + } + + @Test + fun `size decreased by 1 after deletion (rotateLeft changes root)`() { + val tree = makeTreeForLeftRotationChangesRootRemoveTest() + tree.remove(0) + assert(tree.size() == 4L) + } + + @Test + fun `structure is correct after deletion (rotateLeft changes root)`() { + val tree = makeTreeForLeftRotationChangesRootRemoveTest() + tree.remove(0) + val expectedDependencies = listOf(Triple(0, 1, 3), Triple(1, null, 2)) + val expectedOrder = arrayOf(3, 1, 2, 5) + assert(isTreeSStructureThat(tree, expectedOrder, expectedDependencies)) + } + + @Test + fun `sonsHeightDiff values are correct after deletion (rotateLeft changes root)`() { + val tree = makeTreeForLeftRotationChangesRootRemoveTest() + tree.remove(0) + assert(isSonsHeightDiffCorrect(tree)) + } +} diff --git a/lib/src/test/kotlin/trees/avlTree/removeTest/HaveToRotateRight.kt b/lib/src/test/kotlin/trees/avlTree/removeTest/HaveToRotateRight.kt new file mode 100644 index 0000000..b30628b --- /dev/null +++ b/lib/src/test/kotlin/trees/avlTree/removeTest/HaveToRotateRight.kt @@ -0,0 +1,164 @@ +package trees.avlTree.removeTest + +import org.junit.jupiter.api.Test +import trees.avlTree.AVLTreeForTest +import trees.avlTree.AuxiliaryFunctions.isSonsHeightDiffCorrect +import trees.avlTree.AuxiliaryFunctions.isTreeConsistsOf +import trees.avlTree.AuxiliaryFunctions.isTreeSStructureThat +import vertexes.AVLVertex + +class HaveToRotateRight { + private fun makeTreeForRemoveWithRightRotation1Test(): AVLTreeForTest { + val leftSonSLeftSon = AVLVertex('b', true, AVLVertex('a', false), null, 1) + val leftSon = AVLVertex('d', true, leftSonSLeftSon, AVLVertex('e', false), 1) + val root = AVLVertex('k', true, leftSon, AVLVertex('m', true, null, AVLVertex('o', false), -1), 1) + return AVLTreeForTest(root, 7L) + } + + private fun makeTreeForRemoveWithRightRotation2Test(): AVLTreeForTest { + val leftSonSLeftSon = AVLVertex('b', true, AVLVertex('a', false), AVLVertex('c', true), 0) + val leftSon = AVLVertex('d', true, leftSonSLeftSon, AVLVertex('e', false), 1) + val root = AVLVertex('k', true, leftSon, AVLVertex('m', true, null, AVLVertex('o', false), -1), 1) + return AVLTreeForTest(root, 8L) + } + + // new subtree's root initially had sonSHeightDiff == 1 in (1) and 0 in (2) + @Test + fun `returns due value after deletion (1)`() { + val tree = makeTreeForRemoveWithRightRotation1Test() + assert(tree.remove('e') == false) + } + + @Test + fun `returns due value after deletion (2)`() { + val tree = makeTreeForRemoveWithRightRotation2Test() + assert(tree.remove('e') == false) + } + + @Test + fun `content is correct after deletion (1)`() { + val tree = makeTreeForRemoveWithRightRotation1Test() + tree.remove('e') + val expectedContent = + setOf( + 'k' to true, + 'b' to true, + 'm' to true, + 'o' to false, + 'd' to true, + 'a' to false, + ) + assert(isTreeConsistsOf(expectedContent, tree)) + } + + @Test + fun `content is correct after deletion (2)`() { + val tree = makeTreeForRemoveWithRightRotation2Test() + tree.remove('e') + val expectedContent = + setOf( + 'k' to true, + 'b' to true, + 'm' to true, + 'o' to false, + 'd' to true, + 'a' to false, + 'c' to true, + ) + assert(isTreeConsistsOf(expectedContent, tree)) + } + + @Test + fun `size decreased by 1 after deletion (1)`() { + val tree = makeTreeForRemoveWithRightRotation1Test() + tree.remove('e') + assert(tree.size() == 6L) + } + + @Test + fun `size decreased by 1 after deletion (2)`() { + val tree = makeTreeForRemoveWithRightRotation2Test() + tree.remove('e') + assert(tree.size() == 7L) + } + + @Test + fun `structure is correct after deletion (1)`() { + val tree = makeTreeForRemoveWithRightRotation1Test() + tree.remove('e') + val expectedDependencies = listOf(Triple(0, 1, 4), Triple(1, 2, 3), Triple(4, null, 5)) + val expectedOrder = arrayOf('k', 'b', 'a', 'd', 'm', 'o') + assert(isTreeSStructureThat(tree, expectedOrder, expectedDependencies)) + } + + @Test + fun `structure is correct after deletion (2)`() { + val tree = makeTreeForRemoveWithRightRotation2Test() + tree.remove('e') + val expectedDependencies = + listOf( + Triple(0, 1, 5), + Triple(1, 2, 3), + Triple(5, null, 6), + Triple(3, 4, null), + ) + val expectedOrder = arrayOf('k', 'b', 'a', 'd', 'c', 'm', 'o') + assert(isTreeSStructureThat(tree, expectedOrder, expectedDependencies)) + } + + @Test + fun `sonsHeightDiff values are correct after deletion (1)`() { + val tree = makeTreeForRemoveWithRightRotation1Test() + tree.remove('e') + assert(isSonsHeightDiffCorrect(tree)) + } + + @Test + fun `sonsHeightDiff values are correct after deletion (2)`() { + val tree = makeTreeForRemoveWithRightRotation2Test() + tree.remove('e') + assert(isSonsHeightDiffCorrect(tree)) + } + + private fun makeTreeForRightRotationChangesRootRemoveTest(): AVLTreeForTest { + val root = AVLVertex(-1, 1, AVLVertex(-3, 3, AVLVertex(-5, 5), AVLVertex(-2, 2)), AVLVertex(0, 0), 1) + return AVLTreeForTest(root, 5L) + } + + @Test + fun `returns due value after deletion (rotateRight changes root)`() { + val tree = makeTreeForRightRotationChangesRootRemoveTest() + assert(tree.remove(0) == 0) + } + + @Test + fun `content is correct after deletion (rotateRight changes root)`() { + val tree = makeTreeForRightRotationChangesRootRemoveTest() + tree.remove(0) + val expectedContent = setOf(-1 to 1, -2 to 2, -3 to 3, -5 to 5) + assert(isTreeConsistsOf(expectedContent, tree)) + } + + @Test + fun `size decreased by 1 after deletion (rotateRight changes root)`() { + val tree = makeTreeForRightRotationChangesRootRemoveTest() + tree.remove(0) + assert(tree.size() == 4L) + } + + @Test + fun `structure is correct after deletion (rotateRight changes root)`() { + val tree = makeTreeForRightRotationChangesRootRemoveTest() + tree.remove(0) + val expectedDependencies = listOf(Triple(0, 1, 2), Triple(2, 3, null)) + val expectedOrder = arrayOf(-3, -5, -1, -2) + assert(isTreeSStructureThat(tree, expectedOrder, expectedDependencies)) + } + + @Test + fun `sonsHeightDiff values are correct after deletion (rotateRight changes root)`() { + val tree = makeTreeForRightRotationChangesRootRemoveTest() + tree.remove(0) + assert(isSonsHeightDiffCorrect(tree)) + } +} diff --git a/lib/src/test/kotlin/trees/avlTree/removeTest/withoutBalancing/Other.kt b/lib/src/test/kotlin/trees/avlTree/removeTest/withoutBalancing/Other.kt new file mode 100644 index 0000000..bb47e57 --- /dev/null +++ b/lib/src/test/kotlin/trees/avlTree/removeTest/withoutBalancing/Other.kt @@ -0,0 +1,338 @@ +package trees.avlTree.removeTest.withoutBalancing + +import org.junit.jupiter.api.Test +import trees.avlTree.AVLTreeForTest +import trees.avlTree.AuxiliaryFunctions.isSonsHeightDiffCorrect +import trees.avlTree.AuxiliaryFunctions.isTreeConsistsOf +import trees.avlTree.AuxiliaryFunctions.isTreeSStructureThat +import vertexes.AVLVertex + +class Other { + private fun makeEmptyTree(): AVLTreeForTest { + return AVLTreeForTest() + } + + @Test + fun `delete from emptyTree returns null`() { + val tree = makeEmptyTree() + assert(tree.remove(0) == null) + } + + private fun makeSize1Tree(): AVLTreeForTest { + return AVLTreeForTest(AVLVertex('b', '+'), 1L) // init tree by root and size (don't use put) + } + + @Test + fun `tree is empty after root of 'size 1' tree was deleted `() { + val tree = makeSize1Tree() + tree.remove('b') + assert(tree.getVertexesInDFSOrder().isEmpty()) + } + + @Test + fun `size equals 0 after root of 'size 1' tree was deleted`() { + val tree = makeSize1Tree() + tree.remove('b') + assert(tree.size() == 0L) + } + + @Test + fun `remove fun return null if entry's key isn't exists(1)`() { + val tree = makeSize1Tree() + assert(tree.remove('a') == null) + } + + @Test + fun `tree has no changes after deletion by non existed larger key`() { + val tree = makeSize1Tree() + tree.remove('c') + assert(tree.size() == 1L) + assert(tree.getRootT()?.value == '+') + } + + @Test + fun `tree has no changes after deletion by non existed lesser key`() { + val tree = makeSize1Tree() + tree.remove('a') + assert(tree.size() == 1L) + assert(tree.getRootT()?.value == '+') + } + + private fun makeTreeForRemoveLeafWithoutBalancingTest(): AVLTreeForTest { + return AVLTreeForTest(AVLVertex('r', "r", AVLVertex('n', "n"), AVLVertex('z', "z")), 3L) + } + + @Test + fun `right leaf deleted after remove with one's key was called`() { + val tree = makeTreeForRemoveLeafWithoutBalancingTest() + tree.remove('z') + val root = tree.getRootT() + if (root != null) { + assert(root.rightSon == null) + } else { + assert(false) + } + } + + @Test + fun `left leaf deleted after remove with one's key was called`() { + val tree = makeTreeForRemoveLeafWithoutBalancingTest() + tree.remove('n') + val root = tree.getRootT() + if (root != null) { + assert(root.leftSon == null) + } else { + assert(false) + } + } + + @Test + fun `remove by right leaf's key return due value`() { + val tree = makeTreeForRemoveLeafWithoutBalancingTest() + assert(tree.remove('z') == "z") + } + + @Test + fun `remove by left leaf's key return due value`() { + val tree = makeTreeForRemoveLeafWithoutBalancingTest() + assert(tree.remove('n') == "n") + } + + @Test + fun `vertex's sonsHeightDiff increased by 1 after one's right leaf was deleted`() { + val tree = makeTreeForRemoveLeafWithoutBalancingTest() + tree.remove('z') + val root = tree.getRootT() + assert(root?.sonsHeightDiff == 1) + } + + @Test + fun `vertex's sonsHeightDiff decreased by 1 after one's left leaf was deleted`() { + val tree = makeTreeForRemoveLeafWithoutBalancingTest() + tree.remove('n') + val root = tree.getRootT() + assert(root?.sonsHeightDiff == -1) + } + + @Test + fun `size decreased by 1 after right leaf was deleted`() { + val tree = makeTreeForRemoveLeafWithoutBalancingTest() + tree.remove('z') + assert(tree.size() == 2L) + } + + @Test + fun `size decreased by 1 after left leaf was deleted`() { + val tree = makeTreeForRemoveLeafWithoutBalancingTest() + tree.remove('n') + assert(tree.size() == 2L) + } + + private fun makeTreeForRemoveLeftSonWithOnlyLeftSonTest(): AVLTreeForTest { + val leftSon = AVLVertex('q', 9, AVLVertex('o', 0), null, 1) + val root = AVLVertex('s', 5, leftSon, AVLVertex('z', 2), 1) + return AVLTreeForTest(root, 4L) + } + + @Test + fun `remove be key of left son with only left son returns due value`() { + val tree = makeTreeForRemoveLeftSonWithOnlyRightSonTest() + assert(tree.remove('q') == 9) + } + + @Test + fun `content is correct after removed left son with only left son`() { + val tree = makeTreeForRemoveLeftSonWithOnlyLeftSonTest() + tree.remove('q') + assert(isTreeConsistsOf(setOf('o' to 0, 's' to 5, 'z' to 2), tree)) + } + + @Test + fun `size decreased by 1 after left son with only left son was deleted`() { + val tree = makeTreeForRemoveLeftSonWithOnlyLeftSonTest() + tree.remove('q') + assert(tree.size() == 3L) + } + + @Test + fun `structure is correct after left son with only left son was deleted`() { + val tree = makeTreeForRemoveLeftSonWithOnlyLeftSonTest() + tree.remove('q') + assert(isTreeSStructureThat(tree, arrayOf('s', 'o', 'z'), listOf(Triple(0, 1, 2)))) + } + + @Test + fun `sonsHeightDiff values are correct after LSon with only LSon was deleted`() { + val tree = makeTreeForRemoveLeftSonWithOnlyLeftSonTest() + tree.remove('q') + assert(isSonsHeightDiffCorrect(tree)) + } + + private fun makeTreeForRemoveLeftSonWithOnlyRightSonTest(): AVLTreeForTest { + val leftSon = AVLVertex('q', 9, null, AVLVertex('r', 7), -1) + val root = AVLVertex('s', 5, leftSon, AVLVertex('z', 2), 1) + return AVLTreeForTest(root, 4L) + } + + @Test + fun `remove by key of left son with only right son returns due value`() { + val tree = makeTreeForRemoveLeftSonWithOnlyRightSonTest() + assert(tree.remove('q') == 9) + } + + @Test + fun `content is correct after left son with only right son was deleted`() { + val tree = makeTreeForRemoveLeftSonWithOnlyRightSonTest() + tree.remove('q') + assert(isTreeConsistsOf(setOf('r' to 7, 's' to 5, 'z' to 2), tree)) + } + + @Test + fun `size decreased by 1 after left son with only right son was deleted`() { + val tree = makeTreeForRemoveLeftSonWithOnlyRightSonTest() + tree.remove('q') + assert(tree.size() == 3L) + } + + @Test + fun `structure is correct after left son with only right son was deleted`() { + val tree = makeTreeForRemoveLeftSonWithOnlyRightSonTest() + tree.remove('q') + assert(isTreeSStructureThat(tree, arrayOf('s', 'r', 'z'), listOf(Triple(0, 1, 2)))) + } + + @Test + fun `sonsHeightDiff values are correct after LSon with only RSon was deleted`() { + val tree = makeTreeForRemoveLeftSonWithOnlyRightSonTest() + tree.remove('q') + assert(isSonsHeightDiffCorrect(tree)) + } + + private fun makeTreeForRemoveRightSonWithOnlyLeftSonTest(): AVLTreeForTest { + val rightSon = AVLVertex('q', 9, AVLVertex('o', 0), null, 1) + val root = AVLVertex('i', 1, AVLVertex('b', 6), rightSon, -1) + return AVLTreeForTest(root, 4L) + } + + @Test + fun `remove by key of right son with only left son returns due value`() { + val tree = makeTreeForRemoveRightSonWithOnlyLeftSonTest() + assert(tree.remove('q') == 9) + } + + @Test + fun `content is correct after right son with only left son was deleted`() { + val tree = makeTreeForRemoveRightSonWithOnlyLeftSonTest() + tree.remove('q') + assert(isTreeConsistsOf(setOf('o' to 0, 'b' to 6, 'i' to 1), tree)) + } + + @Test + fun `size decreased by 1 after right son with only left son was deleted`() { + val tree = makeTreeForRemoveRightSonWithOnlyLeftSonTest() + tree.remove('q') + assert(tree.size() == 3L) + } + + @Test + fun `structure is correct after right son with only left son was deleted`() { + val tree = makeTreeForRemoveRightSonWithOnlyLeftSonTest() + tree.remove('q') + assert(isTreeSStructureThat(tree, arrayOf('i', 'b', 'o'), listOf(Triple(0, 1, 2)))) + } + + @Test + fun `sonsHeightDiff values are correct after RSon with only LSon was deleted`() { + val tree = makeTreeForRemoveRightSonWithOnlyLeftSonTest() + tree.remove('q') + assert(isSonsHeightDiffCorrect(tree)) + } + + private fun makeTreeForRemoveRightSonWithOnlyRightSonTest(): AVLTreeForTest { + val rightSon = AVLVertex('q', 9, null, AVLVertex('r', 7), -1) + val root = AVLVertex('i', 1, AVLVertex('b', 6), rightSon, -1) + return AVLTreeForTest(root, 4L) + } + + @Test + fun `remove by key of right son with only right son returns due value`() { + val tree = makeTreeForRemoveRightSonWithOnlyRightSonTest() + assert(tree.remove('q') == 9) + } + + @Test + fun `content is correct after right son with only right son was deleted`() { + val tree = makeTreeForRemoveRightSonWithOnlyRightSonTest() + tree.remove('q') + assert(isTreeConsistsOf(setOf('r' to 7, 'b' to 6, 'i' to 1), tree)) + } + + @Test + fun `size decreased by 1 after right son with only right son was deleted`() { + val tree = makeTreeForRemoveRightSonWithOnlyRightSonTest() + tree.remove('q') + assert(tree.size() == 3L) + } + + @Test + fun `structure is correct after right son with only right son was deleted`() { + val tree = makeTreeForRemoveRightSonWithOnlyRightSonTest() + tree.remove('q') + assert(isTreeSStructureThat(tree, arrayOf('i', 'b', 'r'), listOf(Triple(0, 1, 2)))) + } + + @Test + fun `sonsHeightDiff values are correct after RSon with only RSon was deleted`() { + val tree = makeTreeForRemoveRightSonWithOnlyRightSonTest() + tree.remove('q') + assert(isSonsHeightDiffCorrect(tree)) + } + + private fun makeTreeForRemoveRootWithOnlyLeftSon(): AVLTreeForTest { + return AVLTreeForTest(AVLVertex("be", "es", (AVLVertex("and", "et")), null, 1), 2L) + } + + @Test + fun `remove by key of root with only left son returns due value`() { + val tree = makeTreeForRemoveRootWithOnlyLeftSon() + assert(tree.remove("be") == "es") + } + + @Test + fun `content is correct after root with only left son was deleted`() { + val tree = makeTreeForRemoveRootWithOnlyLeftSon() + tree.remove("be") + assert(isTreeConsistsOf(setOf("and" to "et"), tree)) + } + + @Test + fun `sonsHeightDiff values are correct after root with only LSon was deleted`() { + val tree = makeTreeForRemoveRootWithOnlyLeftSon() + tree.remove("and") + assert(isSonsHeightDiffCorrect(tree)) + } + + private fun makeTreeForRemoveRootWithOnlyRightSon(): AVLTreeForTest { + return AVLTreeForTest(AVLVertex("and", "et", null, (AVLVertex("be", "es")), -1), 2L) + } + + @Test + fun `remove by key of root with only right son returns due value`() { + val tree = makeTreeForRemoveRootWithOnlyRightSon() + assert(tree.remove("and") == "et") + } + + @Test + fun `content is correct after root with only right son was deleted`() { + val tree = makeTreeForRemoveRootWithOnlyRightSon() + tree.remove("and") + assert(isTreeConsistsOf(setOf("be" to "es"), tree)) + } + + @Test + fun `sonsHeightDiff values are correct after root with only RSon was deleted`() { + val tree = makeTreeForRemoveRootWithOnlyRightSon() + tree.remove("and") + assert(isSonsHeightDiffCorrect(tree)) + } +} diff --git a/lib/src/test/kotlin/trees/avlTree/removeTest/withoutBalancing/VertexHadTwoSons.kt b/lib/src/test/kotlin/trees/avlTree/removeTest/withoutBalancing/VertexHadTwoSons.kt new file mode 100644 index 0000000..e793753 --- /dev/null +++ b/lib/src/test/kotlin/trees/avlTree/removeTest/withoutBalancing/VertexHadTwoSons.kt @@ -0,0 +1,189 @@ +package trees.avlTree.removeTest.withoutBalancing + +import org.junit.jupiter.api.Test +import trees.avlTree.AVLTreeForTest +import trees.avlTree.AuxiliaryFunctions.isSonsHeightDiffCorrect +import trees.avlTree.AuxiliaryFunctions.isTreeConsistsOf +import trees.avlTree.AuxiliaryFunctions.isTreeSStructureThat +import vertexes.AVLVertex + +class VertexHadTwoSons { + private fun makeTreeForRemoveSonWithBothSons(): AVLTreeForTest { + val eVrt = AVLVertex('e', 'E', AVLVertex('c', 'C'), null, 1) + val bVrt = AVLVertex('b', 'B', AVLVertex('a', 'A'), eVrt, -1) + val leftSon = AVLVertex('f', 'F', bVrt, AVLVertex('i', 'I', null, AVLVertex('k', 'K'), -1), 1) + val qVrt = AVLVertex('q', 'Q', null, AVLVertex('s', 'S'), -1) + val wVrt = AVLVertex('w', 'W', null, AVLVertex('z', 'Z'), -1) + val root = AVLVertex('n', 'N', leftSon, AVLVertex('u', 'U', qVrt, wVrt, 0), 1) + return AVLTreeForTest(root, 13L) + } + + @Test + fun `remove by key of left son with both sons returns due value`() { + val tree = makeTreeForRemoveSonWithBothSons() + assert(tree.remove('f') == 'F') + } + + @Test + fun `content is correct after left son with both sons was deleted`() { + val tree = makeTreeForRemoveSonWithBothSons() + tree.remove('f') + val expectedContent = + setOf( + 'a' to 'A', + 'b' to 'B', + 'c' to 'C', + 'e' to 'E', + 'i' to 'I', + 'z' to 'Z', + 'k' to 'K', + 'n' to 'N', + 'u' to 'U', + 'q' to 'Q', + 's' to 'S', + 'w' to 'W', + ) + assert(isTreeConsistsOf(expectedContent, tree)) + } + + @Test + fun `size decreased by 1 after left son with both sons was deleted`() { + val tree = makeTreeForRemoveSonWithBothSons() + tree.remove('f') + assert(tree.size() == 12L) + } + + @Test + fun `structure is correct after left son with both sons was deleted`() { + val tree = makeTreeForRemoveSonWithBothSons() + tree.remove('f') + val expectedDependencies = + listOf( + Triple(0, 1, 7), + Triple(1, 2, 5), + Triple(2, 3, 4), + Triple(5, null, 6), + Triple(7, 8, 10), + Triple(10, null, 11), + ) + val expectedOrder = arrayOf('n', 'e', 'b', 'a', 'c', 'i', 'k', 'u', 'q', 's', 'w', 'z') + assert(isTreeSStructureThat(tree, expectedOrder, expectedDependencies)) + } + + @Test + fun `sonsHeightDiff values are correct after LSon with both sons was deleted`() { + val tree = makeTreeForRemoveSonWithBothSons() + tree.remove('f') + assert(isSonsHeightDiffCorrect(tree)) + } + + @Test + fun `remove by key of right son with both sons returns due value`() { + val tree = makeTreeForRemoveSonWithBothSons() + assert(tree.remove('u') == 'U') + } + + @Test + fun `content is correct after right son with both sons was deleted`() { + val tree = makeTreeForRemoveSonWithBothSons() + tree.remove('u') + val expectedContent = + setOf( + 'a' to 'A', + 'b' to 'B', + 'c' to 'C', + 'e' to 'E', + 'i' to 'I', + 'z' to 'Z', + 'k' to 'K', + 'n' to 'N', + 'f' to 'F', + 'q' to 'Q', + 's' to 'S', + 'w' to 'W', + ) + assert(isTreeConsistsOf(expectedContent, tree)) + } + + @Test + fun `size decreased by 1 after right son with both sons was deleted`() { + val tree = makeTreeForRemoveSonWithBothSons() + tree.remove('u') + assert(tree.size() == 12L) + } + + @Test + fun `structure is correct after right son with both sons was deleted`() { + val tree = makeTreeForRemoveSonWithBothSons() + tree.remove('u') + val expectedDependencies = + listOf( + Triple(0, 1, 8), + Triple(1, 2, 6), + Triple(2, 3, 4), + Triple(6, null, 7), + Triple(4, 5, null), + Triple(8, 9, 10), + Triple(10, null, 11), + ) + val expectedOrder = arrayOf('n', 'f', 'b', 'a', 'e', 'c', 'i', 'k', 's', 'q', 'w', 'z') + assert(isTreeSStructureThat(tree, expectedOrder, expectedDependencies)) + } + + @Test + fun `sonsHeightDiff values are correct after RSon with both sons was deleted`() { + val tree = makeTreeForRemoveSonWithBothSons() + tree.remove('u') + assert(isSonsHeightDiffCorrect(tree)) + } + + @Test + fun `remove fun return null if entry's key isn't exists(2)`() { + val tree = makeTreeForRemoveSonWithBothSons() + assert(tree.remove('x') == null) + } + + private fun makeTreeForRemoveRootWithBothSonsTest(): AVLTreeForTest { + val leftSon = AVLVertex('b', 2, AVLVertex('a', 1), AVLVertex('e', 5), 0) + val rightSon = AVLVertex('i', 9, null, AVLVertex('k', 11), -1) + val root = AVLVertex('f', 6, leftSon, rightSon, 0) + return AVLTreeForTest(root, 6L) + } + + @Test + fun `remove by key of root with both sons returns due value`() { + val tree = makeTreeForRemoveRootWithBothSonsTest() + assert(tree.remove('f') == 6) + } + + @Test + fun `content is correct after root with both sons was deleted`() { + val tree = makeTreeForRemoveRootWithBothSonsTest() + tree.remove('f') + val expectedContent = setOf('a' to 1, 'b' to 2, 'e' to 5, 'i' to 9, 'k' to 11) + assert(isTreeConsistsOf(expectedContent, tree)) + } + + @Test + fun `size decreased by 1 after root with both sons was deleted`() { + val tree = makeTreeForRemoveRootWithBothSonsTest() + tree.remove('f') + assert(tree.size() == 5L) + } + + @Test + fun `structure is correct after root with both sons was deleted`() { + val tree = makeTreeForRemoveRootWithBothSonsTest() + tree.remove('f') + val expectedDependencies = listOf(Triple(0, 1, 3), Triple(1, 2, null), Triple(3, null, 4)) + val expectedOrder = arrayOf('e', 'b', 'a', 'i', 'k') + assert(isTreeSStructureThat(tree, expectedOrder, expectedDependencies)) + } + + @Test + fun `sonsHeightDiff values are correct after root with both sons was deleted`() { + val tree = makeTreeForRemoveRootWithBothSonsTest() + tree.remove('f') + assert(isSonsHeightDiffCorrect(tree)) + } +} diff --git a/lib/src/test/kotlin/trees/rbTree/RBSearchTreeTest.kt b/lib/src/test/kotlin/trees/rbTree/RBSearchTreeTest.kt index 3fdde9c..cd3b5a0 100644 --- a/lib/src/test/kotlin/trees/rbTree/RBSearchTreeTest.kt +++ b/lib/src/test/kotlin/trees/rbTree/RBSearchTreeTest.kt @@ -1,9 +1,9 @@ package trees.rbTree -import main.trees.RBSearchTree import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test +import trees.RBSearchTree import kotlin.test.assertEquals class RBSearchTreeTest { diff --git a/lib/src/test/kotlin/trees/simpleBSTree/SimpleBSTreeTest.kt b/lib/src/test/kotlin/trees/simpleBSTree/SimpleBSTForTest.kt similarity index 96% rename from lib/src/test/kotlin/trees/simpleBSTree/SimpleBSTreeTest.kt rename to lib/src/test/kotlin/trees/simpleBSTree/SimpleBSTForTest.kt index 47a9e24..2161bc6 100644 --- a/lib/src/test/kotlin/trees/simpleBSTree/SimpleBSTreeTest.kt +++ b/lib/src/test/kotlin/trees/simpleBSTree/SimpleBSTForTest.kt @@ -4,7 +4,7 @@ import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import kotlin.test.assertEquals -class SimpleBSTreeTest { +class SimpleBSTForTest { private lateinit var tree: TestSimpleBST @BeforeEach @@ -173,8 +173,6 @@ class SimpleBSTreeTest { // 5 // ^ // 0 null -// ^ -// null null val returned = tree.remove(5) assertEquals("zero", tree.getTreeRoot()?.value) @@ -189,8 +187,6 @@ class SimpleBSTreeTest { // 5 // ^ // null 6 -// ^ -// null null val returned = tree.remove(5) assertEquals("six", tree.getTreeRoot()?.value) @@ -205,8 +201,6 @@ class SimpleBSTreeTest { // 5 // ^ // 0 null -// ^ -// null null val returned = tree.remove(0) assertEquals("five", tree.getTreeRoot()?.value) @@ -220,8 +214,8 @@ class SimpleBSTreeTest { mapOf( Pair(5, "five"), Pair(0, "zero"), - Pair(4, "four") - ) + Pair(4, "four"), + ), ) // 5 @@ -243,8 +237,8 @@ class SimpleBSTreeTest { mapOf( Pair(5, "five"), Pair(0, "zero"), - Pair(-1, "minus_one") - ) + Pair(-1, "minus_one"), + ), ) // 5 @@ -268,8 +262,8 @@ class SimpleBSTreeTest { Pair(0, "zero"), Pair(-1, "minus_one"), Pair(4, "four"), - Pair(3, "three") - ) + Pair(3, "three"), + ), ) // 5 @@ -343,8 +337,8 @@ class SimpleBSTreeTest { Pair(5, "five"), Pair(10, "ten"), Pair(2, "two"), - Pair(6, "six") - ) + Pair(6, "six"), + ), ) // 1 diff --git a/lib/src/test/kotlin/trees/simpleBSTree/TestSimpleBST.kt b/lib/src/test/kotlin/trees/simpleBSTree/TestSimpleBST.kt index b80da47..249accb 100644 --- a/lib/src/test/kotlin/trees/simpleBSTree/TestSimpleBST.kt +++ b/lib/src/test/kotlin/trees/simpleBSTree/TestSimpleBST.kt @@ -1,7 +1,7 @@ package trees.simpleBSTree -import main.trees.SimpleBinarySearchTree -import main.vertexes.SimpleBSTVertex +import trees.SimpleBinarySearchTree +import vertexes.SimpleBSTVertex class TestSimpleBST : SimpleBinarySearchTree { fun getTreeRoot(): SimpleBSTVertex? {