From df239d18e5799a9990d0100de07a29394ab33a9f Mon Sep 17 00:00:00 2001 From: "github-classroom[bot]" <66690702+github-classroom[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 09:34:13 +0000 Subject: [PATCH 001/130] Setting up GitHub Classroom Feedback From 780db6111b21b6ef049eef71503a229dbeb73d55 Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Thu, 21 Mar 2024 21:23:53 +0300 Subject: [PATCH 002/130] struct: gradle init --- .gitattributes | 9 + .gitignore | 5 + gradle/libs.versions.toml | 15 ++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 43462 bytes gradle/wrapper/gradle-wrapper.properties | 7 + gradlew | 249 ++++++++++++++++++ gradlew.bat | 92 +++++++ lib/build.gradle.kts | 47 ++++ lib/src/main/kotlin/org/example/Library.kt | 10 + .../test/kotlin/org/example/LibraryTest.kt | 14 + settings.gradle.kts | 14 + 11 files changed, 462 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 gradle/libs.versions.toml create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 lib/build.gradle.kts create mode 100644 lib/src/main/kotlin/org/example/Library.kt create mode 100644 lib/src/test/kotlin/org/example/LibraryTest.kt create mode 100644 settings.gradle.kts diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..097f9f9 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,9 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# Linux start script should use lf +/gradlew text eol=lf + +# These are Windows script files and should use crlf +*.bat text eol=crlf + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1b6985c --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore Gradle build output directory +build diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..d4d7e1f --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,15 @@ +# This file was generated by the Gradle 'init' task. +# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format + +[versions] +commons-math3 = "3.6.1" +guava = "32.1.3-jre" +junit-jupiter-engine = "5.10.0" + +[libraries] +commons-math3 = { module = "org.apache.commons:commons-math3", version.ref = "commons-math3" } +guava = { module = "com.google.guava:guava", version.ref = "guava" } +junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit-jupiter-engine" } + +[plugins] +jvm = { id = "org.jetbrains.kotlin.jvm", version = "1.9.20" } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..d64cd4917707c1f8861d8cb53dd15194d4248596 GIT binary patch literal 43462 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 literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..a80b22c --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..1aa94a4 --- /dev/null +++ b/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..25da30d --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts new file mode 100644 index 0000000..6e8f86e --- /dev/null +++ b/lib/build.gradle.kts @@ -0,0 +1,47 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * This generated file contains a sample Kotlin library project to get you started. + * For more details on building Java & JVM projects, please refer to https://docs.gradle.org/8.6/userguide/building_java_projects.html in the Gradle documentation. + */ + +plugins { + // Apply the org.jetbrains.kotlin.jvm Plugin to add support for Kotlin. + alias(libs.plugins.jvm) + + // Apply the java-library plugin for API and implementation separation. + `java-library` +} + +repositories { + // Use Maven Central for resolving dependencies. + mavenCentral() +} + +dependencies { + // Use the Kotlin JUnit 5 integration. + testImplementation("org.jetbrains.kotlin:kotlin-test-junit5") + + // Use the JUnit 5 integration. + testImplementation(libs.junit.jupiter.engine) + + testRuntimeOnly("org.junit.platform:junit-platform-launcher") + + // This dependency is exported to consumers, that is to say found on their compile classpath. + api(libs.commons.math3) + + // This dependency is used internally, and not exposed to consumers on their own compile classpath. + implementation(libs.guava) +} + +// Apply a specific Java toolchain to ease working on different environments. +java { + toolchain { + languageVersion = JavaLanguageVersion.of(11) + } +} + +tasks.named("test") { + // Use JUnit Platform for unit tests. + useJUnitPlatform() +} diff --git a/lib/src/main/kotlin/org/example/Library.kt b/lib/src/main/kotlin/org/example/Library.kt new file mode 100644 index 0000000..628e156 --- /dev/null +++ b/lib/src/main/kotlin/org/example/Library.kt @@ -0,0 +1,10 @@ +/* + * This Kotlin source file was generated by the Gradle 'init' task. + */ +package org.example + +class Library { + fun someLibraryMethod(): Boolean { + return true + } +} diff --git a/lib/src/test/kotlin/org/example/LibraryTest.kt b/lib/src/test/kotlin/org/example/LibraryTest.kt new file mode 100644 index 0000000..f6fa692 --- /dev/null +++ b/lib/src/test/kotlin/org/example/LibraryTest.kt @@ -0,0 +1,14 @@ +/* + * This Kotlin source file was generated by the Gradle 'init' task. + */ +package org.example + +import kotlin.test.Test +import kotlin.test.assertTrue + +class LibraryTest { + @Test fun someLibraryMethodReturnsTrue() { + val classUnderTest = Library() + assertTrue(classUnderTest.someLibraryMethod(), "someLibraryMethod should return 'true'") + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..0b90193 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,14 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * The settings file is used to specify which projects to include in your build. + * For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.6/userguide/multi_project_builds.html in the Gradle documentation. + */ + +plugins { + // Apply the foojay-resolver plugin to allow automatic download of JDKs + id("org.gradle.toolchains.foojay-resolver-convention") version "0.7.0" +} + +rootProject.name = "trees-3" +include("lib") From 24c34c5eb641dd0524718fbc497e71a87e53a1a2 Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Thu, 21 Mar 2024 22:15:13 +0000 Subject: [PATCH 003/130] struct: update .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 1b6985c..54a5f5d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ # Ignore Gradle build output directory build + +.idea \ No newline at end of file From 6b4f63ff63ab824f99a60e1e0a5603b4aa1a117c Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Thu, 21 Mar 2024 22:42:59 +0000 Subject: [PATCH 004/130] struct: get initial structure of files --- lib/src/main/kotlin/Main.kt | 5 +++++ lib/src/main/kotlin/org/example/Library.kt | 10 ---------- lib/src/main/kotlin/tree/AVLTree.kt | 4 ++++ lib/src/main/kotlin/tree/BSTree.kt | 4 ++++ lib/src/main/kotlin/tree/RBTree.kt | 5 +++++ lib/src/main/kotlin/tree/SearchTree.kt | 4 ++++ lib/src/main/kotlin/tree/node/AVLTreeNode.kt | 4 ++++ lib/src/main/kotlin/tree/node/BSTreeNode.kt | 4 ++++ lib/src/main/kotlin/tree/node/BinaryTreeNode.kt | 4 ++++ lib/src/main/kotlin/tree/node/RBTreeNode.kt | 4 ++++ lib/src/test/kotlin/org/example/LibraryTest.kt | 14 -------------- 11 files changed, 38 insertions(+), 24 deletions(-) create mode 100644 lib/src/main/kotlin/Main.kt delete mode 100644 lib/src/main/kotlin/org/example/Library.kt create mode 100644 lib/src/main/kotlin/tree/AVLTree.kt create mode 100644 lib/src/main/kotlin/tree/BSTree.kt create mode 100644 lib/src/main/kotlin/tree/RBTree.kt create mode 100644 lib/src/main/kotlin/tree/SearchTree.kt create mode 100644 lib/src/main/kotlin/tree/node/AVLTreeNode.kt create mode 100644 lib/src/main/kotlin/tree/node/BSTreeNode.kt create mode 100644 lib/src/main/kotlin/tree/node/BinaryTreeNode.kt create mode 100644 lib/src/main/kotlin/tree/node/RBTreeNode.kt delete mode 100644 lib/src/test/kotlin/org/example/LibraryTest.kt diff --git a/lib/src/main/kotlin/Main.kt b/lib/src/main/kotlin/Main.kt new file mode 100644 index 0000000..54d3674 --- /dev/null +++ b/lib/src/main/kotlin/Main.kt @@ -0,0 +1,5 @@ +import tree.node.BinaryTreeNode + +fun main() { + println("Hello world!") +} \ No newline at end of file diff --git a/lib/src/main/kotlin/org/example/Library.kt b/lib/src/main/kotlin/org/example/Library.kt deleted file mode 100644 index 628e156..0000000 --- a/lib/src/main/kotlin/org/example/Library.kt +++ /dev/null @@ -1,10 +0,0 @@ -/* - * This Kotlin source file was generated by the Gradle 'init' task. - */ -package org.example - -class Library { - fun someLibraryMethod(): Boolean { - return true - } -} diff --git a/lib/src/main/kotlin/tree/AVLTree.kt b/lib/src/main/kotlin/tree/AVLTree.kt new file mode 100644 index 0000000..deb74b1 --- /dev/null +++ b/lib/src/main/kotlin/tree/AVLTree.kt @@ -0,0 +1,4 @@ +package tree + +class AVLTree { +} \ No newline at end of file diff --git a/lib/src/main/kotlin/tree/BSTree.kt b/lib/src/main/kotlin/tree/BSTree.kt new file mode 100644 index 0000000..09b35a8 --- /dev/null +++ b/lib/src/main/kotlin/tree/BSTree.kt @@ -0,0 +1,4 @@ +package tree + +class BSTree { +} \ No newline at end of file diff --git a/lib/src/main/kotlin/tree/RBTree.kt b/lib/src/main/kotlin/tree/RBTree.kt new file mode 100644 index 0000000..ea2e7c6 --- /dev/null +++ b/lib/src/main/kotlin/tree/RBTree.kt @@ -0,0 +1,5 @@ +package tree + +class RBTree { + +} \ No newline at end of file diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt new file mode 100644 index 0000000..ce793e6 --- /dev/null +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -0,0 +1,4 @@ +package tree + +abstract class SearchTree { +} \ No newline at end of file diff --git a/lib/src/main/kotlin/tree/node/AVLTreeNode.kt b/lib/src/main/kotlin/tree/node/AVLTreeNode.kt new file mode 100644 index 0000000..dfaafd1 --- /dev/null +++ b/lib/src/main/kotlin/tree/node/AVLTreeNode.kt @@ -0,0 +1,4 @@ +package tree.node + +internal class AVLTreeNode { +} \ No newline at end of file diff --git a/lib/src/main/kotlin/tree/node/BSTreeNode.kt b/lib/src/main/kotlin/tree/node/BSTreeNode.kt new file mode 100644 index 0000000..fe8b9f7 --- /dev/null +++ b/lib/src/main/kotlin/tree/node/BSTreeNode.kt @@ -0,0 +1,4 @@ +package tree.node + +internal class BSTreeNode { +} \ No newline at end of file diff --git a/lib/src/main/kotlin/tree/node/BinaryTreeNode.kt b/lib/src/main/kotlin/tree/node/BinaryTreeNode.kt new file mode 100644 index 0000000..92a0f28 --- /dev/null +++ b/lib/src/main/kotlin/tree/node/BinaryTreeNode.kt @@ -0,0 +1,4 @@ +package tree.node + +internal abstract class BinaryTreeNode { +} \ No newline at end of file diff --git a/lib/src/main/kotlin/tree/node/RBTreeNode.kt b/lib/src/main/kotlin/tree/node/RBTreeNode.kt new file mode 100644 index 0000000..94910c6 --- /dev/null +++ b/lib/src/main/kotlin/tree/node/RBTreeNode.kt @@ -0,0 +1,4 @@ +package tree.node + +internal class RBTreeNode { +} \ No newline at end of file diff --git a/lib/src/test/kotlin/org/example/LibraryTest.kt b/lib/src/test/kotlin/org/example/LibraryTest.kt deleted file mode 100644 index f6fa692..0000000 --- a/lib/src/test/kotlin/org/example/LibraryTest.kt +++ /dev/null @@ -1,14 +0,0 @@ -/* - * This Kotlin source file was generated by the Gradle 'init' task. - */ -package org.example - -import kotlin.test.Test -import kotlin.test.assertTrue - -class LibraryTest { - @Test fun someLibraryMethodReturnsTrue() { - val classUnderTest = Library() - assertTrue(classUnderTest.someLibraryMethod(), "someLibraryMethod should return 'true'") - } -} From d4559217cbd8051e6f507e3c186b201ffe120e2f Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Thu, 21 Mar 2024 22:47:04 +0000 Subject: [PATCH 005/130] struct: add license --- LICENSE | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b3b1854 --- /dev/null +++ b/LICENSE @@ -0,0 +1,7 @@ +Copyright 2024 Dmitry Sheiko, Anastasiia Kuzmina, Ilhom Kombaev + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. From 523f8ba8462782aef4d4d13d4d5429f1c647061f Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Sat, 23 Mar 2024 19:53:11 +0300 Subject: [PATCH 006/130] feat: created an abstract node class --- lib/src/main/kotlin/tree/node/BinaryTreeNode.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/src/main/kotlin/tree/node/BinaryTreeNode.kt b/lib/src/main/kotlin/tree/node/BinaryTreeNode.kt index 92a0f28..fe7af4e 100644 --- a/lib/src/main/kotlin/tree/node/BinaryTreeNode.kt +++ b/lib/src/main/kotlin/tree/node/BinaryTreeNode.kt @@ -1,4 +1,8 @@ package tree.node -internal abstract class BinaryTreeNode { -} \ No newline at end of file +abstract class BinaryTreeNode, V, Node>( + val key: K, + var value: V, + var right: Node? = null, + var left: Node? = null +) \ No newline at end of file From 4a3b0599600c5ea014eb777cbe3390a54ba0cfb6 Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Sun, 24 Mar 2024 01:51:39 +0300 Subject: [PATCH 007/130] feat: created an abstract search tree class --- lib/src/main/kotlin/tree/SearchTree.kt | 85 +++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 2 deletions(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index ce793e6..78f6cfe 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -1,4 +1,85 @@ package tree -abstract class SearchTree { -} \ No newline at end of file +import tree.node.BinaryTreeNode + +abstract class SearchTree, V, Node: BinaryTreeNode> () + { + protected var root: Node? = null + var size: Long = 0 + private set + var recentlyKey: K? = null + private set + constructor(key: K, value:V): this(){ + set(key, value) + } + constructor(pairs: Array>): this(){ + set(pairs) + } + protected fun insertNode(node: Node){ + TODO("Insert node to tree") + } + protected fun removeNode(node: Node){ + TODO("Remove node in tree") + } + protected fun createNode(key: K, value: V): Node{ + TODO("Creating a tree node") + } + protected fun searchNode(key: K): Node?{ + TODO("Finding a node in a tree by key") + } + fun set(key: K, value: V): V?{ + TODO("Adding a node in a tree if there is no such node in the tree") + } + fun set(pairs: Array>): Array{ + TODO("Adding multiple node in a tree if there is no such node in the tree") + } + fun setIfEmpty(key: K, value: V): V?{ + TODO("Adding a node if such a node already exists in the tree") + } + fun setIfEmpty(pairs: Array>): Array { + TODO("Adding several nodes if such a node already exists in the tree") + } + fun remove(key: K){ + TODO("Adding multiple nodes if such nodes already exist in the tree") + } + fun remove(keys: Array): Array { + TODO("Removing multiple catches by keys") + } + fun search(key: K){ + TODO("Search by key") + } + fun getKeys(): Array { + TODO("Returns a complete list of keys") + } + fun getValues(): Array { + TODO("Returns a complete list of values") + } + fun getEntities(): Array> { + TODO("Returns a complete list of pair key value") + } + fun getMin(): Pair{ + TODO("Returns nodes with the minimum key") + } + fun getMax(): Pair{ + TODO("Returns nodes with the maximum key") + } + fun successor(key: K): Pair{ + TODO("Returns the next ascending key") + } + fun predeccessor(key: K): Pair{ + TODO("Returns the previous ascending key") + } + fun clear(){ + TODO("Removing all nodes in a tree") + } + fun preOrderTraversal(action: Pair){ + TODO("Prefix tree traversal") + } + fun inOrderTraversal(action: Pair){ + TODO("Symmetrical tree traversal") + } + fun postOrderTraversal(action: Pair){ + TODO("Postfix tree traversal") + } +} + From 95addd4ae2024e1c3076e99ad228d659ce4503a7 Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Sun, 24 Mar 2024 02:20:16 +0300 Subject: [PATCH 008/130] =?UTF-8?q?fix:=20=D1=81orrected=20methods=20inser?= =?UTF-8?q?tNode,=20removeNode,=20createNode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/src/main/kotlin/tree/SearchTree.kt | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index 78f6cfe..4b9ce18 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -15,15 +15,9 @@ abstract class SearchTree, V, Node: BinaryTreeNode> constructor(pairs: Array>): this(){ set(pairs) } - protected fun insertNode(node: Node){ - TODO("Insert node to tree") - } - protected fun removeNode(node: Node){ - TODO("Remove node in tree") - } - protected fun createNode(key: K, value: V): Node{ - TODO("Creating a tree node") - } + protected abstract fun insertNode(node: Node) + protected abstract fun removeNode(node: Node) + protected abstract fun createNode(key: K, value: V): Node protected fun searchNode(key: K): Node?{ TODO("Finding a node in a tree by key") } From b3974495473dc52daf1ab80a3e819e16b330aef5 Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Sun, 24 Mar 2024 02:39:48 +0300 Subject: [PATCH 009/130] feat: created a binary search tree node class --- lib/src/main/kotlin/tree/node/BSTreeNode.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/src/main/kotlin/tree/node/BSTreeNode.kt b/lib/src/main/kotlin/tree/node/BSTreeNode.kt index fe8b9f7..c6aa839 100644 --- a/lib/src/main/kotlin/tree/node/BSTreeNode.kt +++ b/lib/src/main/kotlin/tree/node/BSTreeNode.kt @@ -1,4 +1,3 @@ package tree.node -internal class BSTreeNode { -} \ No newline at end of file +internal class BSTreeNode, V>(key: K, value: V) : BinaryTreeNode>(key, value) \ No newline at end of file From 8ceb96126ea057f1bd0a3a479cf079f918c77f12 Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Sun, 24 Mar 2024 02:45:25 +0300 Subject: [PATCH 010/130] feat: created a AVL-Tree node class --- lib/src/main/kotlin/tree/node/AVLTreeNode.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/main/kotlin/tree/node/AVLTreeNode.kt b/lib/src/main/kotlin/tree/node/AVLTreeNode.kt index dfaafd1..60039d5 100644 --- a/lib/src/main/kotlin/tree/node/AVLTreeNode.kt +++ b/lib/src/main/kotlin/tree/node/AVLTreeNode.kt @@ -1,4 +1,4 @@ package tree.node -internal class AVLTreeNode { -} \ No newline at end of file +internal class AVLTreeNode, V>(var height: Int = 1, key: K, value: V) : + BinaryTreeNode>(key, value) \ No newline at end of file From a2d7ba23f0247f210102cbc54d403aa2059c355b Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Sun, 24 Mar 2024 17:57:48 +0300 Subject: [PATCH 011/130] fix: the order of the AVL-Tree node class attributes has been changed --- lib/src/main/kotlin/tree/node/AVLTreeNode.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/node/AVLTreeNode.kt b/lib/src/main/kotlin/tree/node/AVLTreeNode.kt index 60039d5..ea6cf25 100644 --- a/lib/src/main/kotlin/tree/node/AVLTreeNode.kt +++ b/lib/src/main/kotlin/tree/node/AVLTreeNode.kt @@ -1,4 +1,4 @@ package tree.node -internal class AVLTreeNode, V>(var height: Int = 1, key: K, value: V) : +internal class AVLTreeNode, V>(key: K, value: V, var height: Int = 1) : BinaryTreeNode>(key, value) \ No newline at end of file From d712b3808ced9ddb8d886446423a134b84ed32c4 Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Sun, 24 Mar 2024 23:50:40 +0300 Subject: [PATCH 012/130] fix: classes AVL, BST and RBT nodes have been corrected --- lib/src/main/kotlin/tree/node/AVLTreeNode.kt | 4 ++-- lib/src/main/kotlin/tree/node/BSTreeNode.kt | 2 +- lib/src/main/kotlin/tree/node/RBTreeNode.kt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/src/main/kotlin/tree/node/AVLTreeNode.kt b/lib/src/main/kotlin/tree/node/AVLTreeNode.kt index ea6cf25..bbd2c26 100644 --- a/lib/src/main/kotlin/tree/node/AVLTreeNode.kt +++ b/lib/src/main/kotlin/tree/node/AVLTreeNode.kt @@ -1,4 +1,4 @@ package tree.node -internal class AVLTreeNode, V>(key: K, value: V, var height: Int = 1) : - BinaryTreeNode>(key, value) \ No newline at end of file +class AVLTreeNode, V>(key: K, value: V, var height: Int = 1) : + BinaryTreeNode>(key, value) \ No newline at end of file diff --git a/lib/src/main/kotlin/tree/node/BSTreeNode.kt b/lib/src/main/kotlin/tree/node/BSTreeNode.kt index c6aa839..47b8fde 100644 --- a/lib/src/main/kotlin/tree/node/BSTreeNode.kt +++ b/lib/src/main/kotlin/tree/node/BSTreeNode.kt @@ -1,3 +1,3 @@ package tree.node -internal class BSTreeNode, V>(key: K, value: V) : BinaryTreeNode>(key, value) \ No newline at end of file +class BSTreeNode, V>(key: K, value: V) : BinaryTreeNode>(key, value) \ No newline at end of file diff --git a/lib/src/main/kotlin/tree/node/RBTreeNode.kt b/lib/src/main/kotlin/tree/node/RBTreeNode.kt index 94910c6..564b30c 100644 --- a/lib/src/main/kotlin/tree/node/RBTreeNode.kt +++ b/lib/src/main/kotlin/tree/node/RBTreeNode.kt @@ -1,4 +1,4 @@ package tree.node -internal class RBTreeNode { +class RBTreeNode { } \ No newline at end of file From a18c27d0e436abe8f2607473b59217c4e069f6bd Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Sun, 24 Mar 2024 23:54:24 +0300 Subject: [PATCH 013/130] =?UTF-8?q?feat:=20=D1=81reated=20a=20binary=20sea?= =?UTF-8?q?rch=20tree=20class?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/src/main/kotlin/tree/BSTree.kt | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/BSTree.kt b/lib/src/main/kotlin/tree/BSTree.kt index 09b35a8..f653b1a 100644 --- a/lib/src/main/kotlin/tree/BSTree.kt +++ b/lib/src/main/kotlin/tree/BSTree.kt @@ -1,4 +1,17 @@ package tree -class BSTree { +import tree.node.BSTreeNode + +class BSTree, V> : SearchTree>() { + override fun insertNode(node: BSTreeNode) { + TODO("Insert node to tree") + } + + override fun removeNode(node: BSTreeNode) { + TODO("Remove node in tree") + } + + override fun createNode(key: K, value: V): BSTreeNode { + TODO("Create a node") + } } \ No newline at end of file From cfdd4cee6ffaabd31910b31cb7b89bfdf6c08b59 Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Mon, 25 Mar 2024 00:02:44 +0300 Subject: [PATCH 014/130] =?UTF-8?q?feat:=20=D1=81reated=20a=20AVL-Tree=20c?= =?UTF-8?q?lass?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/src/main/kotlin/tree/AVLTree.kt | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/AVLTree.kt b/lib/src/main/kotlin/tree/AVLTree.kt index deb74b1..56d2243 100644 --- a/lib/src/main/kotlin/tree/AVLTree.kt +++ b/lib/src/main/kotlin/tree/AVLTree.kt @@ -1,4 +1,17 @@ package tree -class AVLTree { +import tree.node.AVLTreeNode + +class AVLTree, V> : SearchTree>() { + override fun insertNode(node: AVLTreeNode) { + TODO("Insert node to tree") + } + + override fun removeNode(node: AVLTreeNode) { + TODO("Remove node in tree") + } + + override fun createNode(key: K, value: V): AVLTreeNode { + TODO("Create a node") + } } \ No newline at end of file From 74712774f0b2c70f6a99566de9ee8bf6c12e50be Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Mon, 25 Mar 2024 00:32:58 +0300 Subject: [PATCH 015/130] =?UTF-8?q?feat:=20=D1=81reated=20class=20red=20bl?= =?UTF-8?q?ack=20tree=20node?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/src/main/kotlin/tree/node/RBTreeNode.kt | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/src/main/kotlin/tree/node/RBTreeNode.kt b/lib/src/main/kotlin/tree/node/RBTreeNode.kt index 564b30c..969bca9 100644 --- a/lib/src/main/kotlin/tree/node/RBTreeNode.kt +++ b/lib/src/main/kotlin/tree/node/RBTreeNode.kt @@ -1,4 +1,12 @@ package tree.node -class RBTreeNode { -} \ No newline at end of file +enum class RBTreeColor { + BLACK, RED +} + +class RBTreeNode, V>( + key: K, + value: V, + var color: RBTreeColor = RBTreeColor.RED, + var parent: RBTreeNode? = null +) : BinaryTreeNode>(key, value) \ No newline at end of file From d9aefd57dd40b4b5f18cfc43ced9fdc5c37994ed Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Mon, 25 Mar 2024 00:37:22 +0300 Subject: [PATCH 016/130] =?UTF-8?q?feat:=20=D1=81reated=20class=20red=20bl?= =?UTF-8?q?ack=20tree?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/src/main/kotlin/tree/RBTree.kt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/RBTree.kt b/lib/src/main/kotlin/tree/RBTree.kt index ea2e7c6..c451934 100644 --- a/lib/src/main/kotlin/tree/RBTree.kt +++ b/lib/src/main/kotlin/tree/RBTree.kt @@ -1,5 +1,17 @@ package tree -class RBTree { +import tree.node.RBTreeNode +class RBTree, V> : SearchTree>() { + override fun insertNode(node: RBTreeNode) { + TODO("Insert node to tree") + } + + override fun removeNode(node: RBTreeNode) { + TODO("Remove node in tree") + } + + override fun createNode(key: K, value: V): RBTreeNode { + TODO("Create a node") + } } \ No newline at end of file From d077d9b825e00e1b15dbb914807fbd858c37f74f Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Mon, 25 Mar 2024 00:45:18 +0300 Subject: [PATCH 017/130] fix: corrected omissions in serch tree class and formatted code --- lib/src/main/kotlin/tree/SearchTree.kt | 166 ++++++++++++++----------- 1 file changed, 93 insertions(+), 73 deletions(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index 4b9ce18..155b853 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -2,78 +2,98 @@ package tree import tree.node.BinaryTreeNode -abstract class SearchTree, V, Node: BinaryTreeNode> () - { - protected var root: Node? = null - var size: Long = 0 - private set - var recentlyKey: K? = null - private set - constructor(key: K, value:V): this(){ - set(key, value) - } - constructor(pairs: Array>): this(){ - set(pairs) - } - protected abstract fun insertNode(node: Node) - protected abstract fun removeNode(node: Node) - protected abstract fun createNode(key: K, value: V): Node - protected fun searchNode(key: K): Node?{ - TODO("Finding a node in a tree by key") - } - fun set(key: K, value: V): V?{ - TODO("Adding a node in a tree if there is no such node in the tree") - } - fun set(pairs: Array>): Array{ - TODO("Adding multiple node in a tree if there is no such node in the tree") - } - fun setIfEmpty(key: K, value: V): V?{ - TODO("Adding a node if such a node already exists in the tree") - } - fun setIfEmpty(pairs: Array>): Array { - TODO("Adding several nodes if such a node already exists in the tree") - } - fun remove(key: K){ - TODO("Adding multiple nodes if such nodes already exist in the tree") - } - fun remove(keys: Array): Array { - TODO("Removing multiple catches by keys") - } - fun search(key: K){ - TODO("Search by key") - } - fun getKeys(): Array { - TODO("Returns a complete list of keys") - } - fun getValues(): Array { - TODO("Returns a complete list of values") - } - fun getEntities(): Array> { - TODO("Returns a complete list of pair key value") - } - fun getMin(): Pair{ - TODO("Returns nodes with the minimum key") - } - fun getMax(): Pair{ - TODO("Returns nodes with the maximum key") - } - fun successor(key: K): Pair{ - TODO("Returns the next ascending key") - } - fun predeccessor(key: K): Pair{ - TODO("Returns the previous ascending key") - } - fun clear(){ - TODO("Removing all nodes in a tree") - } - fun preOrderTraversal(action: Pair){ - TODO("Prefix tree traversal") - } - fun inOrderTraversal(action: Pair){ - TODO("Symmetrical tree traversal") - } - fun postOrderTraversal(action: Pair){ - TODO("Postfix tree traversal") - } +abstract class SearchTree, V, Node : BinaryTreeNode>() { + protected var root: Node? = null + var size: Long = 0 + private set + var recentlyKey: K? = null + private set + + constructor(key: K, value: V) : this() { + set(key, value) + } + + constructor(pairs: Array>) : this() { + set(pairs) + } + + protected abstract fun insertNode(node: Node) + protected abstract fun removeNode(node: Node) + protected abstract fun createNode(key: K, value: V): Node + protected fun searchNode(key: K): Node? { + TODO("Finding a node in a tree by key") + } + + fun set(key: K, value: V): V? { + TODO("Adding a node in a tree if there is no such node in the tree") + } + + fun set(pairs: Array>): Array { + TODO("Adding multiple node in a tree if there is no such node in the tree") + } + + fun setIfEmpty(key: K, value: V): V? { + TODO("Adding a node if such a node already exists in the tree") + } + + fun setIfEmpty(pairs: Array>): Array { + TODO("Adding several nodes if such a node already exists in the tree") + } + + fun remove(key: K): V? { + TODO("Adding multiple nodes if such nodes already exist in the tree") + } + + fun remove(keys: Array): Array { + TODO("Removing multiple catches by keys") + } + + fun search(key: K): V? { + TODO("Search by key") + } + + fun getKeys(): Array { + TODO("Returns a complete list of keys") + } + + fun getValues(): Array { + TODO("Returns a complete list of values") + } + + fun getEntities(): Array> { + TODO("Returns a complete list of pair key value") + } + + fun getMin(): Pair { + TODO("Returns nodes with the minimum key") + } + + fun getMax(): Pair { + TODO("Returns nodes with the maximum key") + } + + fun successor(key: K): Pair { + TODO("Returns the next ascending key") + } + + fun predeccessor(key: K): Pair { + TODO("Returns the previous ascending key") + } + + fun clear() { + TODO("Removing all nodes in a tree") + } + + fun preOrderTraversal(action: Pair) { + TODO("Prefix tree traversal") + } + + fun inOrderTraversal(action: Pair) { + TODO("Symmetrical tree traversal") + } + + fun postOrderTraversal(action: Pair) { + TODO("Postfix tree traversal") + } } From 5cae8554b51d825b1c2ba38b4d784a406c70bb10 Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Mon, 25 Mar 2024 09:57:51 +0300 Subject: [PATCH 018/130] refactor: move RBTreeColor to seperate file --- lib/src/main/kotlin/tree/node/RBTreeColor.kt | 5 +++++ lib/src/main/kotlin/tree/node/RBTreeNode.kt | 4 ---- 2 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 lib/src/main/kotlin/tree/node/RBTreeColor.kt diff --git a/lib/src/main/kotlin/tree/node/RBTreeColor.kt b/lib/src/main/kotlin/tree/node/RBTreeColor.kt new file mode 100644 index 0000000..a8b0a8d --- /dev/null +++ b/lib/src/main/kotlin/tree/node/RBTreeColor.kt @@ -0,0 +1,5 @@ +package tree.node + +enum class RBTreeColor { + BLACK, RED +} \ No newline at end of file diff --git a/lib/src/main/kotlin/tree/node/RBTreeNode.kt b/lib/src/main/kotlin/tree/node/RBTreeNode.kt index 969bca9..298b67e 100644 --- a/lib/src/main/kotlin/tree/node/RBTreeNode.kt +++ b/lib/src/main/kotlin/tree/node/RBTreeNode.kt @@ -1,9 +1,5 @@ package tree.node -enum class RBTreeColor { - BLACK, RED -} - class RBTreeNode, V>( key: K, value: V, From 8abb345a8f9c58c9fa9f194474eac967538ef748 Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Mon, 25 Mar 2024 10:14:29 +0300 Subject: [PATCH 019/130] refactor: add comments to methods of SearchTree --- lib/src/main/kotlin/tree/SearchTree.kt | 58 ++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index 155b853..71f10a8 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -20,78 +20,136 @@ abstract class SearchTree, V, Node : BinaryTreeNode>): Array { TODO("Adding multiple node in a tree if there is no such node in the tree") } + /** + * Stores the value for the given key if there is no pair with that key. Return previous value. + */ fun setIfEmpty(key: K, value: V): V? { TODO("Adding a node if such a node already exists in the tree") } + /** + * Stores the values for the given keys if there is no pair with that key. Return previous values. + */ fun setIfEmpty(pairs: Array>): Array { TODO("Adding several nodes if such a node already exists in the tree") } + /** + * Remove the value for the given key. Return previous value. + */ fun remove(key: K): V? { TODO("Adding multiple nodes if such nodes already exist in the tree") } + /** + * Remove the values for the given keys. Return previous values. + */ fun remove(keys: Array): Array { TODO("Removing multiple catches by keys") } + /** + * Return the value for the given key. + */ fun search(key: K): V? { TODO("Search by key") } + /** + * Returns a complete list of keys. + */ fun getKeys(): Array { TODO("Returns a complete list of keys") } + /** + * Returns a complete list of values. + */ fun getValues(): Array { TODO("Returns a complete list of values") } + /** + * Returns a complete list of pairs key value. + */ fun getEntities(): Array> { TODO("Returns a complete list of pair key value") } + /** + * Returns pair with the minimum key. + */ fun getMin(): Pair { TODO("Returns nodes with the minimum key") } + /** + * Returns pair with the maximum key. + */ fun getMax(): Pair { TODO("Returns nodes with the maximum key") } + /** + * Returns the pair with next ascending key + */ fun successor(key: K): Pair { TODO("Returns the next ascending key") } + /** + * Returns the pair with previous ascending key + */ fun predeccessor(key: K): Pair { TODO("Returns the previous ascending key") } + /** + * Remove all keys in a tree. + */ fun clear() { TODO("Removing all nodes in a tree") } + /** + * Apply [action] on all pairs by preorder tree traversal. + */ fun preOrderTraversal(action: Pair) { TODO("Prefix tree traversal") } + /** + * Apply [action] on all pairs by inorder tree traversal. + */ fun inOrderTraversal(action: Pair) { TODO("Symmetrical tree traversal") } + /** + * Apply [action] on all pairs by postorder tree traversal. + */ fun postOrderTraversal(action: Pair) { TODO("Postfix tree traversal") } From 85b70bb85d5040389483dd2e25778ff0cc9b00cb Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Mon, 25 Mar 2024 10:15:26 +0300 Subject: [PATCH 020/130] fix: traversal method's argument must be function --- lib/src/main/kotlin/tree/SearchTree.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index 71f10a8..4413e31 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -136,21 +136,21 @@ abstract class SearchTree, V, Node : BinaryTreeNode) { + fun preOrderTraversal(action: (Pair) -> (Unit)) { TODO("Prefix tree traversal") } /** * Apply [action] on all pairs by inorder tree traversal. */ - fun inOrderTraversal(action: Pair) { + fun inOrderTraversal(action: (Pair) -> (Unit)) { TODO("Symmetrical tree traversal") } /** * Apply [action] on all pairs by postorder tree traversal. */ - fun postOrderTraversal(action: Pair) { + fun postOrderTraversal(action: (Pair) -> (Unit)) { TODO("Postfix tree traversal") } } From 0b3bccd750b01d33e42a9158a47816c36c6f2c57 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Wed, 27 Mar 2024 00:27:24 +0300 Subject: [PATCH 021/130] refactor(BST): changed comment to method insertNode --- lib/src/main/kotlin/tree/BSTree.kt | 32 +++++++++++++++--------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/src/main/kotlin/tree/BSTree.kt b/lib/src/main/kotlin/tree/BSTree.kt index f653b1a..b3726eb 100644 --- a/lib/src/main/kotlin/tree/BSTree.kt +++ b/lib/src/main/kotlin/tree/BSTree.kt @@ -1,17 +1,17 @@ -package tree - -import tree.node.BSTreeNode - -class BSTree, V> : SearchTree>() { - override fun insertNode(node: BSTreeNode) { - TODO("Insert node to tree") - } - - override fun removeNode(node: BSTreeNode) { - TODO("Remove node in tree") - } - - override fun createNode(key: K, value: V): BSTreeNode { - TODO("Create a node") - } +package tree + +import tree.node.BSTreeNode + +class BSTree, V> : SearchTree>() { + override fun insertNode(node: BSTreeNode) { + TODO("Insert node to binory search tree") + } + + override fun removeNode(node: BSTreeNode) { + TODO("Remove node in tree") + } + + override fun createNode(key: K, value: V): BSTreeNode { + TODO("Create a node") + } } \ No newline at end of file From d2dccc2014843cf85fd8730d25429994fd7289e3 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Wed, 27 Mar 2024 21:24:23 +0300 Subject: [PATCH 022/130] feat(BST): add method insertNode --- lib/src/main/kotlin/tree/BSTree.kt | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/BSTree.kt b/lib/src/main/kotlin/tree/BSTree.kt index b3726eb..1fd85ad 100644 --- a/lib/src/main/kotlin/tree/BSTree.kt +++ b/lib/src/main/kotlin/tree/BSTree.kt @@ -3,8 +3,25 @@ package tree import tree.node.BSTreeNode class BSTree, V> : SearchTree>() { + override fun insertNode(node: BSTreeNode) { - TODO("Insert node to binory search tree") + var parentNode = root; + var treeNode = root; + while (treeNode != null) { + parentNode = treeNode; + if (node.key < treeNode.key) { + treeNode = treeNode.left + } else { + treeNode = treeNode.right + } + } + if (parentNode == null) { + root = node; + } else if (node.key < parentNode.key) { + parentNode.left = node; + } else { + parentNode.right = node; + } } override fun removeNode(node: BSTreeNode) { From 5727bfe7d57b8d9dc34dce299342cd2591b32d8a Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Wed, 27 Mar 2024 21:30:38 +0300 Subject: [PATCH 023/130] feat(BST): add constructors --- lib/src/main/kotlin/tree/BSTree.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/src/main/kotlin/tree/BSTree.kt b/lib/src/main/kotlin/tree/BSTree.kt index 1fd85ad..01038d3 100644 --- a/lib/src/main/kotlin/tree/BSTree.kt +++ b/lib/src/main/kotlin/tree/BSTree.kt @@ -2,8 +2,12 @@ package tree import tree.node.BSTreeNode -class BSTree, V> : SearchTree>() { - +class BSTree, V> : SearchTree> { + + constructor() : super() + constructor(key: K, value: V) : super(key, value) + constructor(pairs: Array>) : super(pairs) + override fun insertNode(node: BSTreeNode) { var parentNode = root; var treeNode = root; From 783a8630abcd585fa6fc351f1efc2d6d4467ea29 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Wed, 27 Mar 2024 21:53:10 +0300 Subject: [PATCH 024/130] feat(BST): add method createNode --- lib/src/main/kotlin/tree/BSTree.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/BSTree.kt b/lib/src/main/kotlin/tree/BSTree.kt index 01038d3..13d599f 100644 --- a/lib/src/main/kotlin/tree/BSTree.kt +++ b/lib/src/main/kotlin/tree/BSTree.kt @@ -33,6 +33,7 @@ class BSTree, V> : SearchTree> { } override fun createNode(key: K, value: V): BSTreeNode { - TODO("Create a node") + val node = BSTreeNode(key, value); + return node; } } \ No newline at end of file From 8d9cf1b2bc9551543f51e71e01c27b3e3f25baf9 Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Fri, 29 Mar 2024 01:04:53 +0300 Subject: [PATCH 025/130] feat(AVL-T): implemented method createNode --- lib/src/main/kotlin/tree/AVLTree.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/main/kotlin/tree/AVLTree.kt b/lib/src/main/kotlin/tree/AVLTree.kt index 56d2243..27ef33d 100644 --- a/lib/src/main/kotlin/tree/AVLTree.kt +++ b/lib/src/main/kotlin/tree/AVLTree.kt @@ -12,6 +12,6 @@ class AVLTree, V> : SearchTree>() { } override fun createNode(key: K, value: V): AVLTreeNode { - TODO("Create a node") + return AVLTreeNode(key, value) } -} \ No newline at end of file +} From 59ed96066933f49d0f512a2c8eaf4dd73015167e Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Sun, 31 Mar 2024 05:26:44 +0300 Subject: [PATCH 026/130] feat(AVL-T): Implemented insertNode method along with auxiliary methods --- lib/src/main/kotlin/tree/AVLTree.kt | 85 ++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/AVLTree.kt b/lib/src/main/kotlin/tree/AVLTree.kt index 27ef33d..958d4d8 100644 --- a/lib/src/main/kotlin/tree/AVLTree.kt +++ b/lib/src/main/kotlin/tree/AVLTree.kt @@ -2,9 +2,92 @@ package tree import tree.node.AVLTreeNode + class AVLTree, V> : SearchTree>() { + + private fun height(node: AVLTreeNode?): Int { + return node?.height ?: 0 + } + + private fun updateHeight(node: AVLTreeNode?) { + if (node != null) { + node.height = 1 + maxOf(height(node.left), height(node.right)) + } + } + + private fun getBalance(node: AVLTreeNode): Int { + return height(node.left) - height(node.right) + } + + private fun rotateRight(node: AVLTreeNode): AVLTreeNode? { + val nodeLeft = node.left + val nodeLeftRight = nodeLeft?.right + + nodeLeft?.right = node + node.left = nodeLeftRight + + updateHeight(node) + updateHeight(nodeLeft) + + return nodeLeft + } + + private fun rotateLeft(node: AVLTreeNode): AVLTreeNode? { + val nodeRight = node.right + val nodeRightLeft = nodeRight?.left + + nodeRight?.left = node + node.right = nodeRightLeft + + updateHeight(node) + updateHeight(nodeRight) + + return nodeRight + } + + private fun insertRecursive(root: AVLTreeNode?, node: AVLTreeNode?): AVLTreeNode? { + if (root == null) { + return node + } else if (node != null) { + if (root.key > node.key) { + root.left = insertRecursive(root.left, node) + } else if (root.key < node.key) { + root.right = insertRecursive(root.right, node) + } + } + + updateHeight(root) + val balance = getBalance(root) + val rootLeft = root.left + val rootRight = root.right + + if (node != null){ + if (balance > 1) { + if (rootLeft != null) { + if (node.key < rootLeft.key) { + return rotateRight(root) + } else { + root.left = root.left?.let { rotateLeft(it) } + return rotateRight(root) + } + } + } + if (balance < -1) { + if (rootRight != null) { + if (node.key > rootRight.key) { + return rotateLeft(root) + } else { + root.right = root.right?.let { rotateRight(it) } + return rotateLeft(root) + } + } + } + } + return root + } + override fun insertNode(node: AVLTreeNode) { - TODO("Insert node to tree") + root = insertRecursive(root, node) } override fun removeNode(node: AVLTreeNode) { From 2819604d1cbf1ea90af8512cdf0e2f34a092e892 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sun, 31 Mar 2024 17:14:35 +0300 Subject: [PATCH 027/130] feat(BST): add private method searchParentNode --- lib/src/main/kotlin/tree/BSTree.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/src/main/kotlin/tree/BSTree.kt b/lib/src/main/kotlin/tree/BSTree.kt index 13d599f..f42c22f 100644 --- a/lib/src/main/kotlin/tree/BSTree.kt +++ b/lib/src/main/kotlin/tree/BSTree.kt @@ -28,6 +28,19 @@ class BSTree, V> : SearchTree> { } } + private fun searchParentNode(node: BSTreeNode, parentNode: BSTreeNode): BSTreeNode? { + if (parentNode.left == node || parentNode.right == node) { + return parentNode + } + + if (node.key < parentNode.key) { + return parentNode.left?.let { searchParentNode(node, it) } + } else { + return parentNode.right?.let { searchParentNode(node, it) } + } + } + + override fun removeNode(node: BSTreeNode) { TODO("Remove node in tree") } From f6a25f0e551878d1c1ef7d0904c0ec0676abf8ff Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sun, 31 Mar 2024 17:18:38 +0300 Subject: [PATCH 028/130] refactor(BST): remove ; in method insertNode --- lib/src/main/kotlin/tree/BSTree.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/src/main/kotlin/tree/BSTree.kt b/lib/src/main/kotlin/tree/BSTree.kt index f42c22f..717c790 100644 --- a/lib/src/main/kotlin/tree/BSTree.kt +++ b/lib/src/main/kotlin/tree/BSTree.kt @@ -9,10 +9,10 @@ class BSTree, V> : SearchTree> { constructor(pairs: Array>) : super(pairs) override fun insertNode(node: BSTreeNode) { - var parentNode = root; - var treeNode = root; + var parentNode = root + var treeNode = root while (treeNode != null) { - parentNode = treeNode; + parentNode = treeNode if (node.key < treeNode.key) { treeNode = treeNode.left } else { @@ -20,11 +20,11 @@ class BSTree, V> : SearchTree> { } } if (parentNode == null) { - root = node; + root = node } else if (node.key < parentNode.key) { - parentNode.left = node; + parentNode.left = node } else { - parentNode.right = node; + parentNode.right = node } } From 71f58338eac46539cdc4408bba0a6e5f1252d00f Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sun, 31 Mar 2024 17:19:42 +0300 Subject: [PATCH 029/130] refactor(BST): remove ; in method createNode --- lib/src/main/kotlin/tree/BSTree.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/main/kotlin/tree/BSTree.kt b/lib/src/main/kotlin/tree/BSTree.kt index 717c790..b887875 100644 --- a/lib/src/main/kotlin/tree/BSTree.kt +++ b/lib/src/main/kotlin/tree/BSTree.kt @@ -46,7 +46,7 @@ class BSTree, V> : SearchTree> { } override fun createNode(key: K, value: V): BSTreeNode { - val node = BSTreeNode(key, value); - return node; + val node = BSTreeNode(key, value) + return node } } \ No newline at end of file From 36db2a2a95a600faebeb208327bc354da04a7c66 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sun, 31 Mar 2024 17:23:22 +0300 Subject: [PATCH 030/130] feat(BST): add private method getMinSubtree --- lib/src/main/kotlin/tree/BSTree.kt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/BSTree.kt b/lib/src/main/kotlin/tree/BSTree.kt index b887875..72ed647 100644 --- a/lib/src/main/kotlin/tree/BSTree.kt +++ b/lib/src/main/kotlin/tree/BSTree.kt @@ -40,7 +40,15 @@ class BSTree, V> : SearchTree> { } } - + private fun getMinSubtree(node: BSTreeNode): BSTreeNode { + val nodeN = node.left + if (nodeN == null) { + return node + } else { + return getMinSubtree(nodeN) + } + } + override fun removeNode(node: BSTreeNode) { TODO("Remove node in tree") } From d2a8972b67cf4d1b838e899be895473e36b8d8d5 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sun, 31 Mar 2024 17:25:28 +0300 Subject: [PATCH 031/130] feat(BST): add method removeNode --- lib/src/main/kotlin/tree/BSTree.kt | 45 ++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/lib/src/main/kotlin/tree/BSTree.kt b/lib/src/main/kotlin/tree/BSTree.kt index 72ed647..aa0579e 100644 --- a/lib/src/main/kotlin/tree/BSTree.kt +++ b/lib/src/main/kotlin/tree/BSTree.kt @@ -48,9 +48,50 @@ class BSTree, V> : SearchTree> { return getMinSubtree(nodeN) } } - + override fun removeNode(node: BSTreeNode) { - TODO("Remove node in tree") + val parentNode = root?.let { searchParentNode(node, it) } + + if (parentNode == null) { + root = null + return + } + + if (node.left == null && node.right == null) { + if (parentNode.left == node) { + parentNode.left = null + } else { + parentNode.right = null + } + + } else if (node.left == null || node.right == null) { + if (node.left == null) { + + if (parentNode.left == node) { + parentNode.left = node.right + } else { + parentNode.right = node.right + } + + } else { + if (parentNode.left == node) { + parentNode.left = node.left + } else { + parentNode.right = node.left + } + } + } else { + val successor = getMinSubtree(node); + removeNode(getMinSubtree(node)); + successor.left = node.left + successor.right = node.right + + if (parentNode.left == node) { + parentNode.left = successor + } else { + parentNode.right = successor + } + } } override fun createNode(key: K, value: V): BSTreeNode { From 3e2314ed2e2066ef17a885af32f0c0ddb1ca7283 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sun, 31 Mar 2024 19:51:53 +0300 Subject: [PATCH 032/130] refactor(BST): refactor method createNode --- lib/src/main/kotlin/tree/BSTree.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/src/main/kotlin/tree/BSTree.kt b/lib/src/main/kotlin/tree/BSTree.kt index aa0579e..57030e1 100644 --- a/lib/src/main/kotlin/tree/BSTree.kt +++ b/lib/src/main/kotlin/tree/BSTree.kt @@ -95,7 +95,6 @@ class BSTree, V> : SearchTree> { } override fun createNode(key: K, value: V): BSTreeNode { - val node = BSTreeNode(key, value) - return node + return BSTreeNode(key, value) } } \ No newline at end of file From c5d66c88ce6f165a9107622ee2ecf7130fd26212 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sun, 31 Mar 2024 19:55:16 +0300 Subject: [PATCH 033/130] refactor(BST): refactor method insertNode --- lib/src/main/kotlin/tree/BSTree.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/src/main/kotlin/tree/BSTree.kt b/lib/src/main/kotlin/tree/BSTree.kt index 57030e1..e672299 100644 --- a/lib/src/main/kotlin/tree/BSTree.kt +++ b/lib/src/main/kotlin/tree/BSTree.kt @@ -11,6 +11,7 @@ class BSTree, V> : SearchTree> { override fun insertNode(node: BSTreeNode) { var parentNode = root var treeNode = root + while (treeNode != null) { parentNode = treeNode if (node.key < treeNode.key) { @@ -19,6 +20,7 @@ class BSTree, V> : SearchTree> { treeNode = treeNode.right } } + if (parentNode == null) { root = node } else if (node.key < parentNode.key) { From 6fc787cf45449061aaf0b2b8c78f28aaf317d46a Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sun, 31 Mar 2024 20:21:30 +0300 Subject: [PATCH 034/130] feat(BST): add method identifyChild, correct method removeNode --- lib/src/main/kotlin/tree/BSTree.kt | 52 +++++++++++++----------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/lib/src/main/kotlin/tree/BSTree.kt b/lib/src/main/kotlin/tree/BSTree.kt index e672299..0abf1c0 100644 --- a/lib/src/main/kotlin/tree/BSTree.kt +++ b/lib/src/main/kotlin/tree/BSTree.kt @@ -20,7 +20,7 @@ class BSTree, V> : SearchTree> { treeNode = treeNode.right } } - + if (parentNode == null) { root = node } else if (node.key < parentNode.key) { @@ -51,6 +51,14 @@ class BSTree, V> : SearchTree> { } } + private fun identifyChild(parentNode: BSTreeNode, node: BSTreeNode, value: BSTreeNode?) { + if (parentNode.left == node) { + parentNode.left = value + } else { + parentNode.right = value + } + } + override fun removeNode(node: BSTreeNode) { val parentNode = root?.let { searchParentNode(node, it) } @@ -60,40 +68,26 @@ class BSTree, V> : SearchTree> { } if (node.left == null && node.right == null) { - if (parentNode.left == node) { - parentNode.left = null - } else { - parentNode.right = null - } + identifyChild(parentNode, node, null) + return + } - } else if (node.left == null || node.right == null) { + if (node.left == null || node.right == null) { if (node.left == null) { - - if (parentNode.left == node) { - parentNode.left = node.right - } else { - parentNode.right = node.right - } - + identifyChild(parentNode, node, node.right) } else { - if (parentNode.left == node) { - parentNode.left = node.left - } else { - parentNode.right = node.left - } + identifyChild(parentNode, node, node.left) } - } else { - val successor = getMinSubtree(node); - removeNode(getMinSubtree(node)); - successor.left = node.left - successor.right = node.right - if (parentNode.left == node) { - parentNode.left = successor - } else { - parentNode.right = successor - } + return } + + val successor = getMinSubtree(node) + removeNode(getMinSubtree(node)) + successor.left = node.left + successor.right = node.right + + identifyChild(parentNode, node, successor) } override fun createNode(key: K, value: V): BSTreeNode { From 619020e8d9f1959d80498d01aea489d2afb6b97d Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sun, 31 Mar 2024 22:27:17 +0300 Subject: [PATCH 035/130] feat: add method search --- lib/src/main/kotlin/tree/SearchTree.kt | 314 ++++++++++++------------- 1 file changed, 157 insertions(+), 157 deletions(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index 4413e31..0063958 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -1,157 +1,157 @@ -package tree - -import tree.node.BinaryTreeNode - -abstract class SearchTree, V, Node : BinaryTreeNode>() { - protected var root: Node? = null - var size: Long = 0 - private set - var recentlyKey: K? = null - private set - - constructor(key: K, value: V) : this() { - set(key, value) - } - - constructor(pairs: Array>) : this() { - set(pairs) - } - - protected abstract fun insertNode(node: Node) - protected abstract fun removeNode(node: Node) - protected abstract fun createNode(key: K, value: V): Node - - /** - * Finding a node in a tree by key - */ - protected fun searchNode(key: K): Node? { - TODO("Finding a node in a tree by key") - } - - /** - * Stores the value for the given key. Return previous value. - */ - fun set(key: K, value: V): V? { - TODO("Adding a node in a tree if there is no such node in the tree") - } - - /** - * Stores the values for the given keys. Return previous values. - */ - fun set(pairs: Array>): Array { - TODO("Adding multiple node in a tree if there is no such node in the tree") - } - - /** - * Stores the value for the given key if there is no pair with that key. Return previous value. - */ - fun setIfEmpty(key: K, value: V): V? { - TODO("Adding a node if such a node already exists in the tree") - } - - /** - * Stores the values for the given keys if there is no pair with that key. Return previous values. - */ - fun setIfEmpty(pairs: Array>): Array { - TODO("Adding several nodes if such a node already exists in the tree") - } - - /** - * Remove the value for the given key. Return previous value. - */ - fun remove(key: K): V? { - TODO("Adding multiple nodes if such nodes already exist in the tree") - } - - /** - * Remove the values for the given keys. Return previous values. - */ - fun remove(keys: Array): Array { - TODO("Removing multiple catches by keys") - } - - /** - * Return the value for the given key. - */ - fun search(key: K): V? { - TODO("Search by key") - } - - /** - * Returns a complete list of keys. - */ - fun getKeys(): Array { - TODO("Returns a complete list of keys") - } - - /** - * Returns a complete list of values. - */ - fun getValues(): Array { - TODO("Returns a complete list of values") - } - - /** - * Returns a complete list of pairs key value. - */ - fun getEntities(): Array> { - TODO("Returns a complete list of pair key value") - } - - /** - * Returns pair with the minimum key. - */ - fun getMin(): Pair { - TODO("Returns nodes with the minimum key") - } - - /** - * Returns pair with the maximum key. - */ - fun getMax(): Pair { - TODO("Returns nodes with the maximum key") - } - - /** - * Returns the pair with next ascending key - */ - fun successor(key: K): Pair { - TODO("Returns the next ascending key") - } - - /** - * Returns the pair with previous ascending key - */ - fun predeccessor(key: K): Pair { - TODO("Returns the previous ascending key") - } - - /** - * Remove all keys in a tree. - */ - fun clear() { - TODO("Removing all nodes in a tree") - } - - /** - * Apply [action] on all pairs by preorder tree traversal. - */ - fun preOrderTraversal(action: (Pair) -> (Unit)) { - TODO("Prefix tree traversal") - } - - /** - * Apply [action] on all pairs by inorder tree traversal. - */ - fun inOrderTraversal(action: (Pair) -> (Unit)) { - TODO("Symmetrical tree traversal") - } - - /** - * Apply [action] on all pairs by postorder tree traversal. - */ - fun postOrderTraversal(action: (Pair) -> (Unit)) { - TODO("Postfix tree traversal") - } -} - +package tree + +import tree.node.BinaryTreeNode + +abstract class SearchTree, V, Node : BinaryTreeNode>() { + protected var root: Node? = null + var size: Long = 0 + private set + var recentlyKey: K? = null + private set + + constructor(key: K, value: V) : this() { + set(key, value) + } + + constructor(pairs: Array>) : this() { + set(pairs) + } + + protected abstract fun insertNode(node: Node) + protected abstract fun removeNode(node: Node) + protected abstract fun createNode(key: K, value: V): Node + + /** + * Finding a node in a tree by key + */ + protected fun searchNode(key: K): Node? { + TODO("Finding a node in a tree by key") + } + + /** + * Stores the value for the given key. Return previous value. + */ + fun set(key: K, value: V): V? { + TODO("Adding a node in a tree if there is no such node in the tree") + } + + /** + * Stores the values for the given keys. Return previous values. + */ + fun set(pairs: Array>): Array { + TODO("Adding multiple node in a tree if there is no such node in the tree") + } + + /** + * Stores the value for the given key if there is no pair with that key. Return previous value. + */ + fun setIfEmpty(key: K, value: V): V? { + TODO("Adding a node if such a node already exists in the tree") + } + + /** + * Stores the values for the given keys if there is no pair with that key. Return previous values. + */ + fun setIfEmpty(pairs: Array>): Array { + TODO("Adding several nodes if such a node already exists in the tree") + } + + /** + * Remove the value for the given key. Return previous value. + */ + fun remove(key: K): V? { + TODO("Adding multiple nodes if such nodes already exist in the tree") + } + + /** + * Remove the values for the given keys. Return previous values. + */ + fun remove(keys: Array): Array { + TODO("Removing multiple catches by keys") + } + + /** + * Return the value for the given key. + */ + fun search(key: K): V? { + return searchNode(key)?.value + } + + /** + * Returns a complete list of keys. + */ + fun getKeys(): Array { + TODO("Returns a complete list of keys") + } + + /** + * Returns a complete list of values. + */ + fun getValues(): Array { + TODO("Returns a complete list of values") + } + + /** + * Returns a complete list of pairs key value. + */ + fun getEntities(): Array> { + TODO("Returns a complete list of pair key value") + } + + /** + * Returns pair with the minimum key. + */ + fun getMin(): Pair { + TODO("Returns nodes with the minimum key") + } + + /** + * Returns pair with the maximum key. + */ + fun getMax(): Pair { + TODO("Returns nodes with the maximum key") + } + + /** + * Returns the pair with next ascending key + */ + fun successor(key: K): Pair { + TODO("Returns the next ascending key") + } + + /** + * Returns the pair with previous ascending key + */ + fun predeccessor(key: K): Pair { + TODO("Returns the previous ascending key") + } + + /** + * Remove all keys in a tree. + */ + fun clear() { + TODO("Removing all nodes in a tree") + } + + /** + * Apply [action] on all pairs by preorder tree traversal. + */ + fun preOrderTraversal(action: (Pair) -> (Unit)) { + TODO("Prefix tree traversal") + } + + /** + * Apply [action] on all pairs by inorder tree traversal. + */ + fun inOrderTraversal(action: (Pair) -> (Unit)) { + TODO("Symmetrical tree traversal") + } + + /** + * Apply [action] on all pairs by postorder tree traversal. + */ + fun postOrderTraversal(action: (Pair) -> (Unit)) { + TODO("Postfix tree traversal") + } +} + From 439e822bcd9ebd4265868d39cb9068eb940d0ee6 Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Sun, 31 Mar 2024 23:20:50 +0300 Subject: [PATCH 036/130] feat: implement searchNode method --- lib/src/main/kotlin/tree/SearchTree.kt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index 4413e31..dcc60db 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -25,7 +25,19 @@ abstract class SearchTree, V, Node : BinaryTreeNode node.key) { + node = node.right + } else { + return node + } + } + + return null } /** From add2326b83097c65b9bc07c6b503ac47b3d3311a Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Sun, 31 Mar 2024 23:26:06 +0300 Subject: [PATCH 037/130] feat: implement set with single key method --- lib/src/main/kotlin/tree/SearchTree.kt | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index dcc60db..7c37cb8 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -44,7 +44,18 @@ abstract class SearchTree, V, Node : BinaryTreeNode Date: Sun, 31 Mar 2024 23:29:18 +0300 Subject: [PATCH 038/130] fix: spell mistake --- lib/src/main/kotlin/tree/SearchTree.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index 7c37cb8..009eecc 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -145,7 +145,7 @@ abstract class SearchTree, V, Node : BinaryTreeNode { + fun predecessor(key: K): Pair { TODO("Returns the previous ascending key") } From 84f1abe0affd5e22f40139ad9e3e9353bdbe09a4 Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Sun, 31 Mar 2024 23:31:59 +0300 Subject: [PATCH 039/130] refactor(AVL-T): balancing has been moved to a separate method rebalanced --- lib/src/main/kotlin/tree/AVLTree.kt | 33 ++++++++++++++++------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/lib/src/main/kotlin/tree/AVLTree.kt b/lib/src/main/kotlin/tree/AVLTree.kt index 958d4d8..71f88c7 100644 --- a/lib/src/main/kotlin/tree/AVLTree.kt +++ b/lib/src/main/kotlin/tree/AVLTree.kt @@ -45,23 +45,13 @@ class AVLTree, V> : SearchTree>() { return nodeRight } - private fun insertRecursive(root: AVLTreeNode?, node: AVLTreeNode?): AVLTreeNode? { - if (root == null) { - return node - } else if (node != null) { - if (root.key > node.key) { - root.left = insertRecursive(root.left, node) - } else if (root.key < node.key) { - root.right = insertRecursive(root.right, node) - } - } - + private fun rebalanced(root: AVLTreeNode?, node: AVLTreeNode?): AVLTreeNode?{ updateHeight(root) - val balance = getBalance(root) - val rootLeft = root.left - val rootRight = root.right + val balance = root?.let { getBalance(it) } + val rootLeft = root?.left + val rootRight = root?.right - if (node != null){ + if (node != null && balance != null){ if (balance > 1) { if (rootLeft != null) { if (node.key < rootLeft.key) { @@ -86,6 +76,19 @@ class AVLTree, V> : SearchTree>() { return root } + private fun insertRecursive(root: AVLTreeNode?, node: AVLTreeNode?): AVLTreeNode? { + if (root == null) { + return node + } else if (node != null) { + if (root.key > node.key) { + root.left = insertRecursive(root.left, node) + } else if (root.key < node.key) { + root.right = insertRecursive(root.right, node) + } + } + return rebalanced(root, node) + } + override fun insertNode(node: AVLTreeNode) { root = insertRecursive(root, node) } From 41e2366ccc987fc17d85ae56d364938f31294967 Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Sun, 31 Mar 2024 23:43:38 +0300 Subject: [PATCH 040/130] feat: implement postOrderTraversal --- lib/src/main/kotlin/tree/SearchTree.kt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index 009eecc..107bd7e 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -174,7 +174,17 @@ abstract class SearchTree, V, Node : BinaryTreeNode) -> (Unit)) { - TODO("Postfix tree traversal") + val root = this.root ?: return + + fun helper(node: Node?) { + if (node == null) return + + helper(node.left) + helper(node.right) + action(Pair(node.key, node.value)) + } + + helper(root) } } From 5f42f37ddc25a92c7149b46211fff42b8d1c3455 Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Wed, 27 Mar 2024 19:34:43 +0300 Subject: [PATCH 041/130] feat(RBT): implement createNode method --- lib/src/main/kotlin/tree/RBTree.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/RBTree.kt b/lib/src/main/kotlin/tree/RBTree.kt index c451934..5a49495 100644 --- a/lib/src/main/kotlin/tree/RBTree.kt +++ b/lib/src/main/kotlin/tree/RBTree.kt @@ -12,6 +12,6 @@ class RBTree, V> : SearchTree>() { } override fun createNode(key: K, value: V): RBTreeNode { - TODO("Create a node") + return RBTreeNode(key, value) } } \ No newline at end of file From ddd5d3f7c654592a65cdb97e9e54f8275928b3da Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Wed, 27 Mar 2024 20:09:33 +0300 Subject: [PATCH 042/130] feat(RBT): implement rotation methods --- lib/src/main/kotlin/tree/RBTree.kt | 44 ++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/lib/src/main/kotlin/tree/RBTree.kt b/lib/src/main/kotlin/tree/RBTree.kt index 5a49495..10d27ac 100644 --- a/lib/src/main/kotlin/tree/RBTree.kt +++ b/lib/src/main/kotlin/tree/RBTree.kt @@ -14,4 +14,48 @@ class RBTree, V> : SearchTree>() { override fun createNode(key: K, value: V): RBTreeNode { return RBTreeNode(key, value) } + + private fun leftRotation(x: RBTreeNode): Boolean { + val y = x.right ?: return false + + x.right = y.left + y.left?.parent = x; + y.parent = x.parent + + val parent = x.parent + if (parent == null) { + root = y + } else if (parent.left == x) { + parent.left = y + } else { + parent.right = y + } + + y.left = x + x.parent = y + + return true + } + + private fun rightRotation(y: RBTreeNode): Boolean { + val x = y.left ?: return false + + y.left = x.right + x.right?.parent = y + x.parent = y.parent + + val parent = y.parent + if (parent == null) { + root = x + } else if (parent.left == y) { + parent.left = x + } else { + parent.right = x + } + + x.right = y + y.parent = x + + return true + } } \ No newline at end of file From 8a415a371e217fcabce576d979faa44932973ced Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Wed, 27 Mar 2024 20:44:05 +0300 Subject: [PATCH 043/130] feat(RBT): implement insertNode method --- lib/src/main/kotlin/tree/RBTree.kt | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/RBTree.kt b/lib/src/main/kotlin/tree/RBTree.kt index 10d27ac..a2c6b76 100644 --- a/lib/src/main/kotlin/tree/RBTree.kt +++ b/lib/src/main/kotlin/tree/RBTree.kt @@ -1,12 +1,36 @@ package tree +import tree.node.RBTreeColor import tree.node.RBTreeNode class RBTree, V> : SearchTree>() { override fun insertNode(node: RBTreeNode) { - TODO("Insert node to tree") + var tmpNode = root + var tmpNodeParent: RBTreeNode? = null + while (tmpNode != null) { + tmpNodeParent = tmpNode + tmpNode = if (node.key < tmpNode.key) tmpNode.left else tmpNode.right + } + node.parent = tmpNodeParent + + if (tmpNodeParent == null) { + root = node + } else if (node.key < tmpNodeParent.key) { + tmpNodeParent.left = node + } else { + tmpNodeParent.right = node + } + + node.left = null + node.right = null + node.color = RBTreeColor.RED + + insertFixup(node) } + private fun insertFixup(node: RBTreeNode) { + TODO() + } override fun removeNode(node: RBTreeNode) { TODO("Remove node in tree") } @@ -58,4 +82,8 @@ class RBTree, V> : SearchTree>() { return true } + + private fun setNewRoot(root: RBTreeNode) { + this.root = root + } } \ No newline at end of file From dd805250501be8c06734d4abaf4e64d1d17b28d8 Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Wed, 27 Mar 2024 22:17:09 +0300 Subject: [PATCH 044/130] feat(RBT): implement insertFix method --- lib/src/main/kotlin/tree/RBTree.kt | 62 ++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/lib/src/main/kotlin/tree/RBTree.kt b/lib/src/main/kotlin/tree/RBTree.kt index a2c6b76..15cef65 100644 --- a/lib/src/main/kotlin/tree/RBTree.kt +++ b/lib/src/main/kotlin/tree/RBTree.kt @@ -7,12 +7,13 @@ class RBTree, V> : SearchTree>() { override fun insertNode(node: RBTreeNode) { var tmpNode = root var tmpNodeParent: RBTreeNode? = null + while (tmpNode != null) { tmpNodeParent = tmpNode tmpNode = if (node.key < tmpNode.key) tmpNode.left else tmpNode.right } - node.parent = tmpNodeParent + node.parent = tmpNodeParent if (tmpNodeParent == null) { root = node } else if (node.key < tmpNodeParent.key) { @@ -25,12 +26,65 @@ class RBTree, V> : SearchTree>() { node.right = null node.color = RBTreeColor.RED - insertFixup(node) + if (node.parent == null) { + node.color = RBTreeColor.BLACK; + return + } + + if (node.parent?.parent == null) { + return; + } + + insertFix(node) } - private fun insertFixup(node: RBTreeNode) { - TODO() + private fun insertFix(newNode: RBTreeNode) { + var node = newNode + + while (node.parent?.color === RBTreeColor.RED) { + if (node.parent == node.parent?.parent?.right) { + val uncle = node.parent?.parent?.right + + if (uncle?.color == RBTreeColor.RED) { + uncle.color = RBTreeColor.BLACK + node.parent?.color = RBTreeColor.BLACK + node.parent?.parent?.color = RBTreeColor.RED + node = node.parent?.parent ?: return + } else { + if (node == node.parent?.left) { + node = node.parent ?: return + rightRotation(node) + } + node.parent?.color = RBTreeColor.BLACK + node.parent?.parent?.color = RBTreeColor.RED; + leftRotation(node.parent?.parent ?: return) + } + } else { + val uncle = node.parent?.parent?.right + + if (uncle?.color == RBTreeColor.RED) { + uncle.color = RBTreeColor.BLACK + node.parent?.color = RBTreeColor.BLACK + node.parent?.parent?.color = RBTreeColor.RED + node = node.parent?.parent ?: return + } else { + if (node == node.parent?.right) { + node = node.parent ?: return + leftRotation(node) + } + node.parent?.color = RBTreeColor.BLACK + node.parent?.parent?.color = RBTreeColor.RED + rightRotation(node.parent?.parent ?: return) + } + } + if (node == root) { + break + } + } + + root?.color = RBTreeColor.BLACK; } + override fun removeNode(node: RBTreeNode) { TODO("Remove node in tree") } From 3213846991b7669afc0d3b1ca0eafd3ddbc2c39c Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Wed, 27 Mar 2024 22:22:52 +0300 Subject: [PATCH 045/130] refactor(RBT): refactor insertFix method --- lib/src/main/kotlin/tree/RBTree.kt | 50 +++++++++++++++++------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/lib/src/main/kotlin/tree/RBTree.kt b/lib/src/main/kotlin/tree/RBTree.kt index 15cef65..c4af814 100644 --- a/lib/src/main/kotlin/tree/RBTree.kt +++ b/lib/src/main/kotlin/tree/RBTree.kt @@ -42,41 +42,49 @@ class RBTree, V> : SearchTree>() { var node = newNode while (node.parent?.color === RBTreeColor.RED) { - if (node.parent == node.parent?.parent?.right) { - val uncle = node.parent?.parent?.right + var parent = node.parent ?: return + var grandpa = parent.parent ?: return - if (uncle?.color == RBTreeColor.RED) { + if (parent == grandpa.right) { + val uncle = grandpa.right ?: return + + if (uncle.color == RBTreeColor.RED) { uncle.color = RBTreeColor.BLACK - node.parent?.color = RBTreeColor.BLACK - node.parent?.parent?.color = RBTreeColor.RED - node = node.parent?.parent ?: return + parent.color = RBTreeColor.BLACK + grandpa.color = RBTreeColor.RED + node = grandpa } else { - if (node == node.parent?.left) { - node = node.parent ?: return + if (node == parent.left) { + node = parent + parent = node.parent ?: return + grandpa = parent.parent ?: return rightRotation(node) } - node.parent?.color = RBTreeColor.BLACK - node.parent?.parent?.color = RBTreeColor.RED; - leftRotation(node.parent?.parent ?: return) + parent.color = RBTreeColor.BLACK + grandpa.color = RBTreeColor.RED; + leftRotation(grandpa) } } else { - val uncle = node.parent?.parent?.right + val uncle = grandpa.right ?: return - if (uncle?.color == RBTreeColor.RED) { + if (uncle.color == RBTreeColor.RED) { uncle.color = RBTreeColor.BLACK - node.parent?.color = RBTreeColor.BLACK - node.parent?.parent?.color = RBTreeColor.RED - node = node.parent?.parent ?: return + parent.color = RBTreeColor.BLACK + grandpa.color = RBTreeColor.RED + node = grandpa } else { - if (node == node.parent?.right) { - node = node.parent ?: return + if (node == parent.right) { + node = parent + parent = node.parent ?: return + grandpa = parent.parent ?: return leftRotation(node) } - node.parent?.color = RBTreeColor.BLACK - node.parent?.parent?.color = RBTreeColor.RED - rightRotation(node.parent?.parent ?: return) + parent.color = RBTreeColor.BLACK + grandpa.color = RBTreeColor.RED + rightRotation(grandpa) } } + if (node == root) { break } From 0b67dce0d9aecb29d2db4a37691dfa11212a6d3b Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Wed, 27 Mar 2024 22:37:24 +0300 Subject: [PATCH 046/130] feat(RBT): implement throwError() method --- lib/src/main/kotlin/tree/RBTree.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/RBTree.kt b/lib/src/main/kotlin/tree/RBTree.kt index c4af814..2b9c50a 100644 --- a/lib/src/main/kotlin/tree/RBTree.kt +++ b/lib/src/main/kotlin/tree/RBTree.kt @@ -148,4 +148,8 @@ class RBTree, V> : SearchTree>() { private fun setNewRoot(root: RBTreeNode) { this.root = root } -} \ No newline at end of file + + private fun throwError() { + throw UnknownError("Bug. Please contact with developer of library"); + } +} From 3f58a4d39f6f672722b8d9840c07fff196d36131 Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Wed, 27 Mar 2024 22:37:44 +0300 Subject: [PATCH 047/130] refactor(RBT): refactor rotation methods rename variables for readability --- lib/src/main/kotlin/tree/RBTree.kt | 52 ++++++++++++++---------------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/lib/src/main/kotlin/tree/RBTree.kt b/lib/src/main/kotlin/tree/RBTree.kt index 2b9c50a..70aafc9 100644 --- a/lib/src/main/kotlin/tree/RBTree.kt +++ b/lib/src/main/kotlin/tree/RBTree.kt @@ -101,48 +101,44 @@ class RBTree, V> : SearchTree>() { return RBTreeNode(key, value) } - private fun leftRotation(x: RBTreeNode): Boolean { - val y = x.right ?: return false + private fun leftRotation(node: RBTreeNode) { + val rightNode = node.right ?: return - x.right = y.left - y.left?.parent = x; - y.parent = x.parent + node.right = rightNode.left + rightNode.left?.parent = node; + rightNode.parent = node.parent - val parent = x.parent + val parent = node.parent if (parent == null) { - root = y - } else if (parent.left == x) { - parent.left = y + root = rightNode + } else if (parent.left == node) { + parent.left = rightNode } else { - parent.right = y + parent.right = rightNode } - y.left = x - x.parent = y - - return true + rightNode.left = node + node.parent = rightNode } - private fun rightRotation(y: RBTreeNode): Boolean { - val x = y.left ?: return false + private fun rightRotation(node: RBTreeNode) { + val leftNode = node.left ?: return - y.left = x.right - x.right?.parent = y - x.parent = y.parent + node.left = leftNode.right + leftNode.right?.parent = node + leftNode.parent = node.parent - val parent = y.parent + val parent = node.parent if (parent == null) { - root = x - } else if (parent.left == y) { - parent.left = x + root = leftNode + } else if (parent.left == node) { + parent.left = leftNode } else { - parent.right = x + parent.right = leftNode } - x.right = y - y.parent = x - - return true + leftNode.right = node + node.parent = leftNode } private fun setNewRoot(root: RBTreeNode) { From b78d2f69434f40cb35f98180fedff2ec72755372 Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Wed, 27 Mar 2024 22:42:10 +0300 Subject: [PATCH 048/130] fix(RBT): remove useless method that I did just for fun and forgeted delete --- lib/src/main/kotlin/tree/RBTree.kt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/src/main/kotlin/tree/RBTree.kt b/lib/src/main/kotlin/tree/RBTree.kt index 70aafc9..9ccd5a5 100644 --- a/lib/src/main/kotlin/tree/RBTree.kt +++ b/lib/src/main/kotlin/tree/RBTree.kt @@ -84,7 +84,7 @@ class RBTree, V> : SearchTree>() { rightRotation(grandpa) } } - + if (node == root) { break } @@ -141,10 +141,6 @@ class RBTree, V> : SearchTree>() { node.parent = leftNode } - private fun setNewRoot(root: RBTreeNode) { - this.root = root - } - private fun throwError() { throw UnknownError("Bug. Please contact with developer of library"); } From 8a2a2acbbfef98899894130fecb16b2dee7455a7 Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Wed, 27 Mar 2024 22:45:37 +0300 Subject: [PATCH 049/130] feat(RBT): inherit constructors from SearchTree --- lib/src/main/kotlin/tree/RBTree.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/RBTree.kt b/lib/src/main/kotlin/tree/RBTree.kt index 9ccd5a5..8c2852a 100644 --- a/lib/src/main/kotlin/tree/RBTree.kt +++ b/lib/src/main/kotlin/tree/RBTree.kt @@ -3,7 +3,11 @@ package tree import tree.node.RBTreeColor import tree.node.RBTreeNode -class RBTree, V> : SearchTree>() { +class RBTree, V> : SearchTree> { + constructor() : super() + constructor(key: K, value: V) : super(key, value) + constructor(pairs: Array>) : super(pairs) + override fun insertNode(node: RBTreeNode) { var tmpNode = root var tmpNodeParent: RBTreeNode? = null From 9e0c75f2bb09048291cee0e9aacea0cb795af9b2 Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Wed, 27 Mar 2024 23:24:56 +0300 Subject: [PATCH 050/130] fix(RBT): fix bug in insertFix wrong side of granpa in uncle initilization --- lib/src/main/kotlin/tree/RBTree.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/RBTree.kt b/lib/src/main/kotlin/tree/RBTree.kt index 8c2852a..014e6e3 100644 --- a/lib/src/main/kotlin/tree/RBTree.kt +++ b/lib/src/main/kotlin/tree/RBTree.kt @@ -50,7 +50,7 @@ class RBTree, V> : SearchTree> { var grandpa = parent.parent ?: return if (parent == grandpa.right) { - val uncle = grandpa.right ?: return + val uncle = grandpa.left ?: return if (uncle.color == RBTreeColor.RED) { uncle.color = RBTreeColor.BLACK From 3d8d788d7bb02b6e0eb3f6fe41c5b2d81d719540 Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Wed, 27 Mar 2024 23:27:20 +0300 Subject: [PATCH 051/130] refactor(RBT): refactor RBTree class, remove semicolons --- lib/src/main/kotlin/tree/RBTree.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/src/main/kotlin/tree/RBTree.kt b/lib/src/main/kotlin/tree/RBTree.kt index 014e6e3..a6e733a 100644 --- a/lib/src/main/kotlin/tree/RBTree.kt +++ b/lib/src/main/kotlin/tree/RBTree.kt @@ -31,12 +31,12 @@ class RBTree, V> : SearchTree> { node.color = RBTreeColor.RED if (node.parent == null) { - node.color = RBTreeColor.BLACK; + node.color = RBTreeColor.BLACK return } if (node.parent?.parent == null) { - return; + return } insertFix(node) @@ -65,7 +65,7 @@ class RBTree, V> : SearchTree> { rightRotation(node) } parent.color = RBTreeColor.BLACK - grandpa.color = RBTreeColor.RED; + grandpa.color = RBTreeColor.RED leftRotation(grandpa) } } else { @@ -94,7 +94,7 @@ class RBTree, V> : SearchTree> { } } - root?.color = RBTreeColor.BLACK; + root?.color = RBTreeColor.BLACK } override fun removeNode(node: RBTreeNode) { @@ -109,7 +109,7 @@ class RBTree, V> : SearchTree> { val rightNode = node.right ?: return node.right = rightNode.left - rightNode.left?.parent = node; + rightNode.left?.parent = node rightNode.parent = node.parent val parent = node.parent @@ -146,6 +146,6 @@ class RBTree, V> : SearchTree> { } private fun throwError() { - throw UnknownError("Bug. Please contact with developer of library"); + throw UnknownError("Bug. Please contact with developer of library") } } From b8c74a84f360939b4d88a869fbecfe4e002e266c Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Fri, 29 Mar 2024 02:00:28 +0300 Subject: [PATCH 052/130] feat(RBT): add rbTransplant method --- lib/src/main/kotlin/tree/RBTree.kt | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/RBTree.kt b/lib/src/main/kotlin/tree/RBTree.kt index a6e733a..23d28d9 100644 --- a/lib/src/main/kotlin/tree/RBTree.kt +++ b/lib/src/main/kotlin/tree/RBTree.kt @@ -98,13 +98,29 @@ class RBTree, V> : SearchTree> { } override fun removeNode(node: RBTreeNode) { - TODO("Remove node in tree") + var } override fun createNode(key: K, value: V): RBTreeNode { return RBTreeNode(key, value) } + private fun rbTransplant(previous: RBTreeNode, curr: RBTreeNode?) { + val parent = previous.parent + + if (parent == null) { + root = curr + } else if (previous == parent.left) { + parent.left = curr + } else { + parent.right = curr + } + + if (curr != null) { + curr.parent = parent + } + } + private fun leftRotation(node: RBTreeNode) { val rightNode = node.right ?: return From dc8f1f89ab5afc9eb14e59dd0a67a4e2d82409bb Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Fri, 29 Mar 2024 02:24:13 +0300 Subject: [PATCH 053/130] feat(RBT): implement removeNode method --- lib/src/main/kotlin/tree/RBTree.kt | 52 +++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/RBTree.kt b/lib/src/main/kotlin/tree/RBTree.kt index 23d28d9..9112bb3 100644 --- a/lib/src/main/kotlin/tree/RBTree.kt +++ b/lib/src/main/kotlin/tree/RBTree.kt @@ -98,13 +98,63 @@ class RBTree, V> : SearchTree> { } override fun removeNode(node: RBTreeNode) { - var + var nodeTmp = node + val transplantedNode: RBTreeNode? + var originalColor = nodeTmp.color + + val leftNode = nodeTmp.left + val rightNode = nodeTmp.right + if (leftNode == null) { + transplantedNode = nodeTmp.right + rbTransplant(nodeTmp, nodeTmp.right) + } else if (rightNode == null) { + transplantedNode = nodeTmp.left + rbTransplant(nodeTmp, nodeTmp.left) + } else { + nodeTmp = minimum(rightNode) + originalColor = nodeTmp.color + transplantedNode = nodeTmp.right + if (nodeTmp.parent == node) { + transplantedNode?.parent = nodeTmp + } else { + rbTransplant(nodeTmp, nodeTmp.right) + nodeTmp.right = node.right + nodeTmp.right?.parent = nodeTmp; + } + + rbTransplant(node, nodeTmp) + nodeTmp.left = node.left + nodeTmp.left?.parent = nodeTmp + nodeTmp.color = node.color + } + + if (originalColor == RBTreeColor.BLACK) { + if (transplantedNode != null) { + deleteFix(transplantedNode) + } + } } override fun createNode(key: K, value: V): RBTreeNode { return RBTreeNode(key, value) } + private fun deleteFix(node: RBTreeNode) { + TODO() + } + + private fun minimum(node: RBTreeNode): RBTreeNode { + var node = node + var leftNode = node.left + + while (leftNode !== null) { + node = leftNode + leftNode = node.left + } + + return node + } + private fun rbTransplant(previous: RBTreeNode, curr: RBTreeNode?) { val parent = previous.parent From 5a5c4de2ee5439b783a87df4aa168b26a5728d28 Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Mon, 1 Apr 2024 12:22:30 +0300 Subject: [PATCH 054/130] refactor(RBT): make minimum and removeNode prettier --- lib/src/main/kotlin/tree/RBTree.kt | 61 ++++++++++++++---------------- 1 file changed, 29 insertions(+), 32 deletions(-) diff --git a/lib/src/main/kotlin/tree/RBTree.kt b/lib/src/main/kotlin/tree/RBTree.kt index 9112bb3..c0005d3 100644 --- a/lib/src/main/kotlin/tree/RBTree.kt +++ b/lib/src/main/kotlin/tree/RBTree.kt @@ -98,40 +98,39 @@ class RBTree, V> : SearchTree> { } override fun removeNode(node: RBTreeNode) { - var nodeTmp = node val transplantedNode: RBTreeNode? - var originalColor = nodeTmp.color - val leftNode = nodeTmp.left - val rightNode = nodeTmp.right + var originalColor = node.color + val leftNode = node.left + val rightNode = node.right + if (leftNode == null) { - transplantedNode = nodeTmp.right - rbTransplant(nodeTmp, nodeTmp.right) + transplantedNode = rightNode + rbTransplant(node, rightNode) } else if (rightNode == null) { - transplantedNode = nodeTmp.left - rbTransplant(nodeTmp, nodeTmp.left) + transplantedNode = leftNode + rbTransplant(node, leftNode) } else { - nodeTmp = minimum(rightNode) - originalColor = nodeTmp.color - transplantedNode = nodeTmp.right - if (nodeTmp.parent == node) { - transplantedNode?.parent = nodeTmp + val minNode = minimum(rightNode) + + originalColor = minNode.color + transplantedNode = minNode.right + if (minNode.parent == node) { + transplantedNode?.parent = minNode } else { - rbTransplant(nodeTmp, nodeTmp.right) - nodeTmp.right = node.right - nodeTmp.right?.parent = nodeTmp; + rbTransplant(minNode, minNode.right) + minNode.right = node.right + minNode.right?.parent = minNode } - rbTransplant(node, nodeTmp) - nodeTmp.left = node.left - nodeTmp.left?.parent = nodeTmp - nodeTmp.color = node.color + rbTransplant(node, minNode) + minNode.left = node.left + minNode.left?.parent = minNode + minNode.color = node.color } - if (originalColor == RBTreeColor.BLACK) { - if (transplantedNode != null) { - deleteFix(transplantedNode) - } + if (originalColor == RBTreeColor.BLACK && transplantedNode != null) { + deleteFix(transplantedNode) } } @@ -143,16 +142,14 @@ class RBTree, V> : SearchTree> { TODO() } - private fun minimum(node: RBTreeNode): RBTreeNode { - var node = node - var leftNode = node.left + private tailrec fun minimum(node: RBTreeNode): RBTreeNode { + val leftNode = node.left - while (leftNode !== null) { - node = leftNode - leftNode = node.left + if (leftNode == null) { + return node + } else { + return minimum(leftNode) } - - return node } private fun rbTransplant(previous: RBTreeNode, curr: RBTreeNode?) { From dd6cf3efcae318afe392fcc2d08bbef1da884ab9 Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Mon, 1 Apr 2024 12:48:28 +0300 Subject: [PATCH 055/130] feat(RBT): implement deleteFix method --- lib/src/main/kotlin/tree/RBTree.kt | 64 +++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/lib/src/main/kotlin/tree/RBTree.kt b/lib/src/main/kotlin/tree/RBTree.kt index c0005d3..7739d22 100644 --- a/lib/src/main/kotlin/tree/RBTree.kt +++ b/lib/src/main/kotlin/tree/RBTree.kt @@ -138,8 +138,68 @@ class RBTree, V> : SearchTree> { return RBTreeNode(key, value) } - private fun deleteFix(node: RBTreeNode) { - TODO() + private fun deleteFix(transplantedNode: RBTreeNode) { + var node: RBTreeNode? = transplantedNode + + while (node != root && node?.color == RBTreeColor.BLACK) { + val parentNode = node.parent ?: return + + if (node == parentNode.left) { + var uncle = parentNode.right ?: return + + if (uncle.color == RBTreeColor.RED) { + uncle.color = RBTreeColor.BLACK + parentNode.color = RBTreeColor.RED + leftRotation(parentNode) + uncle = parentNode.right ?: return + } + + if (uncle.left?.color == RBTreeColor.BLACK && uncle.right?.color == RBTreeColor.BLACK) { + uncle.color = RBTreeColor.RED + node = parentNode + } else { + if (uncle.right?.color == RBTreeColor.BLACK) { + uncle.left?.color = RBTreeColor.BLACK + uncle.color = RBTreeColor.RED + rightRotation(uncle) + uncle = parentNode.right ?: return + } + + uncle.color = parentNode.color + parentNode.color = RBTreeColor.BLACK + uncle.right?.color = RBTreeColor.BLACK + leftRotation(parentNode) + node = root + } + } else { + var uncle = parentNode.left ?: return + + if (uncle.color == RBTreeColor.RED) { + uncle.color = RBTreeColor.BLACK + parentNode.color = RBTreeColor.RED + rightRotation(parentNode) + uncle = parentNode.left ?: return + } + + if (uncle.right?.color == RBTreeColor.BLACK && uncle.right?.color == RBTreeColor.BLACK) { + uncle.color = RBTreeColor.RED + node = parentNode + } else { + if (uncle.left?.color == RBTreeColor.BLACK) { + uncle.right?.color = RBTreeColor.BLACK + uncle.color = RBTreeColor.RED + leftRotation(uncle) + uncle = parentNode.left ?: return + } + + uncle.color = parentNode.color + parentNode.color = RBTreeColor.BLACK + uncle.left?.color = RBTreeColor.BLACK + rightRotation(parentNode) + node = root + } + } + } } private tailrec fun minimum(node: RBTreeNode): RBTreeNode { From 359a1d91079a4474f09170a35e1abcfe4156cfd0 Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Mon, 1 Apr 2024 12:49:08 +0300 Subject: [PATCH 056/130] refactor(RBT): delete useless method that throw error --- lib/src/main/kotlin/tree/RBTree.kt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/src/main/kotlin/tree/RBTree.kt b/lib/src/main/kotlin/tree/RBTree.kt index 7739d22..c0c35de 100644 --- a/lib/src/main/kotlin/tree/RBTree.kt +++ b/lib/src/main/kotlin/tree/RBTree.kt @@ -267,8 +267,4 @@ class RBTree, V> : SearchTree> { leftNode.right = node node.parent = leftNode } - - private fun throwError() { - throw UnknownError("Bug. Please contact with developer of library") - } } From d465c6725af4ec5cb5308db64b455143b198113a Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Mon, 1 Apr 2024 12:50:48 +0300 Subject: [PATCH 057/130] refactor(RBT): make names of methods prettier --- lib/src/main/kotlin/tree/RBTree.kt | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/src/main/kotlin/tree/RBTree.kt b/lib/src/main/kotlin/tree/RBTree.kt index c0c35de..de8a509 100644 --- a/lib/src/main/kotlin/tree/RBTree.kt +++ b/lib/src/main/kotlin/tree/RBTree.kt @@ -62,11 +62,11 @@ class RBTree, V> : SearchTree> { node = parent parent = node.parent ?: return grandpa = parent.parent ?: return - rightRotation(node) + rightRotate(node) } parent.color = RBTreeColor.BLACK grandpa.color = RBTreeColor.RED - leftRotation(grandpa) + leftRotate(grandpa) } } else { val uncle = grandpa.right ?: return @@ -81,11 +81,11 @@ class RBTree, V> : SearchTree> { node = parent parent = node.parent ?: return grandpa = parent.parent ?: return - leftRotation(node) + leftRotate(node) } parent.color = RBTreeColor.BLACK grandpa.color = RBTreeColor.RED - rightRotation(grandpa) + rightRotate(grandpa) } } @@ -111,7 +111,7 @@ class RBTree, V> : SearchTree> { transplantedNode = leftNode rbTransplant(node, leftNode) } else { - val minNode = minimum(rightNode) + val minNode = getMinNode(rightNode) originalColor = minNode.color transplantedNode = minNode.right @@ -150,7 +150,7 @@ class RBTree, V> : SearchTree> { if (uncle.color == RBTreeColor.RED) { uncle.color = RBTreeColor.BLACK parentNode.color = RBTreeColor.RED - leftRotation(parentNode) + leftRotate(parentNode) uncle = parentNode.right ?: return } @@ -161,14 +161,14 @@ class RBTree, V> : SearchTree> { if (uncle.right?.color == RBTreeColor.BLACK) { uncle.left?.color = RBTreeColor.BLACK uncle.color = RBTreeColor.RED - rightRotation(uncle) + rightRotate(uncle) uncle = parentNode.right ?: return } uncle.color = parentNode.color parentNode.color = RBTreeColor.BLACK uncle.right?.color = RBTreeColor.BLACK - leftRotation(parentNode) + leftRotate(parentNode) node = root } } else { @@ -177,7 +177,7 @@ class RBTree, V> : SearchTree> { if (uncle.color == RBTreeColor.RED) { uncle.color = RBTreeColor.BLACK parentNode.color = RBTreeColor.RED - rightRotation(parentNode) + rightRotate(parentNode) uncle = parentNode.left ?: return } @@ -188,27 +188,27 @@ class RBTree, V> : SearchTree> { if (uncle.left?.color == RBTreeColor.BLACK) { uncle.right?.color = RBTreeColor.BLACK uncle.color = RBTreeColor.RED - leftRotation(uncle) + leftRotate(uncle) uncle = parentNode.left ?: return } uncle.color = parentNode.color parentNode.color = RBTreeColor.BLACK uncle.left?.color = RBTreeColor.BLACK - rightRotation(parentNode) + rightRotate(parentNode) node = root } } } } - private tailrec fun minimum(node: RBTreeNode): RBTreeNode { + private tailrec fun getMinNode(node: RBTreeNode): RBTreeNode { val leftNode = node.left if (leftNode == null) { return node } else { - return minimum(leftNode) + return getMinNode(leftNode) } } @@ -228,7 +228,7 @@ class RBTree, V> : SearchTree> { } } - private fun leftRotation(node: RBTreeNode) { + private fun leftRotate(node: RBTreeNode) { val rightNode = node.right ?: return node.right = rightNode.left @@ -248,7 +248,7 @@ class RBTree, V> : SearchTree> { node.parent = rightNode } - private fun rightRotation(node: RBTreeNode) { + private fun rightRotate(node: RBTreeNode) { val leftNode = node.left ?: return node.left = leftNode.right From 3abdc842bdd62d14f3c7853918baf7f77af390e2 Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Mon, 1 Apr 2024 13:57:10 +0300 Subject: [PATCH 058/130] refactor(AVL-T): implemented removeNode method along with auxiliary methods --- lib/src/main/kotlin/tree/AVLTree.kt | 44 +++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/lib/src/main/kotlin/tree/AVLTree.kt b/lib/src/main/kotlin/tree/AVLTree.kt index 71f88c7..4fe900d 100644 --- a/lib/src/main/kotlin/tree/AVLTree.kt +++ b/lib/src/main/kotlin/tree/AVLTree.kt @@ -73,19 +73,23 @@ class AVLTree, V> : SearchTree>() { } } } + return root } private fun insertRecursive(root: AVLTreeNode?, node: AVLTreeNode?): AVLTreeNode? { if (root == null) { return node - } else if (node != null) { + } + + if (node != null) { if (root.key > node.key) { root.left = insertRecursive(root.left, node) } else if (root.key < node.key) { root.right = insertRecursive(root.right, node) } } + return rebalanced(root, node) } @@ -93,8 +97,44 @@ class AVLTree, V> : SearchTree>() { root = insertRecursive(root, node) } + private fun minValueNode(node: AVLTreeNode): AVLTreeNode { + var current = node + val curLeft = current.left + while (curLeft != null) current = curLeft + return current + } + private fun removeRecursive(root: AVLTreeNode?, node: AVLTreeNode): AVLTreeNode? { + var rootNode = root + + if (rootNode == null) { + return root + } + + if (rootNode.key > node.key) { + rootNode.left = removeRecursive(rootNode.left, node) + } else if (rootNode.key < node.key) { + rootNode.right = removeRecursive(rootNode.right, node) + } else { + val rootNodeRight = rootNode.right + val rootNodeLeft = rootNode.left + if (rootNode.left == null || rootNode.right == null) { + rootNode = if (rootNode.left == null) rootNodeRight else rootNodeLeft + } else { + val mostLeftChild: AVLTreeNode? = rootNode.right?.let { minValueNode(it) } + rootNode = mostLeftChild + rootNode?.right = rootNode?.let { removeRecursive(rootNode.right, it) } + } + } + + if (rootNode == null) { + return root + } + + return rebalanced(rootNode, node) + } + override fun removeNode(node: AVLTreeNode) { - TODO("Remove node in tree") + root = removeRecursive(root, node) } override fun createNode(key: K, value: V): AVLTreeNode { From 1711e3c6b1824bbe4e432d2c82d2184b1eaa809d Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Mon, 1 Apr 2024 17:07:22 +0300 Subject: [PATCH 059/130] feat: add method inOrderTraversal --- lib/src/main/kotlin/tree/SearchTree.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index 0063958..1da4303 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -144,7 +144,14 @@ abstract class SearchTree, V, Node : BinaryTreeNode) -> (Unit)) { - TODO("Symmetrical tree traversal") + fun inOrder(node: Node?) { + if (node != null) { + inOrder(node.left) + action(Pair(node.key, node.value)) + inOrder(node.right) + } + } + inOrder(this.root) } /** From 2711d2be510845a9c7b59a97bb525d3b3235e0b3 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Mon, 1 Apr 2024 17:10:41 +0300 Subject: [PATCH 060/130] feat: add method predecessor --- lib/src/main/kotlin/tree/SearchTree.kt | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index 1da4303..af8e60b 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -122,8 +122,20 @@ abstract class SearchTree, V, Node : BinaryTreeNode { - TODO("Returns the previous ascending key") + fun predecessor(key: K): Pair { + var node = root + var predecessor: Node? = root?.left + + while (node != null) { + if (node.key < key) { + predecessor = node + node = node.right + } else { + node = node.left + } + } + + return Pair(predecessor?.key, predecessor?.value) } /** From 9f36f1284ec800e5c0d17fcabae5843fd58bda29 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Mon, 1 Apr 2024 17:12:04 +0300 Subject: [PATCH 061/130] feat: add method successor --- lib/src/main/kotlin/tree/SearchTree.kt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index af8e60b..25b49b7 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -116,7 +116,19 @@ abstract class SearchTree, V, Node : BinaryTreeNode { - TODO("Returns the next ascending key") + var node = root + var successor: Node? = null + + while (node != null) { + if (node.key > key) { + successor = node + node = node.left + } else { + node = node.right + } + } + + return Pair(successor?.key, successor?.value) } /** From 28f266a3192b1818763b7ef0e07d71b8dff5e894 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Mon, 1 Apr 2024 17:13:12 +0300 Subject: [PATCH 062/130] feat: add method getMin --- lib/src/main/kotlin/tree/SearchTree.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index 25b49b7..fdc5bef 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -102,7 +102,11 @@ abstract class SearchTree, V, Node : BinaryTreeNode { - TODO("Returns nodes with the minimum key") + var node = root + while (node?.left != null) { + node = node.left + } + return Pair(node?.key, node?.value) } /** From 012efc3161ae8f3cdb518a6b99710b367d16bdf5 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Mon, 1 Apr 2024 17:14:20 +0300 Subject: [PATCH 063/130] feat: add method getEntities --- lib/src/main/kotlin/tree/SearchTree.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index fdc5bef..333df91 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -95,7 +95,11 @@ abstract class SearchTree, V, Node : BinaryTreeNode> { - TODO("Returns a complete list of pair key value") + val result = emptyArray>() + var index = 0 + + inOrderTraversal { result[index] = it; index++ } + return result } /** From 5c94f1ab91903767928c350cfb82e8457c3c6c70 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Mon, 1 Apr 2024 18:30:13 +0300 Subject: [PATCH 064/130] refactor: add empty line in methods getMin and inOrderTraversal --- lib/src/main/kotlin/tree/SearchTree.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index 333df91..74a5e4d 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -110,6 +110,7 @@ abstract class SearchTree, V, Node : BinaryTreeNode, V, Node : BinaryTreeNode Date: Mon, 1 Apr 2024 19:55:52 +0300 Subject: [PATCH 065/130] feat: implements getKeys and getValues methods --- lib/src/main/kotlin/tree/SearchTree.kt | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index 868439d..2d57828 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -99,19 +99,31 @@ abstract class SearchTree, V, Node : BinaryTreeNode { - TODO("Returns a complete list of keys") + fun getKeys(): List { + val result = listOf() + + inOrderTraversal { + result.addLast(it.first) + } + + return result } /** * Returns a complete list of values. */ - fun getValues(): Array { - TODO("Returns a complete list of values") + fun getValues(): List { + val result = listOf() + + inOrderTraversal { + result.addLast(it.second) + } + + return result } /** @@ -207,7 +219,7 @@ abstract class SearchTree, V, Node : BinaryTreeNode Date: Mon, 1 Apr 2024 22:20:10 +0300 Subject: [PATCH 066/130] refactor(AVL-T): added lines for easier code readability --- lib/src/main/kotlin/tree/AVLTree.kt | 57 +++++++++++++++-------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/lib/src/main/kotlin/tree/AVLTree.kt b/lib/src/main/kotlin/tree/AVLTree.kt index 4fe900d..b426a8e 100644 --- a/lib/src/main/kotlin/tree/AVLTree.kt +++ b/lib/src/main/kotlin/tree/AVLTree.kt @@ -52,27 +52,26 @@ class AVLTree, V> : SearchTree>() { val rootRight = root?.right if (node != null && balance != null){ - if (balance > 1) { - if (rootLeft != null) { - if (node.key < rootLeft.key) { - return rotateRight(root) - } else { - root.left = root.left?.let { rotateLeft(it) } - return rotateRight(root) - } + if (balance > 1 && rootLeft != null) { + if (node.key < rootLeft.key) { + + return rotateRight(root) } + + root.left = root.left?.let { rotateLeft(it) } + return rotateRight(root) } - if (balance < -1) { - if (rootRight != null) { - if (node.key > rootRight.key) { - return rotateLeft(root) - } else { - root.right = root.right?.let { rotateRight(it) } - return rotateLeft(root) - } + + if (balance < -1 && rootRight != null) { + if (node.key > rootRight.key) { + return rotateLeft(root) + } + + root.right = root.right?.let { rotateRight(it) } + + return rotateLeft(root) } } - } return root } @@ -86,7 +85,7 @@ class AVLTree, V> : SearchTree>() { if (root.key > node.key) { root.left = insertRecursive(root.left, node) } else if (root.key < node.key) { - root.right = insertRecursive(root.right, node) + root.right = insertRecursive(root.right, node) } } @@ -101,8 +100,10 @@ class AVLTree, V> : SearchTree>() { var current = node val curLeft = current.left while (curLeft != null) current = curLeft + return current } + private fun removeRecursive(root: AVLTreeNode?, node: AVLTreeNode): AVLTreeNode? { var rootNode = root @@ -112,18 +113,20 @@ class AVLTree, V> : SearchTree>() { if (rootNode.key > node.key) { rootNode.left = removeRecursive(rootNode.left, node) + return rebalanced(rootNode, node) } else if (rootNode.key < node.key) { rootNode.right = removeRecursive(rootNode.right, node) + return rebalanced(rootNode, node) + } + + val rootNodeRight = rootNode.right + val rootNodeLeft = rootNode.left + if (rootNode.left == null || rootNode.right == null) { + rootNode = if (rootNode.left == null) rootNodeRight else rootNodeLeft } else { - val rootNodeRight = rootNode.right - val rootNodeLeft = rootNode.left - if (rootNode.left == null || rootNode.right == null) { - rootNode = if (rootNode.left == null) rootNodeRight else rootNodeLeft - } else { - val mostLeftChild: AVLTreeNode? = rootNode.right?.let { minValueNode(it) } - rootNode = mostLeftChild - rootNode?.right = rootNode?.let { removeRecursive(rootNode.right, it) } - } + val mostLeftChild: AVLTreeNode? = rootNode.right?.let { minValueNode(it) } + rootNode = mostLeftChild + rootNode?.right = rootNode?.let { removeRecursive(rootNode.right, it) } } if (rootNode == null) { From c282e91c6b4da6ca98a532159551bd8b510f40f1 Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Mon, 1 Apr 2024 22:26:55 +0300 Subject: [PATCH 067/130] refactor(AVL-T): used ready-made variables for easy readability of the code --- lib/src/main/kotlin/tree/AVLTree.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/src/main/kotlin/tree/AVLTree.kt b/lib/src/main/kotlin/tree/AVLTree.kt index b426a8e..1709647 100644 --- a/lib/src/main/kotlin/tree/AVLTree.kt +++ b/lib/src/main/kotlin/tree/AVLTree.kt @@ -121,12 +121,12 @@ class AVLTree, V> : SearchTree>() { val rootNodeRight = rootNode.right val rootNodeLeft = rootNode.left - if (rootNode.left == null || rootNode.right == null) { - rootNode = if (rootNode.left == null) rootNodeRight else rootNodeLeft + if (rootNodeLeft == null || rootNodeRight == null) { + rootNode = rootNodeLeft ?: rootNodeRight } else { - val mostLeftChild: AVLTreeNode? = rootNode.right?.let { minValueNode(it) } + val mostLeftChild: AVLTreeNode = minValueNode(rootNodeRight) rootNode = mostLeftChild - rootNode?.right = rootNode?.let { removeRecursive(rootNode.right, it) } + rootNode.right = removeRecursive(rootNode.right, rootNode) } if (rootNode == null) { From 08fe10b895776cb963e05e2f13e0ba9893ff2b37 Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Mon, 1 Apr 2024 22:30:54 +0300 Subject: [PATCH 068/130] fix(AVL-T): fixed infinite loop bug in minValueNode --- lib/src/main/kotlin/tree/AVLTree.kt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/src/main/kotlin/tree/AVLTree.kt b/lib/src/main/kotlin/tree/AVLTree.kt index 1709647..1f44f50 100644 --- a/lib/src/main/kotlin/tree/AVLTree.kt +++ b/lib/src/main/kotlin/tree/AVLTree.kt @@ -97,9 +97,13 @@ class AVLTree, V> : SearchTree>() { } private fun minValueNode(node: AVLTreeNode): AVLTreeNode { - var current = node - val curLeft = current.left - while (curLeft != null) current = curLeft + var current: AVLTreeNode = node + var leftNode = current.left + + while (leftNode != null) { + current = leftNode + leftNode = current.left + } return current } From 9dfde1839c723871422b86d651115e21c4c30041 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Tue, 2 Apr 2024 01:15:01 +0300 Subject: [PATCH 069/130] fix: change return type in method getEntities --- lib/src/main/kotlin/tree/SearchTree.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index 2d57828..b762338 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -129,11 +129,11 @@ abstract class SearchTree, V, Node : BinaryTreeNode> { - val result = emptyArray>() - var index = 0 + fun getEntities(): List> { + val result = mutableListOf>() + + inOrderTraversal { result.add(it) } - inOrderTraversal { result[index] = it; index++ } return result } From bc3a9a5dcd45e4a661afc66444c19c1b8f999f8a Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Tue, 2 Apr 2024 14:43:34 +0300 Subject: [PATCH 070/130] fix: fix getValues and getKeys methods --- lib/src/main/kotlin/tree/SearchTree.kt | 484 ++++++++++++------------- 1 file changed, 242 insertions(+), 242 deletions(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index b762338..6952120 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -1,242 +1,242 @@ -package tree - -import tree.node.BinaryTreeNode - -abstract class SearchTree, V, Node : BinaryTreeNode>() { - protected var root: Node? = null - var size: Long = 0 - private set - var recentlyKey: K? = null - private set - - constructor(key: K, value: V) : this() { - set(key, value) - } - - constructor(pairs: Array>) : this() { - set(pairs) - } - - protected abstract fun insertNode(node: Node) - protected abstract fun removeNode(node: Node) - protected abstract fun createNode(key: K, value: V): Node - - /** - * Finding a node in a tree by key - */ - protected fun searchNode(key: K): Node? { - var node = root - - while (node != null) { - if (key < node.key) { - node = node.left - } else if (key > node.key) { - node = node.right - } else { - return node - } - } - - return null - } - - /** - * Stores the value for the given key. Return previous value. - */ - fun set(key: K, value: V): V? { - recentlyKey = key - val node = searchNode(key) - - if (node == null) { - insertNode(createNode(key, value)) - size++ - return null - } - - val result = node.value - node.value = value - return result - } - - /** - * Stores the values for the given keys. Return previous values. - */ - fun set(pairs: Array>): Array { - TODO("Adding multiple node in a tree if there is no such node in the tree") - } - - /** - * Stores the value for the given key if there is no pair with that key. Return previous value. - */ - fun setIfEmpty(key: K, value: V): V? { - TODO("Adding a node if such a node already exists in the tree") - } - - /** - * Stores the values for the given keys if there is no pair with that key. Return previous values. - */ - fun setIfEmpty(pairs: Array>): Array { - TODO("Adding several nodes if such a node already exists in the tree") - } - - /** - * Remove the value for the given key. Return previous value. - */ - fun remove(key: K): V? { - TODO("Adding multiple nodes if such nodes already exist in the tree") - } - - /** - * Remove the values for the given keys. Return previous values. - */ - fun remove(keys: Array): Array { - TODO("Removing multiple catches by keys") - } - - /** - * Return the value for the given key. - */ - fun search(key: K): V? { - return searchNode(key)?.value - } - - /** - * Returns a complete list of keys. - */ - fun getKeys(): List { - val result = listOf() - - inOrderTraversal { - result.addLast(it.first) - } - - return result - } - - /** - * Returns a complete list of values. - */ - fun getValues(): List { - val result = listOf() - - inOrderTraversal { - result.addLast(it.second) - } - - return result - } - - /** - * Returns a complete list of pairs key value. - */ - fun getEntities(): List> { - val result = mutableListOf>() - - inOrderTraversal { result.add(it) } - - return result - } - - /** - * Returns pair with the minimum key. - */ - fun getMin(): Pair { - var node = root - while (node?.left != null) { - node = node.left - } - - return Pair(node?.key, node?.value) - } - - /** - * Returns pair with the maximum key. - */ - fun getMax(): Pair { - TODO("Returns nodes with the maximum key") - } - - /** - * Returns the pair with next ascending key - */ - fun successor(key: K): Pair { - var node = root - var successor: Node? = null - - while (node != null) { - if (node.key > key) { - successor = node - node = node.left - } else { - node = node.right - } - } - - return Pair(successor?.key, successor?.value) - } - - /** - * Returns the pair with previous ascending key - */ - fun predecessor(key: K): Pair { - var node = root - var predecessor: Node? = root?.left - - while (node != null) { - if (node.key < key) { - predecessor = node - node = node.right - } else { - node = node.left - } - } - - return Pair(predecessor?.key, predecessor?.value) - } - - /** - * Remove all keys in a tree. - */ - fun clear() { - TODO("Removing all nodes in a tree") - } - - /** - * Apply [action] on all pairs by preorder tree traversal. - */ - fun preOrderTraversal(action: (Pair) -> (Unit)) { - TODO("Prefix tree traversal") - } - - /** - * Apply [action] on all pairs by inorder tree traversal. - */ - fun inOrderTraversal(action: (Pair) -> (Unit)) { - fun inOrder(node: Node?) { - if (node != null) { - inOrder(node.left) - action(Pair(node.key, node.value)) - inOrder(node.right) - } - } - - inOrder(this.root) - } - - /** - * Apply [action] on all pairs by postorder tree traversal. - */ - fun postOrderTraversal(action: (Pair) -> (Unit)) { - val root = this.root ?: return - - fun helper(node: Node?) { - if (node == null) return - - helper(node.left) - helper(node.right) - action(Pair(node.key, node.value)) - } - - helper(root) - } -} +package tree + +import tree.node.BinaryTreeNode + +abstract class SearchTree, V, Node : BinaryTreeNode>() { + protected var root: Node? = null + var size: Long = 0 + private set + var recentlyKey: K? = null + private set + + constructor(key: K, value: V) : this() { + set(key, value) + } + + constructor(pairs: Array>) : this() { + set(pairs) + } + + protected abstract fun insertNode(node: Node) + protected abstract fun removeNode(node: Node) + protected abstract fun createNode(key: K, value: V): Node + + /** + * Finding a node in a tree by key + */ + protected fun searchNode(key: K): Node? { + var node = root + + while (node != null) { + if (key < node.key) { + node = node.left + } else if (key > node.key) { + node = node.right + } else { + return node + } + } + + return null + } + + /** + * Stores the value for the given key. Return previous value. + */ + fun set(key: K, value: V): V? { + recentlyKey = key + val node = searchNode(key) + + if (node == null) { + insertNode(createNode(key, value)) + size++ + return null + } + + val result = node.value + node.value = value + return result + } + + /** + * Stores the values for the given keys. Return previous values. + */ + fun set(pairs: Array>): Array { + TODO("Adding multiple node in a tree if there is no such node in the tree") + } + + /** + * Stores the value for the given key if there is no pair with that key. Return previous value. + */ + fun setIfEmpty(key: K, value: V): V? { + TODO("Adding a node if such a node already exists in the tree") + } + + /** + * Stores the values for the given keys if there is no pair with that key. Return previous values. + */ + fun setIfEmpty(pairs: Array>): Array { + TODO("Adding several nodes if such a node already exists in the tree") + } + + /** + * Remove the value for the given key. Return previous value. + */ + fun remove(key: K): V? { + TODO("Adding multiple nodes if such nodes already exist in the tree") + } + + /** + * Remove the values for the given keys. Return previous values. + */ + fun remove(keys: Array): Array { + TODO("Removing multiple catches by keys") + } + + /** + * Return the value for the given key. + */ + fun search(key: K): V? { + return searchNode(key)?.value + } + + /** + * Returns a complete list of keys. + */ + fun getKeys(): List { + val result = mutableListOf() + + inOrderTraversal { + result.add(it.first) + } + + return result + } + + /** + * Returns a complete list of values. + */ + fun getValues(): List { + val result = mutableListOf() + + inOrderTraversal { + result.add(it.second) + } + + return result + } + + /** + * Returns a complete list of pairs key value. + */ + fun getEntities(): List> { + val result = mutableListOf>() + + inOrderTraversal { result.add(it) } + + return result + } + + /** + * Returns pair with the minimum key. + */ + fun getMin(): Pair { + var node = root + while (node?.left != null) { + node = node.left + } + + return Pair(node?.key, node?.value) + } + + /** + * Returns pair with the maximum key. + */ + fun getMax(): Pair { + TODO("Returns nodes with the maximum key") + } + + /** + * Returns the pair with next ascending key + */ + fun successor(key: K): Pair { + var node = root + var successor: Node? = null + + while (node != null) { + if (node.key > key) { + successor = node + node = node.left + } else { + node = node.right + } + } + + return Pair(successor?.key, successor?.value) + } + + /** + * Returns the pair with previous ascending key + */ + fun predecessor(key: K): Pair { + var node = root + var predecessor: Node? = root?.left + + while (node != null) { + if (node.key < key) { + predecessor = node + node = node.right + } else { + node = node.left + } + } + + return Pair(predecessor?.key, predecessor?.value) + } + + /** + * Remove all keys in a tree. + */ + fun clear() { + TODO("Removing all nodes in a tree") + } + + /** + * Apply [action] on all pairs by preorder tree traversal. + */ + fun preOrderTraversal(action: (Pair) -> (Unit)) { + TODO("Prefix tree traversal") + } + + /** + * Apply [action] on all pairs by inorder tree traversal. + */ + fun inOrderTraversal(action: (Pair) -> (Unit)) { + fun inOrder(node: Node?) { + if (node != null) { + inOrder(node.left) + action(Pair(node.key, node.value)) + inOrder(node.right) + } + } + + inOrder(this.root) + } + + /** + * Apply [action] on all pairs by postorder tree traversal. + */ + fun postOrderTraversal(action: (Pair) -> (Unit)) { + val root = this.root ?: return + + fun helper(node: Node?) { + if (node == null) return + + helper(node.left) + helper(node.right) + action(Pair(node.key, node.value)) + } + + helper(root) + } +} From cfb0356e305233f738d84939b5093749c2970db0 Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Wed, 3 Apr 2024 02:28:01 +0300 Subject: [PATCH 071/130] feat: added set method for arrays --- lib/src/main/kotlin/tree/SearchTree.kt | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index 6952120..eabafdc 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -61,8 +61,25 @@ abstract class SearchTree, V, Node : BinaryTreeNode>): Array { - TODO("Adding multiple node in a tree if there is no such node in the tree") + fun set(pairs: Array>): MutableList { + val listValue = mutableListOf() + + for (pair in pairs) { + recentlyKey = pair.first + val nodeToInsert = searchNode(pair.first) + + if (nodeToInsert == null) { + insertNode(createNode(pair.first, pair.second)) + size++ + listValue.add(null) + } else { + val result = nodeToInsert.value + nodeToInsert.value = pair.second + listValue.add(result) + } + } + + return listValue } /** From 5af73f9092cce7dc112fd12edf5deca814e20e75 Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Wed, 3 Apr 2024 02:51:38 +0300 Subject: [PATCH 072/130] feat: added setIfEmpty method --- lib/src/main/kotlin/tree/SearchTree.kt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index eabafdc..cbe2442 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -86,7 +86,16 @@ abstract class SearchTree, V, Node : BinaryTreeNode Date: Wed, 3 Apr 2024 03:00:15 +0300 Subject: [PATCH 073/130] feat: added setIfEmpty method for arrays --- lib/src/main/kotlin/tree/SearchTree.kt | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index cbe2442..6350860 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -101,8 +101,24 @@ abstract class SearchTree, V, Node : BinaryTreeNode>): Array { - TODO("Adding several nodes if such a node already exists in the tree") + fun setIfEmpty(pairs: Array>): MutableList { + val listValue = mutableListOf() + + for (pair in pairs) { + val node = searchNode(pair.first) + + if (node == null) { + recentlyKey = pair.first + insertNode(createNode(pair.first, pair.second)) + size++ + listValue.add(null) + } + else{ + listValue.add(node.value) + } + } + + return listValue } /** From 6d632dff0ec7947edde2edb9e60ddcada09f90c8 Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Wed, 3 Apr 2024 03:06:57 +0300 Subject: [PATCH 074/130] feat: added remove method --- lib/src/main/kotlin/tree/SearchTree.kt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index 6350860..680df61 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -125,7 +125,15 @@ abstract class SearchTree, V, Node : BinaryTreeNode Date: Wed, 3 Apr 2024 03:11:18 +0300 Subject: [PATCH 075/130] feat: added remove method for arrays --- lib/src/main/kotlin/tree/SearchTree.kt | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index 680df61..27fb8bd 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -139,8 +139,23 @@ abstract class SearchTree, V, Node : BinaryTreeNode): Array { - TODO("Removing multiple catches by keys") + fun remove(keys: Array): MutableList { + val listValue = mutableListOf() + + for (key in keys) { + val node = searchNode(key) + + if (node != null) { + removeNode(node) + size-- + listValue.add(node.value) + } + else { + listValue.add(null) + } + } + + return listValue } /** From fa83af85e9fe17e384ffc0fdc4e5edbedd973cd0 Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Wed, 3 Apr 2024 03:13:31 +0300 Subject: [PATCH 076/130] feat: added getMax method --- lib/src/main/kotlin/tree/SearchTree.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index 27fb8bd..3671e8d 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -218,7 +218,11 @@ abstract class SearchTree, V, Node : BinaryTreeNode { - TODO("Returns nodes with the maximum key") + var node = root + while (node?.right != null) { + node = node.right + } + return Pair(node?.key, node?.value) } /** From d51ebfa7171aeaea61d9473bf9b87579b75d8694 Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Wed, 3 Apr 2024 03:31:28 +0300 Subject: [PATCH 077/130] feat: added clear method --- lib/src/main/kotlin/tree/SearchTree.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index 3671e8d..a668e77 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -267,7 +267,8 @@ abstract class SearchTree, V, Node : BinaryTreeNode Date: Wed, 3 Apr 2024 13:51:54 +0300 Subject: [PATCH 078/130] feat: added preOrderTraversal method --- lib/src/main/kotlin/tree/SearchTree.kt | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index a668e77..69577f5 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -275,7 +275,18 @@ abstract class SearchTree, V, Node : BinaryTreeNode) -> (Unit)) { - TODO("Prefix tree traversal") + val root = this.root ?: return + + fun preOrder(node: Node?) { + if (node == null) return + + action(Pair(node.key, node.value)) + preOrder(node.left) + preOrder(node.right) + + } + + preOrder(root) } /** From c5019db87b731d2ba7d8e416189c8c28a59e1430 Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Wed, 3 Apr 2024 14:32:02 +0300 Subject: [PATCH 079/130] refactor: optimized methods set, setIfEmpty, remove --- lib/src/main/kotlin/tree/SearchTree.kt | 36 +++----------------------- 1 file changed, 3 insertions(+), 33 deletions(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index 69577f5..a12dcb5 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -65,18 +65,7 @@ abstract class SearchTree, V, Node : BinaryTreeNode() for (pair in pairs) { - recentlyKey = pair.first - val nodeToInsert = searchNode(pair.first) - - if (nodeToInsert == null) { - insertNode(createNode(pair.first, pair.second)) - size++ - listValue.add(null) - } else { - val result = nodeToInsert.value - nodeToInsert.value = pair.second - listValue.add(result) - } + listValue.add(set(pair.first, pair.second)) } return listValue @@ -105,17 +94,7 @@ abstract class SearchTree, V, Node : BinaryTreeNode() for (pair in pairs) { - val node = searchNode(pair.first) - - if (node == null) { - recentlyKey = pair.first - insertNode(createNode(pair.first, pair.second)) - size++ - listValue.add(null) - } - else{ - listValue.add(node.value) - } + listValue.add(setIfEmpty(pair.first, pair.second)) } return listValue @@ -143,16 +122,7 @@ abstract class SearchTree, V, Node : BinaryTreeNode() for (key in keys) { - val node = searchNode(key) - - if (node != null) { - removeNode(node) - size-- - listValue.add(node.value) - } - else { - listValue.add(null) - } + listValue.add(remove(key)) } return listValue From 0f3e4104c4a14eacc175a68cf943fd08b6214e04 Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Tue, 2 Apr 2024 15:02:45 +0300 Subject: [PATCH 080/130] test: add some basic tests --- lib/src/test/kotlin/tree/RBTreeTest.kt | 27 ++++++ lib/src/test/kotlin/tree/SearchTreeTest.kt | 101 +++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 lib/src/test/kotlin/tree/RBTreeTest.kt create mode 100644 lib/src/test/kotlin/tree/SearchTreeTest.kt diff --git a/lib/src/test/kotlin/tree/RBTreeTest.kt b/lib/src/test/kotlin/tree/RBTreeTest.kt new file mode 100644 index 0000000..2716e55 --- /dev/null +++ b/lib/src/test/kotlin/tree/RBTreeTest.kt @@ -0,0 +1,27 @@ +package tree + +import org.junit.jupiter.api.Test + +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Nested +import tree.node.RBTreeNode + +class RBTreeTest { + private lateinit var rbt: RBTree + + @BeforeEach + fun setup() { + rbt = RBTree() + } + + @Nested + inner class `Insertion tests` { + @Test + fun `set one key on empty tree`() { + rbt.set(1, "Homka") + assertEquals(1, rbt.size) + assertEquals("Homka", rbt.search(1)) + } + } +} \ No newline at end of file diff --git a/lib/src/test/kotlin/tree/SearchTreeTest.kt b/lib/src/test/kotlin/tree/SearchTreeTest.kt new file mode 100644 index 0000000..48f4f6a --- /dev/null +++ b/lib/src/test/kotlin/tree/SearchTreeTest.kt @@ -0,0 +1,101 @@ +package tree + +import org.junit.jupiter.api.Test + +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Nested + +class SearchTreeTest { + private lateinit var bst: BSTree + private val bstWithoutNodes = BSTree() + + @BeforeEach + fun setup() { + bst = BSTree() + bst.set(5, "A") + bst.set(8, "A") + bst.set(6, "A") + bst.set(1, "A") + bst.set(2, "A") + bst.set(4, "A") + bst.set(3, "A") + bst.set(10, "A") + } + + @Nested + inner class `Min and max tests` { + @Test + fun `getMin() return right pair`() { + assertEquals(Pair(1, "A"), bst.getMin()) + } + + @Test + fun `getMax() return right pair`() { + assertEquals(Pair(10, "A"), bst.getMax()) + } + + @Test + fun `getMin() return pair of nulls on empty tree`() { + assertEquals(Pair(null, null), bstWithoutNodes.getMin()) + } + + @Test + fun `getMax() return pair of nulls on empty tree`() { + assertEquals(Pair(null, null), bstWithoutNodes.getMax()) + } + } + + @Nested + inner class `Clear tests` { + @Test + fun `clear() removes all nodes from tree`() { + bst.clear() + assertEquals(0, bst.size) + assertEquals(emptyList(), bst.getValues()) + } + + @Test + fun `clear() works fine on empty tree`() { + bst.clear() + bst.clear() + assertEquals(0, bst.size) + assertEquals(emptyList(), bst.getValues()) + } + } + + @Nested + inner class `Successor and predecessor tests`() { + @Test + fun `successor() test with existed keys`() { + assertEquals(Pair(2, "A"), bst.successor(1)) + assertEquals(Pair(3, "A"), bst.successor(2)) + assertEquals(Pair(4, "A"), bst.successor(3)) + assertEquals(Pair(5, "A"), bst.successor(4)) + assertEquals(Pair(6, "A"), bst.successor(5)) + assertEquals(Pair(8, "A"), bst.successor(6)) + assertEquals(Pair(10, "A"), bst.successor(8)) + } + + @Test + fun `successor() if key don't exists it return next key`() { + assertEquals(Pair(8, "A"), bst.successor(7)) + } + + @Test + fun `predecessor() if key don't exists it return previous key`() { + assertEquals(Pair(6, "A"), bst.predecessor(7)) + } + + @Test + fun `predecessor() test with existed keys`() { + assertEquals(Pair(1, "A"), bst.predecessor(2)) + assertEquals(Pair(2, "A"), bst.predecessor(3)) + assertEquals(Pair(3, "A"), bst.predecessor(4)) + assertEquals(Pair(4, "A"), bst.predecessor(5)) + assertEquals(Pair(5, "A"), bst.predecessor(6)) + assertEquals(Pair(6, "A"), bst.predecessor(8)) + assertEquals(Pair(8, "A"), bst.predecessor(10)) + } + } +} \ No newline at end of file From 849c07940410ebfa0a5f6ce908baa77b8e4ef93c Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Wed, 3 Apr 2024 02:13:28 +0300 Subject: [PATCH 081/130] test: add jacoco support --- lib/build.gradle.kts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 6e8f86e..8cb3007 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -11,6 +11,7 @@ plugins { // Apply the java-library plugin for API and implementation separation. `java-library` + jacoco } repositories { @@ -24,6 +25,7 @@ dependencies { // Use the JUnit 5 integration. testImplementation(libs.junit.jupiter.engine) + testImplementation("org.junit.jupiter:junit-jupiter:5.8.1") testRuntimeOnly("org.junit.platform:junit-platform-launcher") @@ -44,4 +46,16 @@ java { tasks.named("test") { // Use JUnit Platform for unit tests. useJUnitPlatform() + finalizedBy(tasks.jacocoTestReport) +} + +tasks.jacocoTestReport { + dependsOn(tasks.named("test")) // tests are required to run before generating the report + + reports { + xml.required = false + csv.required = false + html.required = true + html.outputLocation = layout.buildDirectory.dir("jacocoHtml") + } } From 48d8a531c36a37c80b76cd19ecc10a9ef2be8994 Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Wed, 3 Apr 2024 02:14:45 +0300 Subject: [PATCH 082/130] test(RBT): add constructors tests --- lib/src/test/kotlin/tree/RBTreeTest.kt | 38 +++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/lib/src/test/kotlin/tree/RBTreeTest.kt b/lib/src/test/kotlin/tree/RBTreeTest.kt index 2716e55..5d8fa37 100644 --- a/lib/src/test/kotlin/tree/RBTreeTest.kt +++ b/lib/src/test/kotlin/tree/RBTreeTest.kt @@ -5,7 +5,6 @@ import org.junit.jupiter.api.Test import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Nested -import tree.node.RBTreeNode class RBTreeTest { private lateinit var rbt: RBTree @@ -15,6 +14,43 @@ class RBTreeTest { rbt = RBTree() } + @Nested + inner class `Constructor tests` { + @Test + fun `without args`() { + assertEquals(0, RBTree().size) + assertEquals(0, RBTree().getEntities().size) + } + + @Test + fun `one entity`() { + val rbt = RBTree(1, "Homka") + assertEquals("Homka", rbt.search(1)) + } + + @Test + fun `array of entities`() { + val entities = arrayOf( + Pair(35, 1), + Pair(21, 1), + Pair(25, 1), + Pair(62, 1), + Pair(12, 1), + Pair(62, 1), + Pair(122, 1), + Pair(621, 1), + Pair(121, 1), + Pair(362, 1), + Pair(35, 1), + Pair(523, 1), + ) + + val rbt = RBTree(entities) + assertEquals(10, rbt.size) + assertEquals(listOf(12, 21, 25, 35, 62, 121, 122, 362, 523, 621), rbt.getKeys()) + } + } + @Nested inner class `Insertion tests` { @Test From 415270f5ae654311e03274ddf307e614307a2e78 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Wed, 3 Apr 2024 20:28:12 +0300 Subject: [PATCH 083/130] test: add test for BSTree --- lib/src/test/kotlin/tree/BSTreeTest.kt | 106 +++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 lib/src/test/kotlin/tree/BSTreeTest.kt diff --git a/lib/src/test/kotlin/tree/BSTreeTest.kt b/lib/src/test/kotlin/tree/BSTreeTest.kt new file mode 100644 index 0000000..3816138 --- /dev/null +++ b/lib/src/test/kotlin/tree/BSTreeTest.kt @@ -0,0 +1,106 @@ +package tree + +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test + +class BSTreeTest { + private lateinit var bst: BSTree + private val bstEmpty = BSTree() + + @BeforeEach + fun setup() { + bst = BSTree() + bst.set(2, "B") + bst.set(3, "C") + bst.set(4, "D") + bst.set(6, "F") + bst.set(7, "G") + bst.set(8, "H") + } + + @Nested + inner class `Insert tests` { + @Test + fun `set new min key`() { + assertEquals(null, bst.set(1, "A")) + assertEquals(Pair(1, "A"), bst.getMin()) + assertEquals(7, bst.size) + } + + @Test + fun `set new max key`() { + assertEquals(null, bst.set(9, "I")) + assertEquals(Pair(9, "I"), bst.getMax()) + assertEquals(7, bst.size) + } + + @Test + fun `set new key inside tree`() { + assertEquals(null, bst.set(5, "E")) + assertEquals("E", bst.search(5)) + assertEquals(Pair(5, "E"), bst.predecessor(6)) + assertEquals(Pair(5, "E"), bst.successor(4)) + assertEquals(7, bst.size) + } + + @Test + fun `set the same key`() { + assertEquals("G", bst.set(7, "g")) + assertEquals("g", bst.search(7)) + assertEquals(Pair(7, "g"), bst.predecessor(8)) + assertEquals(Pair(7, "g"), bst.successor(6)) + assertEquals(6, bst.size) + } + + @Test + fun `set key in empty tree`() { + bstEmpty.set(1, "A") + assertEquals(listOf(Pair(1, "A")), bstEmpty.getEntities()) + assertEquals(Pair(null, null), bstEmpty.predecessor(1)) + assertEquals(Pair(null, null), bstEmpty.successor(1)) + assertEquals(1, bstEmpty.size) + } + } + + @Nested + inner class `Remove tests` { + @Test + fun `remove key without child`() { + assertEquals("B", bst.remove(2)) + assertEquals(Pair(3, "C"), bst.getMin()) + assertEquals(Pair(null, null), bst.predecessor(3)) + assertEquals(5, bst.size) + } + + @Test + fun `remove key with one child`() { + assertEquals("C", bst.remove(3)) + assertEquals(Pair(2, "B"), bst.predecessor(4)) + assertEquals(Pair(4, "D"), bst.successor(2)) + assertEquals(5, bst.size) + } + + @Test + fun `remove key that is not in the tree`() { + assertEquals("A", bst.remove(1)) + // + } + + @Test + fun `remove key from empty tree`() { + assertEquals("A", bstEmpty.remove(1)) + // + } + } + + @Nested + inner class `Create tests` { + @Test + fun `insert new node`() { + assertEquals(null, bst.set(1, "A")) + assertEquals("A", bst.search(1)) + } + } +} \ No newline at end of file From e0b74c7f15855974407a5298b1eddda588a3b6e2 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Wed, 3 Apr 2024 22:27:09 +0300 Subject: [PATCH 084/130] test: add insert test and change remove test for BSTree --- lib/src/test/kotlin/tree/BSTreeTest.kt | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/lib/src/test/kotlin/tree/BSTreeTest.kt b/lib/src/test/kotlin/tree/BSTreeTest.kt index 3816138..084f236 100644 --- a/lib/src/test/kotlin/tree/BSTreeTest.kt +++ b/lib/src/test/kotlin/tree/BSTreeTest.kt @@ -7,6 +7,7 @@ import org.junit.jupiter.api.Test class BSTreeTest { private lateinit var bst: BSTree + private lateinit var bstTwoNode: BSTree private val bstEmpty = BSTree() @BeforeEach @@ -26,6 +27,7 @@ class BSTreeTest { fun `set new min key`() { assertEquals(null, bst.set(1, "A")) assertEquals(Pair(1, "A"), bst.getMin()) + assertEquals(Pair(1, "A"), bst.predecessor(2)) assertEquals(7, bst.size) } @@ -33,6 +35,7 @@ class BSTreeTest { fun `set new max key`() { assertEquals(null, bst.set(9, "I")) assertEquals(Pair(9, "I"), bst.getMax()) + assertEquals(Pair(9, "I"), bst.successor(8)) assertEquals(7, bst.size) } @@ -66,12 +69,16 @@ class BSTreeTest { @Nested inner class `Remove tests` { + @Test + fun `remove key without child`() { - assertEquals("B", bst.remove(2)) - assertEquals(Pair(3, "C"), bst.getMin()) - assertEquals(Pair(null, null), bst.predecessor(3)) - assertEquals(5, bst.size) + bstTwoNode = BSTree() + bstTwoNode.set(2, "B") + bstTwoNode.set(3, "C") + assertEquals("B", bstTwoNode.remove(2)) + assertEquals(1, bstTwoNode.size) + assertEquals(Pair(3, "C"), bstTwoNode.getMin()) } @Test @@ -84,14 +91,12 @@ class BSTreeTest { @Test fun `remove key that is not in the tree`() { - assertEquals("A", bst.remove(1)) - // + assertEquals(null, bst.remove(1)) } @Test fun `remove key from empty tree`() { - assertEquals("A", bstEmpty.remove(1)) - // + assertEquals(null, bstEmpty.remove(1)) } } From 6ba30e8f10ef98a4cd96e18be693c0761b9d894c Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Wed, 3 Apr 2024 22:28:58 +0300 Subject: [PATCH 085/130] test:fix removeNode method in BSTree --- lib/src/main/kotlin/tree/BSTree.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/BSTree.kt b/lib/src/main/kotlin/tree/BSTree.kt index 0abf1c0..2f57426 100644 --- a/lib/src/main/kotlin/tree/BSTree.kt +++ b/lib/src/main/kotlin/tree/BSTree.kt @@ -63,7 +63,7 @@ class BSTree, V> : SearchTree> { val parentNode = root?.let { searchParentNode(node, it) } if (parentNode == null) { - root = null + root = node.right return } From 6c1184ae0e70ee4f158824fe72c4993dff741e99 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Wed, 3 Apr 2024 23:53:35 +0300 Subject: [PATCH 086/130] test(BST): refactor tests of method insertNode --- lib/src/test/kotlin/tree/BSTreeTest.kt | 67 +++++++++++++++----------- 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/lib/src/test/kotlin/tree/BSTreeTest.kt b/lib/src/test/kotlin/tree/BSTreeTest.kt index 084f236..80e01a6 100644 --- a/lib/src/test/kotlin/tree/BSTreeTest.kt +++ b/lib/src/test/kotlin/tree/BSTreeTest.kt @@ -10,59 +10,71 @@ class BSTreeTest { private lateinit var bstTwoNode: BSTree private val bstEmpty = BSTree() - @BeforeEach - fun setup() { - bst = BSTree() - bst.set(2, "B") - bst.set(3, "C") - bst.set(4, "D") - bst.set(6, "F") - bst.set(7, "G") - bst.set(8, "H") - } - @Nested inner class `Insert tests` { + @BeforeEach + fun setup() { + bst = BSTree() + bst.set(2, "B") + bst.set(3, "C") + bst.set(4, "D") + bst.set(6, "F") + bst.set(7, "G") + bst.set(8, "H") + } + @Test fun `set new min key`() { - assertEquals(null, bst.set(1, "A")) - assertEquals(Pair(1, "A"), bst.getMin()) - assertEquals(Pair(1, "A"), bst.predecessor(2)) + bst.set(1, "A") assertEquals(7, bst.size) + assertEquals( + listOf( + Pair(1, "A"), Pair(2, "B"), Pair(3, "C"), Pair(4, "D"), + Pair(6, "F"), Pair(7, "G"), Pair(8, "H") + ), bst.getEntities() + ) } @Test fun `set new max key`() { - assertEquals(null, bst.set(9, "I")) - assertEquals(Pair(9, "I"), bst.getMax()) - assertEquals(Pair(9, "I"), bst.successor(8)) + bst.set(9, "I") assertEquals(7, bst.size) + assertEquals( + listOf( + Pair(2, "B"), Pair(3, "C"), Pair(4, "D"), + Pair(6, "F"), Pair(7, "G"), Pair(8, "H"), Pair(9, "I") + ), bst.getEntities() + ) } @Test fun `set new key inside tree`() { - assertEquals(null, bst.set(5, "E")) - assertEquals("E", bst.search(5)) - assertEquals(Pair(5, "E"), bst.predecessor(6)) - assertEquals(Pair(5, "E"), bst.successor(4)) + bst.set(5, "E") assertEquals(7, bst.size) + assertEquals( + listOf( + Pair(2, "B"), Pair(3, "C"), Pair(4, "D"), Pair(5, "E"), + Pair(6, "F"), Pair(7, "G"), Pair(8, "H") + ), bst.getEntities() + ) } @Test fun `set the same key`() { - assertEquals("G", bst.set(7, "g")) - assertEquals("g", bst.search(7)) - assertEquals(Pair(7, "g"), bst.predecessor(8)) - assertEquals(Pair(7, "g"), bst.successor(6)) + bst.set(7, "g") assertEquals(6, bst.size) + assertEquals( + listOf( + Pair(2, "B"), Pair(3, "C"), Pair(4, "D"), + Pair(6, "F"), Pair(7, "g"), Pair(8, "H") + ), bst.getEntities() + ) } @Test fun `set key in empty tree`() { bstEmpty.set(1, "A") assertEquals(listOf(Pair(1, "A")), bstEmpty.getEntities()) - assertEquals(Pair(null, null), bstEmpty.predecessor(1)) - assertEquals(Pair(null, null), bstEmpty.successor(1)) assertEquals(1, bstEmpty.size) } } @@ -71,7 +83,6 @@ class BSTreeTest { inner class `Remove tests` { @Test - fun `remove key without child`() { bstTwoNode = BSTree() bstTwoNode.set(2, "B") From 224c37a5079281db34b1d19fcc02f04c3f5a140d Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Thu, 4 Apr 2024 02:38:48 +0300 Subject: [PATCH 087/130] refactor(RBT): make insertNode more readable and add comments --- lib/src/main/kotlin/tree/RBTree.kt | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/src/main/kotlin/tree/RBTree.kt b/lib/src/main/kotlin/tree/RBTree.kt index de8a509..836c7fb 100644 --- a/lib/src/main/kotlin/tree/RBTree.kt +++ b/lib/src/main/kotlin/tree/RBTree.kt @@ -9,6 +9,7 @@ class RBTree, V> : SearchTree> { constructor(pairs: Array>) : super(pairs) override fun insertNode(node: RBTreeNode) { + // put node like we are in BST var tmpNode = root var tmpNodeParent: RBTreeNode? = null @@ -17,25 +18,22 @@ class RBTree, V> : SearchTree> { tmpNode = if (node.key < tmpNode.key) tmpNode.left else tmpNode.right } - node.parent = tmpNodeParent + // that mean tree is empty if (tmpNodeParent == null) { root = node - } else if (node.key < tmpNodeParent.key) { + node.color = RBTreeColor.BLACK + return + } + + node.parent = tmpNodeParent + if (node.key < tmpNodeParent.key) { tmpNodeParent.left = node } else { tmpNodeParent.right = node } - node.left = null - node.right = null - node.color = RBTreeColor.RED - - if (node.parent == null) { - node.color = RBTreeColor.BLACK - return - } - - if (node.parent?.parent == null) { + // if node has no grandpa all fine + if (tmpNodeParent.parent == null) { return } From 252a2aad673634d9902d9f193ed6d1d58f797ac9 Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Thu, 4 Apr 2024 04:54:34 +0300 Subject: [PATCH 088/130] test(RBT): add helper methods for tests --- lib/src/test/kotlin/tree/RBTreeTest.kt | 61 +++++++++++++++++++------- 1 file changed, 44 insertions(+), 17 deletions(-) diff --git a/lib/src/test/kotlin/tree/RBTreeTest.kt b/lib/src/test/kotlin/tree/RBTreeTest.kt index 5d8fa37..f9c4ceb 100644 --- a/lib/src/test/kotlin/tree/RBTreeTest.kt +++ b/lib/src/test/kotlin/tree/RBTreeTest.kt @@ -9,6 +9,33 @@ import org.junit.jupiter.api.Nested class RBTreeTest { private lateinit var rbt: RBTree + private fun checkSize(size: Long, rbt: RBTree = this.rbt) { + assertEquals(size, rbt.size) + checkCountNodes(size.toInt(), rbt) + } + + private fun checkCountNodes(count: Int, rbt: RBTree = this.rbt) { + assertEquals(count, rbt.getEntities().size) + } + + private fun checkValue(key: Int, value: String, rbt: RBTree = this.rbt) { + assertEquals(value, rbt.search(key)) + } + + private fun checkValues(data: Array>) { + data.forEach { + checkValue(it.first, it.second) + } + } + + private fun checkKeys(keys: List, rbt: RBTree = this.rbt) { + assertEquals(keys.distinct().sorted(), rbt.getKeys()) + } + + private fun checkKeys(keys: Array>, rbt: RBTree = this.rbt) { + assertEquals(keys.map { it.first }.distinct().sorted(), rbt.getKeys()) + } + @BeforeEach fun setup() { rbt = RBTree() @@ -18,8 +45,8 @@ class RBTreeTest { inner class `Constructor tests` { @Test fun `without args`() { - assertEquals(0, RBTree().size) - assertEquals(0, RBTree().getEntities().size) + val rbt = RBTree() + checkSize(0, rbt) } @Test @@ -31,23 +58,23 @@ class RBTreeTest { @Test fun `array of entities`() { val entities = arrayOf( - Pair(35, 1), - Pair(21, 1), - Pair(25, 1), - Pair(62, 1), - Pair(12, 1), - Pair(62, 1), - Pair(122, 1), - Pair(621, 1), - Pair(121, 1), - Pair(362, 1), - Pair(35, 1), - Pair(523, 1), + Pair(35, "A"), + Pair(21, "A"), + Pair(25, "A"), + Pair(62, "A"), + Pair(12, "A"), + Pair(62, "A"), + Pair(122, "A"), + Pair(621, "A"), + Pair(121, "A"), + Pair(362, "A"), + Pair(35, "A"), + Pair(523, "A"), ) - val rbt = RBTree(entities) - assertEquals(10, rbt.size) - assertEquals(listOf(12, 21, 25, 35, 62, 121, 122, 362, 523, 621), rbt.getKeys()) + val rbt: RBTree = RBTree(entities) + checkSize(10, rbt) + checkKeys(entities.map { it.first }.distinct().sorted(), rbt) } } From 336584a442fca5525bddfeac610619b7ad333edc Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Thu, 4 Apr 2024 04:55:36 +0300 Subject: [PATCH 089/130] test(RBT): add set tests --- lib/src/test/kotlin/tree/RBTreeTest.kt | 66 ++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/lib/src/test/kotlin/tree/RBTreeTest.kt b/lib/src/test/kotlin/tree/RBTreeTest.kt index f9c4ceb..315499e 100644 --- a/lib/src/test/kotlin/tree/RBTreeTest.kt +++ b/lib/src/test/kotlin/tree/RBTreeTest.kt @@ -5,6 +5,7 @@ import org.junit.jupiter.api.Test import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Nested +import kotlin.random.Random class RBTreeTest { private lateinit var rbt: RBTree @@ -79,12 +80,71 @@ class RBTreeTest { } @Nested - inner class `Insertion tests` { + inner class `Set tests` { + + @Test fun `set one key on empty tree`() { + val data = arrayOf(1 to "Homka") rbt.set(1, "Homka") - assertEquals(1, rbt.size) - assertEquals("Homka", rbt.search(1)) + checkValue(1, "Homka") + checkSize(1) + } + + @Test + fun `set second key as right child`() { + val data = arrayOf(1 to "Homka", 2 to "Dima") + rbt.set(data) + checkValue(1, "Homka") + checkValue(2, "Dima") + checkSize(2) + checkKeys(data) + } + + @Test + fun `set second key as left child`() { + val data = arrayOf(2 to "Homka", 1 to "Dima") + rbt.set(data) + checkValue(2, "Homka") + checkValue(1, "Dima") + checkSize(2) + checkKeys(data) + } + + @Test + fun `set third key as left child`() { + val data = arrayOf(1 to "Homka", 2 to "Dima") + rbt.set(data) + checkValue(2, "Homka") + checkValue(1, "Dima") + checkSize(2) + checkKeys(data) + } + + @Test + fun `insert 1`() { + val rbt = RBTree() + val setWithNull: (Int) -> (Unit) = { key -> rbt.set(key, null) } + + listOf(35, 21, 25, 62, 12, 62, 122, 621, 121, 362, 35, 523).forEach(setWithNull) + } + + @Test + fun `stress test`() { + val rbt = RBTree() + val generator = Random(5) + val setWithNull: (Int) -> (Unit) = { key -> rbt.set(key, null) } + + val randomKeys = mutableListOf() + for (i in 1..1000000) { + val randomValue = generator.nextInt() + randomKeys.add(randomValue) + setWithNull(randomValue) + } + + val randomKeysDistinct = randomKeys.distinct() + assertEquals(randomKeysDistinct.sorted(), rbt.getKeys()) + assertEquals(randomKeysDistinct.size.toLong(), rbt.size) } } } \ No newline at end of file From 8a86df2f6b925cf489b00ecd639feee024a7e2ec Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Thu, 4 Apr 2024 04:57:58 +0300 Subject: [PATCH 090/130] test(RBT): add universal set test --- lib/src/test/kotlin/tree/RBTreeTest.kt | 30 +++++++++----------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/lib/src/test/kotlin/tree/RBTreeTest.kt b/lib/src/test/kotlin/tree/RBTreeTest.kt index 315499e..7411482 100644 --- a/lib/src/test/kotlin/tree/RBTreeTest.kt +++ b/lib/src/test/kotlin/tree/RBTreeTest.kt @@ -81,44 +81,34 @@ class RBTreeTest { @Nested inner class `Set tests` { - + fun setTest(data: Array>) { + rbt.set(data) + checkValues(data) + checkSize(data.size.toLong()) + } @Test fun `set one key on empty tree`() { val data = arrayOf(1 to "Homka") - rbt.set(1, "Homka") - checkValue(1, "Homka") - checkSize(1) + setTest(data) } @Test fun `set second key as right child`() { val data = arrayOf(1 to "Homka", 2 to "Dima") - rbt.set(data) - checkValue(1, "Homka") - checkValue(2, "Dima") - checkSize(2) - checkKeys(data) + setTest(data) } @Test fun `set second key as left child`() { val data = arrayOf(2 to "Homka", 1 to "Dima") - rbt.set(data) - checkValue(2, "Homka") - checkValue(1, "Dima") - checkSize(2) - checkKeys(data) + setTest(data) } @Test fun `set third key as left child`() { - val data = arrayOf(1 to "Homka", 2 to "Dima") - rbt.set(data) - checkValue(2, "Homka") - checkValue(1, "Dima") - checkSize(2) - checkKeys(data) + val data = arrayOf(2 to "Homka", 3 to "Dima", 1 to "Nastya") + setTest(data) } @Test From 086ae28398d733f18a546b459f9002137534ed73 Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Thu, 4 Apr 2024 05:41:57 +0300 Subject: [PATCH 091/130] test(RBT): add more set tests --- lib/src/test/kotlin/tree/RBTreeTest.kt | 73 ++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 5 deletions(-) diff --git a/lib/src/test/kotlin/tree/RBTreeTest.kt b/lib/src/test/kotlin/tree/RBTreeTest.kt index 7411482..af85883 100644 --- a/lib/src/test/kotlin/tree/RBTreeTest.kt +++ b/lib/src/test/kotlin/tree/RBTreeTest.kt @@ -24,7 +24,7 @@ class RBTreeTest { } private fun checkValues(data: Array>) { - data.forEach { + data.distinctBy { it.first }.forEach { checkValue(it.first, it.second) } } @@ -112,11 +112,74 @@ class RBTreeTest { } @Test - fun `insert 1`() { - val rbt = RBTree() - val setWithNull: (Int) -> (Unit) = { key -> rbt.set(key, null) } + fun `set third key as right child`() { + val data = arrayOf(2 to "Homka", 1 to "Dima", 3 to "Nastya") + setTest(data) + } - listOf(35, 21, 25, 62, 12, 62, 122, 621, 121, 362, 35, 523).forEach(setWithNull) + @Test + fun `set third key as root from left`() { + val data = arrayOf(3 to "Homka", 2 to "Dima", 1 to "Nastya") + setTest(data) + } + + @Test + fun `set third key as root from right`() { + val data = arrayOf(1 to "Homka", 2 to "Dima", 3 to "Nastya") + setTest(data) + } + + @Test + fun `set key to the left when uncle is red`() { + val data = arrayOf(5 to "Homka", 10 to "Dima", 15 to "Nastya", 7 to "Rodion") + setTest(data) + } + + @Test + fun `set key to the right when uncle is red`() { + val data = arrayOf(5 to "Homka", 10 to "Dima", 15 to "Nastya", 17 to "Rodion") + setTest(data) + } + + @Test + fun `set key to the left when uncle is black and parent red`() { + val data = arrayOf(15 to "Homka", 10 to "Dima", 5 to "Nastya", 1 to "Rodion", 6 to "spisladqo") + setTest(data) + } + + @Test + fun `set key to the left when uncle is null and parent red`() { + val data = arrayOf( + 5 to "Homka", 10 to "Dima", 15 to "Nastya", 20 to "Rodion", + 25 to "spisladqo", 30 to "Vichislav Zorich", 27 to "Sibiri4ok" + ) + setTest(data) + } + + @Test + fun `set key to the right when uncle is black and parent red`() { + val data = arrayOf(1 to "Homka", 5 to "Dima", 10 to "Nastya", 15 to "Rodion", 14 to "spisladqo") + setTest(data) + } + + @Test + fun `set key to the right when uncle is null and parent red`() { + val data = arrayOf( + 30 to "Homka", 25 to "Dima", 20 to "Nastya", 15 to "Rodion", + 10 to "spisladqo", 5 to "Vichislav Zorich", 6 to "Sibiri4ok" + ) + setTest(data) + } + + @Test + fun `set some random keys`() { + val data = arrayOf( + 35 to "Homka", 21 to "Dima", 25 to "Nastya", 622 to "Rodion", + 12 to "spisladqo", 62 to "Vichislav Zorich", 122 to "Sibiri4ok", + 621 to "kotenok-barista", 121 to "vlad zavtra v zal", 362 to "karim", + 36 to "seriy cardinal", 523 to "katya", 251 to "sonechka" + ) + setTest(data) } @Test From 253038bf418ad83c7e89b9083daba6ded58cbcfa Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Thu, 4 Apr 2024 06:58:11 +0300 Subject: [PATCH 092/130] test(RBT): add remove tests --- lib/src/test/kotlin/tree/RBTreeTest.kt | 109 +++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/lib/src/test/kotlin/tree/RBTreeTest.kt b/lib/src/test/kotlin/tree/RBTreeTest.kt index af85883..cdeea2e 100644 --- a/lib/src/test/kotlin/tree/RBTreeTest.kt +++ b/lib/src/test/kotlin/tree/RBTreeTest.kt @@ -200,4 +200,113 @@ class RBTreeTest { assertEquals(randomKeysDistinct.size.toLong(), rbt.size) } } + + @Nested + inner class `Remove Tests` { + fun removeTest(data: Array>, key: Int) { + rbt.set(data) + rbt.remove(key) + checkValues(data.filter { it.first != key }.toTypedArray()) + checkSize((data.size - 1).toLong()) + + } + + @Test + fun `remove one key`() { + val data = arrayOf(1 to "Homka") + removeTest(data, 1) + } + + @Test + fun `remove leaf key from right`() { + val data = arrayOf(2 to "Homka", 3 to "Dima", 1 to "Nastya") + removeTest(data, 3) + } + + @Test + fun `remove single leaf key from right`() { + val data = arrayOf(2 to "Homka", 3 to "Dima") + removeTest(data, 3) + } + + @Test + fun `remove leaf key from left`() { + val data = arrayOf(2 to "Homka", 3 to "Dima", 1 to "Nastya") + removeTest(data, 1) + } + + @Test + fun `remove single leaf key from left`() { + val data = arrayOf(2 to "Homka", 1 to "Nastya") + removeTest(data, 1) + } + + @Test + fun `remove root in tree with 3 nodes`() { + val data = arrayOf(2 to "Homka", 3 to "Dima", 1 to "Nastya") + removeTest(data, 2) + } + + @Test + fun `remove root in tree with right node`() { + val data = arrayOf(2 to "Homka", 3 to "Dima") + removeTest(data, 2) + } + + @Test + fun `remove root in tree with left node`() { + val data = arrayOf(2 to "Homka", 1 to "Dima") + removeTest(data, 2) + } + + @Test + fun `remove node that is right subtree with nodes`() { + val data = arrayOf( + 35 to "Homka", 21 to "Dima", 25 to "Nastya", 622 to "Rodion", + 12 to "spisladqo", 62 to "Vichislav Zorich", 122 to "Sibiri4ok", + 621 to "kotenok-barista", 121 to "vlad zavtra v zal", 362 to "karim", + 36 to "seriy cardinal", 523 to "katya", 251 to "sonechka", + 6422 to "dinozavrik", 4621 to "ruslan", 2093 to "islam", + 235 to "miss mi", 682 to "liya", 2058 to "cold water", 2391 to "azamat", + 2269 to "graphblas" + ) + removeTest(data, 682) + } + + @Test + fun `remove node that is left subtree with nodes`() { + val data = arrayOf( + 35 to "Homka", 21 to "Dima", 25 to "Nastya", 622 to "Rodion", + 12 to "spisladqo", 62 to "Vichislav Zorich", 122 to "Sibiri4ok", + 621 to "kotenok-barista", 121 to "vlad zavtra v zal", 362 to "karim", + 36 to "seriy cardinal", 523 to "katya", 251 to "sonechka", + 6422 to "dinozavrik", 4621 to "ruslan", 2093 to "islam", + 235 to "miss mi" + ) + removeTest(data, 21) + } + + @Test + fun `stress test`() { + val rbt = RBTree() + val generator = Random(5) + val setWithDefaultValue: (Int) -> (Unit) = { key -> rbt.set(key, "") } + + val randomKeys = mutableListOf() + for (i in 1..1000000) { + val randomValue = generator.nextInt() + randomKeys.add(randomValue) + setWithDefaultValue(randomValue) + } + + val len = randomKeys.size + for (index in 1..len) { + val value: Int = randomKeys.removeLast() + rbt.remove(value) + } + + checkSize(0, rbt) + checkKeys(arrayOf(), rbt) + } + } } \ No newline at end of file From 7c88442dc49799ef6dacecb8c5a268f1564428ce Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Thu, 4 Apr 2024 06:59:48 +0300 Subject: [PATCH 093/130] refactor(RBT): make methods prettier, add comments --- lib/src/main/kotlin/tree/RBTree.kt | 96 +++++++++++++++++------------- 1 file changed, 53 insertions(+), 43 deletions(-) diff --git a/lib/src/main/kotlin/tree/RBTree.kt b/lib/src/main/kotlin/tree/RBTree.kt index 836c7fb..0120901 100644 --- a/lib/src/main/kotlin/tree/RBTree.kt +++ b/lib/src/main/kotlin/tree/RBTree.kt @@ -44,52 +44,58 @@ class RBTree, V> : SearchTree> { var node = newNode while (node.parent?.color === RBTreeColor.RED) { - var parent = node.parent ?: return - var grandpa = parent.parent ?: return + var parent = node.parent ?: throw IllegalStateException() + var grandpa = parent.parent ?: throw IllegalStateException() - if (parent == grandpa.right) { - val uncle = grandpa.left ?: return + if (parent == grandpa.left) { + val uncle = grandpa.right - if (uncle.color == RBTreeColor.RED) { + // uncle is red + if (uncle != null && uncle.color == RBTreeColor.RED) { uncle.color = RBTreeColor.BLACK parent.color = RBTreeColor.BLACK grandpa.color = RBTreeColor.RED node = grandpa - } else { - if (node == parent.left) { - node = parent - parent = node.parent ?: return - grandpa = parent.parent ?: return - rightRotate(node) - } - parent.color = RBTreeColor.BLACK - grandpa.color = RBTreeColor.RED - leftRotate(grandpa) + continue } - } else { - val uncle = grandpa.right ?: return - if (uncle.color == RBTreeColor.RED) { - uncle.color = RBTreeColor.BLACK - parent.color = RBTreeColor.BLACK - grandpa.color = RBTreeColor.RED - node = grandpa - } else { - if (node == parent.right) { - node = parent - parent = node.parent ?: return - grandpa = parent.parent ?: return - leftRotate(node) - } - parent.color = RBTreeColor.BLACK - grandpa.color = RBTreeColor.RED - rightRotate(grandpa) + // uncle is black (null node = black) + if (node == parent.right) { + node = parent + leftRotate(node) + parent = node.parent ?: throw IllegalStateException() + grandpa = parent.parent ?: throw IllegalStateException() } + + parent.color = RBTreeColor.BLACK + grandpa.color = RBTreeColor.RED + rightRotate(grandpa) + continue } - if (node == root) { - break + // parent is right child of grandpa + val uncle = grandpa.left + + // uncle is red + if (uncle != null && uncle.color == RBTreeColor.RED) { + uncle.color = RBTreeColor.BLACK + parent.color = RBTreeColor.BLACK + grandpa.color = RBTreeColor.RED + node = grandpa + continue } + + // uncle is black + if (node == parent.left) { + node = parent + rightRotate(node) + parent = node.parent ?: throw IllegalStateException() + grandpa = parent.parent ?: throw IllegalStateException() + } + + parent.color = RBTreeColor.BLACK + grandpa.color = RBTreeColor.RED + leftRotate(grandpa) } root?.color = RBTreeColor.BLACK @@ -136,11 +142,15 @@ class RBTree, V> : SearchTree> { return RBTreeNode(key, value) } + private fun isBlack(node: RBTreeNode?): Boolean { + return node == null || node.color == RBTreeColor.BLACK + } + private fun deleteFix(transplantedNode: RBTreeNode) { var node: RBTreeNode? = transplantedNode while (node != root && node?.color == RBTreeColor.BLACK) { - val parentNode = node.parent ?: return + val parentNode = node.parent ?: throw IllegalStateException() if (node == parentNode.left) { var uncle = parentNode.right ?: return @@ -152,15 +162,15 @@ class RBTree, V> : SearchTree> { uncle = parentNode.right ?: return } - if (uncle.left?.color == RBTreeColor.BLACK && uncle.right?.color == RBTreeColor.BLACK) { + if (isBlack(uncle.left) && isBlack(uncle.right)) { uncle.color = RBTreeColor.RED node = parentNode } else { - if (uncle.right?.color == RBTreeColor.BLACK) { + if (isBlack(uncle.right)) { uncle.left?.color = RBTreeColor.BLACK uncle.color = RBTreeColor.RED rightRotate(uncle) - uncle = parentNode.right ?: return + uncle = parentNode.right ?: throw IllegalStateException() } uncle.color = parentNode.color @@ -179,15 +189,15 @@ class RBTree, V> : SearchTree> { uncle = parentNode.left ?: return } - if (uncle.right?.color == RBTreeColor.BLACK && uncle.right?.color == RBTreeColor.BLACK) { + if (isBlack(uncle.left) && isBlack(uncle.right)) { uncle.color = RBTreeColor.RED node = parentNode } else { - if (uncle.left?.color == RBTreeColor.BLACK) { + if (isBlack(uncle.left)) { uncle.right?.color = RBTreeColor.BLACK uncle.color = RBTreeColor.RED leftRotate(uncle) - uncle = parentNode.left ?: return + uncle = parentNode.left ?: throw IllegalStateException() } uncle.color = parentNode.color @@ -227,7 +237,7 @@ class RBTree, V> : SearchTree> { } private fun leftRotate(node: RBTreeNode) { - val rightNode = node.right ?: return + val rightNode = node.right ?: throw IllegalStateException() node.right = rightNode.left rightNode.left?.parent = node @@ -247,7 +257,7 @@ class RBTree, V> : SearchTree> { } private fun rightRotate(node: RBTreeNode) { - val leftNode = node.left ?: return + val leftNode = node.left ?: throw IllegalStateException() node.left = leftNode.right leftNode.right?.parent = node From ab6fb80c07348fb270f69d0c2929428c5f7362ac Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Thu, 4 Apr 2024 07:15:08 +0300 Subject: [PATCH 094/130] ci: add tests ci --- .github/workflows/tests.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .github/workflows/tests.yml diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..c4ba9b0 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,26 @@ +name: Kotlin CI With Gradle + +on: + push: + branches: [ "main", "test" ] + pull_request: + branches: [ "main", "test" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + + - name: Build with Gradle Wrapper + run: ./gradlew build + + - name: Launch tests + run: ./gradlew :lib:test From bc3d40ac52d9bb27e12325a0ef63d37ea0a43557 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Thu, 4 Apr 2024 00:01:44 +0300 Subject: [PATCH 095/130] test(BST): refactor tests of method createNode --- lib/src/test/kotlin/tree/BSTreeTest.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/test/kotlin/tree/BSTreeTest.kt b/lib/src/test/kotlin/tree/BSTreeTest.kt index 80e01a6..a57a80d 100644 --- a/lib/src/test/kotlin/tree/BSTreeTest.kt +++ b/lib/src/test/kotlin/tree/BSTreeTest.kt @@ -115,8 +115,8 @@ class BSTreeTest { inner class `Create tests` { @Test fun `insert new node`() { - assertEquals(null, bst.set(1, "A")) - assertEquals("A", bst.search(1)) + bst = BSTree(1, "A") + assertEquals(listOf(Pair(1, "A")), bst.getEntities()) } } } \ No newline at end of file From c63ac8361d1f87062650addcdd64f5af52e37ee7 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Thu, 4 Apr 2024 15:10:15 +0300 Subject: [PATCH 096/130] test(BST): add tests of method removeNode --- lib/src/test/kotlin/tree/BSTreeTest.kt | 137 ++++++++++++++++++++++--- 1 file changed, 125 insertions(+), 12 deletions(-) diff --git a/lib/src/test/kotlin/tree/BSTreeTest.kt b/lib/src/test/kotlin/tree/BSTreeTest.kt index a57a80d..c2c1ac4 100644 --- a/lib/src/test/kotlin/tree/BSTreeTest.kt +++ b/lib/src/test/kotlin/tree/BSTreeTest.kt @@ -7,7 +7,6 @@ import org.junit.jupiter.api.Test class BSTreeTest { private lateinit var bst: BSTree - private lateinit var bstTwoNode: BSTree private val bstEmpty = BSTree() @Nested @@ -83,31 +82,145 @@ class BSTreeTest { inner class `Remove tests` { @Test - fun `remove key without child`() { - bstTwoNode = BSTree() - bstTwoNode.set(2, "B") - bstTwoNode.set(3, "C") - assertEquals("B", bstTwoNode.remove(2)) - assertEquals(1, bstTwoNode.size) - assertEquals(Pair(3, "C"), bstTwoNode.getMin()) + fun `remove single root`() { + bst = BSTree() + bst.set(2, "B") + assertEquals("B", bst.remove(2)) + assertEquals(0, bst.size) } @Test - fun `remove key with one child`() { - assertEquals("C", bst.remove(3)) - assertEquals(Pair(2, "B"), bst.predecessor(4)) - assertEquals(Pair(4, "D"), bst.successor(2)) + fun `remove root with two children(list)`() { + bst = BSTree() + bst.set(2, "B") + bst.set(3, "C") + bst.set(1, "A") + bst.set(0, "Z") + bst.set(5, "E") + bst.set(4, "D") + assertEquals("B", bst.remove(2)) assertEquals(5, bst.size) + assertEquals(listOf(0, 1, 3, 4, 5), bst.getKeys()) + } + + @Test + fun `remove root with two children`() { + bst = BSTree() + bst.set(2, "B") + bst.set(1, "A") + bst.set(0, "Z") + bst.set(6, "F") + bst.set(4, "D") + bst.set(5, "E") + assertEquals("B", bst.remove(2)) + assertEquals(5, bst.size) + assertEquals(listOf(0, 1, 4, 5, 6), bst.getKeys()) + } + + @Test + fun `remove root with two children2`() { + bst = BSTree() + bst.set(2, "B") + bst.set(1, "A") + bst.set(0, "Z") + bst.set(6, "F") + bst.set(7, "G") + bst.set(4, "D") + bst.set(5, "E") + assertEquals("B", bst.remove(2)) + assertEquals(6, bst.size) + assertEquals(listOf(0, 1, 4, 5, 6, 7), bst.getKeys()) + } + + @Test + fun `remove root with two children3`() { + bst = BSTree() + bst.set(2, "B") + bst.set(1, "A") + bst.set(0, "Z") + bst.set(8, "F") + bst.set(3, "D") + bst.set(5, "E") + bst.set(4, "F") + bst.set(6, "F") + assertEquals("B", bst.remove(2)) + assertEquals(7, bst.size) + assertEquals(listOf(0, 1, 3, 4, 5, 6, 8), bst.getKeys()) + } + + @Test + fun `remove root without left child`() { + bst = BSTree() + bst.set(2, "B") + bst.set(3, "C") + bst.set(5, "E") + bst.set(4, "D") + assertEquals("B", bst.remove(2)) + assertEquals(3, bst.size) + assertEquals(listOf(3, 4, 5), bst.getKeys()) + } + + @Test + fun `remove root without right child`() { + bst = BSTree() + bst.set(6, "F") + bst.set(3, "C") + bst.set(5, "E") + bst.set(4, "D") + assertEquals("F", bst.remove(6)) + assertEquals(3, bst.size) + assertEquals(listOf(3, 4, 5), bst.getKeys()) + } + + @Test + fun `remove key without left child`() { + bst = BSTree() + bst.set(1, "A") + bst.set(2, "B") + bst.set(3, "C") + assertEquals("B", bst.remove(2)) + assertEquals(2, bst.size) + assertEquals(listOf(Pair(1, "A"), Pair(3, "C")), bst.getEntities()) + } + + @Test + fun `remove key without right child`() { + bst = BSTree() + bst.set(3, "C") + bst.set(2, "B") + bst.set(1, "A") + assertEquals("B", bst.remove(2)) + assertEquals(2, bst.size) + assertEquals(listOf(Pair(1, "A"), Pair(3, "C")), bst.getEntities()) + } + + @Test + fun `remove key with two children`() { + bst = BSTree() + bst.set(1, "A") + bst.set(3, "C") + bst.set(2, "B") + bst.set(4, "D") + assertEquals("C", bst.remove(3)) + assertEquals(3, bst.size) + assertEquals(listOf(Pair(1, "A"), Pair(2, "B"), Pair(4, "D")), bst.getEntities()) } @Test fun `remove key that is not in the tree`() { + bst = BSTree() + bst.set(2, "B") + bst.set(3, "C") + bst.set(0, "Z") assertEquals(null, bst.remove(1)) + assertEquals(3, bst.size) + assertEquals(listOf(Pair(0, "Z"), Pair(2, "B"), Pair(3, "C")), bst.getEntities()) } @Test fun `remove key from empty tree`() { assertEquals(null, bstEmpty.remove(1)) + assertEquals(0, bstEmpty.size) } } From 613284c806517fbe7a08bb757ed3aed7ea31d589 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Thu, 4 Apr 2024 15:14:31 +0300 Subject: [PATCH 097/130] test(BST): fix method removeNode --- lib/src/main/kotlin/tree/BSTree.kt | 49 +++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/lib/src/main/kotlin/tree/BSTree.kt b/lib/src/main/kotlin/tree/BSTree.kt index 2f57426..b79b432 100644 --- a/lib/src/main/kotlin/tree/BSTree.kt +++ b/lib/src/main/kotlin/tree/BSTree.kt @@ -62,32 +62,51 @@ class BSTree, V> : SearchTree> { override fun removeNode(node: BSTreeNode) { val parentNode = root?.let { searchParentNode(node, it) } - if (parentNode == null) { - root = node.right - return - } - if (node.left == null && node.right == null) { + + if (parentNode == null) { + root = null + return + } + identifyChild(parentNode, node, null) - return - } - if (node.left == null || node.right == null) { + } else if (node.left == null || node.right == null) { + if (node.left == null) { + + if (parentNode == null) { + root = node.right + return + } + identifyChild(parentNode, node, node.right) + } else { + + if (parentNode == null) { + root = node.left + return + } + identifyChild(parentNode, node, node.left) } - return - } + } else { + val nodeR = node.right + val successor = nodeR?.let { getMinSubtree(it) } + nodeR?.let { getMinSubtree(it) }?.let { removeNode(it) } + + successor?.left = node.left + successor?.right = node.right - val successor = getMinSubtree(node) - removeNode(getMinSubtree(node)) - successor.left = node.left - successor.right = node.right + if (parentNode == null) { + root = successor + return + } - identifyChild(parentNode, node, successor) + identifyChild(parentNode, node, successor) + } } override fun createNode(key: K, value: V): BSTreeNode { From c1d3d1720ea3435b1af365fdd7304b22213083a0 Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Thu, 4 Apr 2024 17:19:05 +0300 Subject: [PATCH 098/130] Create README.md --- README.md | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..676cdb3 --- /dev/null +++ b/README.md @@ -0,0 +1,149 @@ +## NamelessKitty.kt - library that appreciate your data ✨ + +**NamelessKitty.kt** is library that help you work with your data by simple interface, using binary search trees under the hood. + + + +## ⚡️Quick start + +```kotlin +import tree.RBTree + +fun main() { + val rbt = RBTree() + + rbt.set(1, "Hello world") + + println(rbt.search(1)) +} +``` + +Yes, that is really simple. \ +We Love KISS. + +## ✨ Features +- **Null-safety code** - We didn't use anything that could break your code +- **18 public methods** - Thanks to Dima +- **Simple interface** - Our library is easy to use and we proud of it +- **Easy to expand** - We provide simple abstact class that allow you create new type of trees and use it for your tasks +- **Generic types** - Use whatever you want types. We handle with it. + +## 👀 Examples + +#### 📖 **Add array of data** +```kotlin +import tree.RBTree + +fun main() { + val data = arrayOf(122 to "Homka", 21 to "Dima", 25 to "Nastya") + val dataKeys = data.map { it.first }.toTypedArray() + + val rbt = RBTree(data) + rbt.set(data) + rbt.remove(dataKeys) +} +``` + +#### 📖 **Print all data in ascending order** +```kotlin +import tree.RBTree + +fun main() { + val data = arrayOf(122 to "Homka", 21 to "Dima", 25 to "Nastya") + + val rbt = RBTree(data) + + rbt.inOrderTraversal { + println("key: ${it.first}, value: ${it.second}") + } +} +``` + +#### 📖 **Put only first incoming data** +```kotlin +import tree.RBTree + +fun main() { + val data = arrayOf(1 to "Homka", 2 to "Dima", 3 to "Nastya", 1 to "Homka") + + val rbt = RBTree(data) + + data.forEach { + val previousValue = rbt.setIfEmpty(it.first, it.second) + + if (previousValue != null) { + println("Data with key: ${it.first} already exists and contain: ${previousValue}") + } + } +} +``` + +## 🐤 Docs +- We have three types of tree: BST, AVL, RBT +- Each tree has constructor that accept: + - Nothing (Empty tree) + - Key and Value + - Array of Pairs of Key\Value +- Each tree has these methods: + - `set(key: K, value: V): V?` \ + Stores the value for the given key. Return previous value. + + - `set(pairs: Array>): MutableList` \ + Stores the values for the given keys. Return previous values. + + - `setIfEmpty(key: K, value: V): V?` \ + Stores the value for the given key if there is no pair with that key. Return previous value. + + - `setIfEmpty(pairs: Array>): MutableList` \ + Stores the values for the given keys if there is no pair with that key. Return previous values. + + - `remove(key: K): V?` \ + Remove the value for the given key. Return previous value. + + - `remove(keys: Array): MutableList` \ + Remove the values for the given keys. Return previous values. + + - `search(key: K): V?` \ + Return the value for the given key. + + - `getKeys(): List` \ + Returns a complete list of keys. + + - `getValues(): List` \ + Returns a complete list of values. + + - `getEntities(): List>` \ + Returns a complete list of pairs key value. + + - `getMin(): Pair` \ + Returns pair with the minimum key. + + - `getMax(): Pair` \ + Returns pair with the maximum key. + + - `successor(key: K): Pair` \ + Returns the pair with next ascending key. + + - `predecessor(key: K): Pair` \ + Returns the pair with previous ascending key + + - `clear()` \ + Remove all keys in a tree. + + - `preOrderTraversal(action: (Pair) -> (Unit))` \ + Apply [action] on all pairs by preorder tree traversal. + + - `inOrderTraversal(action: (Pair) -> (Unit))` \ + Apply [action] on all pairs by inorder tree traversal. + + - `postOrderTraversal(action: (Pair) -> (Unit))` \ + Apply [action] on all pairs by postorder tree traversal. + +## 🐹 Gitbub stars +We love stars (ok, just me). I would be very pleased if you put a star on our project. \ +![image](https://github.com/spbu-coding-2023/trees-3/assets/39369841/bb81c1b0-5d69-4b63-9a9a-49b952625ad7) + +## Contacts +- [Dmitry Sheiko] (https://github.com/Demon32123) +- [Anastasiia Kuzmina] (https://github.com/far1yg) +- [Homa Kombaev] (https://github.com/homka122) From 802c05734c0073a13759fbad089f04d48416baff Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Thu, 4 Apr 2024 17:51:55 +0300 Subject: [PATCH 099/130] test(RBT): add more random values --- lib/src/test/kotlin/tree/RBTreeTest.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/src/test/kotlin/tree/RBTreeTest.kt b/lib/src/test/kotlin/tree/RBTreeTest.kt index cdeea2e..89635ed 100644 --- a/lib/src/test/kotlin/tree/RBTreeTest.kt +++ b/lib/src/test/kotlin/tree/RBTreeTest.kt @@ -177,7 +177,9 @@ class RBTreeTest { 35 to "Homka", 21 to "Dima", 25 to "Nastya", 622 to "Rodion", 12 to "spisladqo", 62 to "Vichislav Zorich", 122 to "Sibiri4ok", 621 to "kotenok-barista", 121 to "vlad zavtra v zal", 362 to "karim", - 36 to "seriy cardinal", 523 to "katya", 251 to "sonechka" + 36 to "seriy cardinal", 523 to "katya", 251 to "sonechka", 9352 to "qrutyy misha", + 513 to "little hamster", 462 to "nameless kitty", 2395 to "therain7", + 3252 to "vacman", 1352 to "homerizde", 723 to "kvas" ) setTest(data) } From e8a7c636f97127b4fe3abdad159a683057190441 Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Thu, 4 Apr 2024 18:00:07 +0300 Subject: [PATCH 100/130] Create docs.md --- docs.md | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 docs.md diff --git a/docs.md b/docs.md new file mode 100644 index 0000000..a64c5f7 --- /dev/null +++ b/docs.md @@ -0,0 +1,60 @@ +## 🐤 Docs +- We have three types of tree: BST, AVL, RBT +- Each tree has constructor that accept: + - Nothing (Empty tree) + - Key and Value + - Array of Pairs of Key\Value +- Each tree has these methods: + - `set(key: K, value: V): V?` \ + Stores the value for the given key. Return previous value. + + - `set(pairs: Array>): MutableList` \ + Stores the values for the given keys. Return previous values. + + - `setIfEmpty(key: K, value: V): V?` \ + Stores the value for the given key if there is no pair with that key. Return previous value. + + - `setIfEmpty(pairs: Array>): MutableList` \ + Stores the values for the given keys if there is no pair with that key. Return previous values. + + - `remove(key: K): V?` \ + Remove the value for the given key. Return previous value. + + - `remove(keys: Array): MutableList` \ + Remove the values for the given keys. Return previous values. + + - `search(key: K): V?` \ + Return the value for the given key. + + - `getKeys(): List` \ + Returns a complete list of keys. + + - `getValues(): List` \ + Returns a complete list of values. + + - `getEntities(): List>` \ + Returns a complete list of pairs key value. + + - `getMin(): Pair` \ + Returns pair with the minimum key. + + - `getMax(): Pair` \ + Returns pair with the maximum key. + + - `successor(key: K): Pair` \ + Returns the pair with next ascending key. + + - `predecessor(key: K): Pair` \ + Returns the pair with previous ascending key + + - `clear()` \ + Remove all keys in a tree. + + - `preOrderTraversal(action: (Pair) -> (Unit))` \ + Apply [action] on all pairs by preorder tree traversal. + + - `inOrderTraversal(action: (Pair) -> (Unit))` \ + Apply [action] on all pairs by inorder tree traversal. + + - `postOrderTraversal(action: (Pair) -> (Unit))` \ + Apply [action] on all pairs by postorder tree traversal. From ef36bf7699fd1baf41ed4d94d983da228be444e0 Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Thu, 4 Apr 2024 18:01:39 +0300 Subject: [PATCH 101/130] Move docs to another files and fix urls --- README.md | 66 ++++--------------------------------------------------- 1 file changed, 4 insertions(+), 62 deletions(-) diff --git a/README.md b/README.md index 676cdb3..3f4f918 100644 --- a/README.md +++ b/README.md @@ -79,71 +79,13 @@ fun main() { ``` ## 🐤 Docs -- We have three types of tree: BST, AVL, RBT -- Each tree has constructor that accept: - - Nothing (Empty tree) - - Key and Value - - Array of Pairs of Key\Value -- Each tree has these methods: - - `set(key: K, value: V): V?` \ - Stores the value for the given key. Return previous value. - - - `set(pairs: Array>): MutableList` \ - Stores the values for the given keys. Return previous values. - - - `setIfEmpty(key: K, value: V): V?` \ - Stores the value for the given key if there is no pair with that key. Return previous value. - - - `setIfEmpty(pairs: Array>): MutableList` \ - Stores the values for the given keys if there is no pair with that key. Return previous values. - - - `remove(key: K): V?` \ - Remove the value for the given key. Return previous value. - - - `remove(keys: Array): MutableList` \ - Remove the values for the given keys. Return previous values. - - - `search(key: K): V?` \ - Return the value for the given key. - - - `getKeys(): List` \ - Returns a complete list of keys. - - - `getValues(): List` \ - Returns a complete list of values. - - - `getEntities(): List>` \ - Returns a complete list of pairs key value. - - - `getMin(): Pair` \ - Returns pair with the minimum key. - - - `getMax(): Pair` \ - Returns pair with the maximum key. - - - `successor(key: K): Pair` \ - Returns the pair with next ascending key. - - - `predecessor(key: K): Pair` \ - Returns the pair with previous ascending key - - - `clear()` \ - Remove all keys in a tree. - - - `preOrderTraversal(action: (Pair) -> (Unit))` \ - Apply [action] on all pairs by preorder tree traversal. - - - `inOrderTraversal(action: (Pair) -> (Unit))` \ - Apply [action] on all pairs by inorder tree traversal. - - - `postOrderTraversal(action: (Pair) -> (Unit))` \ - Apply [action] on all pairs by postorder tree traversal. +[docs.md](https://github.com/spbu-coding-2023/trees-3/blob/main/docs.md) ## 🐹 Gitbub stars We love stars (ok, just me). I would be very pleased if you put a star on our project. \ ![image](https://github.com/spbu-coding-2023/trees-3/assets/39369841/bb81c1b0-5d69-4b63-9a9a-49b952625ad7) ## Contacts -- [Dmitry Sheiko] (https://github.com/Demon32123) -- [Anastasiia Kuzmina] (https://github.com/far1yg) -- [Homa Kombaev] (https://github.com/homka122) +- [Dmitry Sheiko](https://github.com/Demon32123) +- [Anastasiia Kuzmina](https://github.com/far1yg) +- [Homa Kombaev](https://github.com/homka122) From 09adfd69753fe9616c2a8df89eb66c9267f230ed Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Thu, 4 Apr 2024 19:47:20 +0300 Subject: [PATCH 102/130] test(BST): fix removeNode method --- lib/src/main/kotlin/tree/BSTree.kt | 56 ++++++++++-------------------- 1 file changed, 19 insertions(+), 37 deletions(-) diff --git a/lib/src/main/kotlin/tree/BSTree.kt b/lib/src/main/kotlin/tree/BSTree.kt index b79b432..129f1fa 100644 --- a/lib/src/main/kotlin/tree/BSTree.kt +++ b/lib/src/main/kotlin/tree/BSTree.kt @@ -51,8 +51,10 @@ class BSTree, V> : SearchTree> { } } - private fun identifyChild(parentNode: BSTreeNode, node: BSTreeNode, value: BSTreeNode?) { - if (parentNode.left == node) { + private fun identifyChild(parentNode: BSTreeNode?, node: BSTreeNode, value: BSTreeNode?) { + if (parentNode == null) { + root = value + } else if (parentNode.left == node) { parentNode.left = value } else { parentNode.right = value @@ -62,51 +64,31 @@ class BSTree, V> : SearchTree> { override fun removeNode(node: BSTreeNode) { val parentNode = root?.let { searchParentNode(node, it) } - if (node.left == null && node.right == null) { - - if (parentNode == null) { - root = null - return - } - - identifyChild(parentNode, node, null) - - } else if (node.left == null || node.right == null) { + val nodeRight = node.right + val nodeLeft = node.left - if (node.left == null) { - if (parentNode == null) { - root = node.right - return - } + if (nodeLeft == null && nodeRight == null) { + return identifyChild(parentNode, node, null) + } - identifyChild(parentNode, node, node.right) + if (nodeLeft == null || nodeRight == null) { + if (nodeLeft == null) { + return identifyChild(parentNode, node, nodeRight) } else { - - if (parentNode == null) { - root = node.left - return - } - - identifyChild(parentNode, node, node.left) + return identifyChild(parentNode, node, nodeLeft) } - } else { - val nodeR = node.right - val successor = nodeR?.let { getMinSubtree(it) } - nodeR?.let { getMinSubtree(it) }?.let { removeNode(it) } + } - successor?.left = node.left - successor?.right = node.right + val successor = getMinSubtree(nodeRight) + removeNode(successor) - if (parentNode == null) { - root = successor - return - } + successor.left = node.left + successor.right = node.right - identifyChild(parentNode, node, successor) - } + identifyChild(parentNode, node, successor) } override fun createNode(key: K, value: V): BSTreeNode { From bbf901d3f9a85e7edab94bb8828d824aed70bf3b Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Thu, 4 Apr 2024 19:49:21 +0300 Subject: [PATCH 103/130] test(BST): add test for remove method --- lib/src/test/kotlin/tree/BSTreeTest.kt | 36 +++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/lib/src/test/kotlin/tree/BSTreeTest.kt b/lib/src/test/kotlin/tree/BSTreeTest.kt index c2c1ac4..4552b01 100644 --- a/lib/src/test/kotlin/tree/BSTreeTest.kt +++ b/lib/src/test/kotlin/tree/BSTreeTest.kt @@ -9,6 +9,36 @@ class BSTreeTest { private lateinit var bst: BSTree private val bstEmpty = BSTree() + @Nested + inner class `Constructor tests` { + @Test + fun `tree without args`() { + val bst = BSTree() + assertEquals(0, bst.size) + } + + @Test + fun `tree with one arg`() { + val bst = BSTree(1, "A") + assertEquals(listOf(Pair(1, "A")), bst.getEntities()) + } + + @Test + fun `tree with some args`() { + val bst: BSTree = BSTree( + arrayOf( + Pair(1, "A"), + Pair(2, "B"), + Pair(3, "C"), + ) + ) + + assertEquals(3, bst.size) + assertEquals(listOf(Pair(1, "A"), Pair(2, "B"), Pair(3, "C")), bst.getEntities()) + } + } + + @Nested inner class `Insert tests` { @BeforeEach @@ -138,10 +168,10 @@ class BSTreeTest { bst.set(2, "B") bst.set(1, "A") bst.set(0, "Z") - bst.set(8, "F") - bst.set(3, "D") + bst.set(8, "K") + bst.set(3, "C") bst.set(5, "E") - bst.set(4, "F") + bst.set(4, "D") bst.set(6, "F") assertEquals("B", bst.remove(2)) assertEquals(7, bst.size) From f3e3d3c42fccb46dfb4f08d222cc211a457fcc11 Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Thu, 4 Apr 2024 20:10:50 +0300 Subject: [PATCH 104/130] refactor(BST): make removeNode method prettier --- lib/src/main/kotlin/tree/BSTree.kt | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/lib/src/main/kotlin/tree/BSTree.kt b/lib/src/main/kotlin/tree/BSTree.kt index 129f1fa..4cf0c50 100644 --- a/lib/src/main/kotlin/tree/BSTree.kt +++ b/lib/src/main/kotlin/tree/BSTree.kt @@ -63,23 +63,17 @@ class BSTree, V> : SearchTree> { override fun removeNode(node: BSTreeNode) { val parentNode = root?.let { searchParentNode(node, it) } - val nodeRight = node.right val nodeLeft = node.left - if (nodeLeft == null && nodeRight == null) { return identifyChild(parentNode, node, null) } if (nodeLeft == null || nodeRight == null) { + val notNullNode = nodeLeft ?: nodeRight - if (nodeLeft == null) { - return identifyChild(parentNode, node, nodeRight) - } else { - return identifyChild(parentNode, node, nodeLeft) - } - + return identifyChild(parentNode, node, notNullNode) } val successor = getMinSubtree(nodeRight) From 4accdb80968bb2c7c1f72cbca97d2981289f8fda Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Thu, 4 Apr 2024 20:29:16 +0300 Subject: [PATCH 105/130] test(AVL): add tests for set in AVL-Tree --- lib/src/test/kotlin/tree/AVLTreeTest.kt | 97 +++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 lib/src/test/kotlin/tree/AVLTreeTest.kt diff --git a/lib/src/test/kotlin/tree/AVLTreeTest.kt b/lib/src/test/kotlin/tree/AVLTreeTest.kt new file mode 100644 index 0000000..5ae198b --- /dev/null +++ b/lib/src/test/kotlin/tree/AVLTreeTest.kt @@ -0,0 +1,97 @@ +package tree + +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import kotlin.random.Random + +class AVLTreeTest { + private val tree = AVLTree() + + @Nested + inner class `set test` { + + @Test + fun `base test`(){ + tree.set(1, 1) + assertEquals(1, tree.size) + assertEquals(listOf(1), tree.getKeys()) + } + + @Test + fun `many node`() { + val entities = arrayOf( + Pair(35, 1), + Pair(21, 1), + Pair(25, 1), + Pair(62, 1), + Pair(12, 1), + Pair(62, 1), + Pair(122, 1), + Pair(621, 1), + Pair(121, 1), + Pair(362, 1), + Pair(35, 1), + Pair(523, 1), + ) + + tree.set(entities) + assertEquals(10, tree.size) + assertEquals(listOf( + 12, 21, 25, 35, 62, 121, 122, 362, 523, 621 + ), tree.getKeys()) + } + + @Test + fun `test right`() { + tree.set(arrayOf( + Pair(2, 1), + Pair(4, 1), + Pair(6, 1), + Pair(8, 1), + Pair(3, 1), + Pair(9, 1))) + + assertEquals(6, tree.size) + assertEquals( + listOf( + 2, 3, 4, 6, 8, 9 + ), tree.getKeys() + ) + } + + @Test + fun `test left`() { + tree.set(5, 1) + tree.set(4, 1) + tree.set(2, 1) + tree.set(1, 1) + assertEquals(4, tree.size) + assertEquals(listOf( + 1, 2, 4, 5 + ), tree.getKeys()) + } + + @Test + fun `stress test`() { + val tree = AVLTree() + val generator = Random(7) + val setWithNull: (Int) -> (Unit) = { key -> tree.set(key, null) } + + val randomKeys = mutableListOf() + for (i in 1..1000000) { + val randomValue = generator.nextInt() + randomKeys.add(randomValue) + setWithNull(randomValue) + } + + val randomKeysDistinct = randomKeys.distinct() + assertEquals(randomKeysDistinct.sorted(), tree.getKeys()) + assertEquals(randomKeysDistinct.size.toLong(), tree.size) + } + } + + @Nested + inner class `remove test`{} +} \ No newline at end of file From 07c3b2d190412b6cedd301f6404a75451474e257 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Thu, 4 Apr 2024 20:41:58 +0300 Subject: [PATCH 106/130] test(STree): add getting test --- lib/src/test/kotlin/tree/SearchTreeTest.kt | 34 +++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/lib/src/test/kotlin/tree/SearchTreeTest.kt b/lib/src/test/kotlin/tree/SearchTreeTest.kt index 48f4f6a..c29f1b8 100644 --- a/lib/src/test/kotlin/tree/SearchTreeTest.kt +++ b/lib/src/test/kotlin/tree/SearchTreeTest.kt @@ -98,4 +98,36 @@ class SearchTreeTest { assertEquals(Pair(8, "A"), bst.predecessor(10)) } } -} \ No newline at end of file + + @Nested + inner class `Getting test` { + @Test + fun `tree with node`() { + bst = BSTree() + bst.set(2, "B") + bst.set(3, "C") + bst.set(4, "D") + bst.set(6, "F") + bst.set(7, "G") + bst.set(8, "H") + + assertEquals(listOf(2, 3, 4, 6, 7, 8), bst.getKeys()) + assertEquals(listOf("B", "C", "D", "F", "G", "H"), bst.getValues()) + assertEquals( + listOf(Pair(2, "B"), Pair(3, "C"), Pair(4, "D"), Pair(6, "F"), Pair(7, "G"), Pair(8, "H")), + bst.getEntities() + ) + } + + @Test + fun `empty tree`() { + val bstEmpty = BSTree() + + assertEquals(listOf(), bstEmpty.getKeys()) + assertEquals(listOf(), bstEmpty.getValues()) + assertEquals(listOf>(), bstEmpty.getEntities()) + } + } +} + + From 3a96a74ca90c807edef16a3a9092bb7becbac961 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Thu, 4 Apr 2024 20:52:40 +0300 Subject: [PATCH 107/130] test(STree): add search test --- lib/src/test/kotlin/tree/SearchTreeTest.kt | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/lib/src/test/kotlin/tree/SearchTreeTest.kt b/lib/src/test/kotlin/tree/SearchTreeTest.kt index c29f1b8..8ce6a5e 100644 --- a/lib/src/test/kotlin/tree/SearchTreeTest.kt +++ b/lib/src/test/kotlin/tree/SearchTreeTest.kt @@ -128,6 +128,27 @@ class SearchTreeTest { assertEquals(listOf>(), bstEmpty.getEntities()) } } + + @Nested + inner class `Search test` { + @Test + fun `tree with node`() { + bst = BSTree() + bst.set(2, "B") + bst.set(3, "C") + bst.set(4, "D") + + assertEquals("B", bst.search(2)) + } + + @Test + fun `empty tree`() { + val bstEmpty = BSTree() + + assertEquals(null, bstEmpty.search(2)) + } + } + } From dd0fb8e4666e230f7c79fa315fa6054326b1fcb1 Mon Sep 17 00:00:00 2001 From: Ilhom Kombaev Date: Thu, 4 Apr 2024 20:57:36 +0300 Subject: [PATCH 108/130] test(STree): add traversal tests --- lib/src/test/kotlin/tree/SearchTreeTest.kt | 66 ++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/lib/src/test/kotlin/tree/SearchTreeTest.kt b/lib/src/test/kotlin/tree/SearchTreeTest.kt index 8ce6a5e..1fafaed 100644 --- a/lib/src/test/kotlin/tree/SearchTreeTest.kt +++ b/lib/src/test/kotlin/tree/SearchTreeTest.kt @@ -149,6 +149,72 @@ class SearchTreeTest { } } + + @Nested + inner class `Traversal methods` { + @Test + fun `inOrderTraversal return empty list on empty tree`() { + val rbt = BSTree() + val result = mutableListOf() + + rbt.inOrderTraversal { result.add(it.first) } + + assertEquals(listOf(), result) + } + + @Test + fun `inOrderTraversal return keys in inOrder order`() { + val bst = BSTree() + bst.set(arrayOf(1 to "Homka", 2 to "Dima", 3 to "Nastya")) + + val result = mutableListOf() + bst.inOrderTraversal { result.add(it.first) } + + assertEquals(listOf(1, 2, 3), bst.getKeys()) + } + + @Test + fun `preOrderTraversal return empty list on empty tree`() { + val rbt = RBTree() + val result = mutableListOf() + + rbt.preOrderTraversal { result.add(it.first) } + + assertEquals(listOf(), result) + } + + @Test + fun `preOrderTraversal return keys in preorder order`() { + val bst = BSTree() + bst.set(arrayOf(2 to "Homka", 1 to "Dima", 3 to "Nastya")) + + val result = mutableListOf() + bst.preOrderTraversal { result.add(it.first) } + + assertEquals(listOf(2, 1, 3), result) + } + + @Test + fun `postOrderTraversal return empty list on empty tree`() { + val rbt = RBTree() + val result = mutableListOf() + + rbt.preOrderTraversal { result.add(it.first) } + + assertEquals(listOf(), result) + } + + @Test + fun `postOrderTraversal return keys in preorder order`() { + val bst = BSTree() + bst.set(arrayOf(2 to "Homka", 1 to "Dima", 3 to "Nastya")) + + val result = mutableListOf() + bst.postOrderTraversal { result.add(it.first) } + + assertEquals(listOf(1, 3, 2), result) + } + } } From 035fa06efdb91d6c36cdb70bd7395b09990a1e96 Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Thu, 4 Apr 2024 20:57:45 +0300 Subject: [PATCH 109/130] test(AVL): add tests for remove in AVL-Tree --- lib/src/test/kotlin/tree/AVLTreeTest.kt | 34 ++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/lib/src/test/kotlin/tree/AVLTreeTest.kt b/lib/src/test/kotlin/tree/AVLTreeTest.kt index 5ae198b..a40a022 100644 --- a/lib/src/test/kotlin/tree/AVLTreeTest.kt +++ b/lib/src/test/kotlin/tree/AVLTreeTest.kt @@ -93,5 +93,37 @@ class AVLTreeTest { } @Nested - inner class `remove test`{} + inner class `remove test`{ + @Test + fun `base test`() { + tree.set(1, 1) + tree.remove(1) + assertEquals(0, tree.size) + } + + @Test + fun `many test`(){ + val entities = arrayOf( + Pair(35, 1), + Pair(21, 1), + Pair(25, 1), + Pair(62, 1), + Pair(12, 1), + Pair(122, 1), + Pair(621, 1), + Pair(121, 1), + Pair(362, 1), + Pair(523, 1), + ) + + tree.set(entities) + tree.remove(arrayOf( + 35, 12, 523 + )) + assertEquals(7, tree.size) + assertEquals(listOf( + 21, 25, 62, 121, 122, 362, 621 + ), tree.getKeys()) + } + } } \ No newline at end of file From b10fe3ee6693bed7123853a75ea66800ccdf3b6a Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sat, 6 Apr 2024 23:55:06 +0300 Subject: [PATCH 110/130] test(BST): refactor remove tests --- lib/src/test/kotlin/tree/BSTreeTest.kt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/src/test/kotlin/tree/BSTreeTest.kt b/lib/src/test/kotlin/tree/BSTreeTest.kt index 4552b01..87bd427 100644 --- a/lib/src/test/kotlin/tree/BSTreeTest.kt +++ b/lib/src/test/kotlin/tree/BSTreeTest.kt @@ -112,7 +112,7 @@ class BSTreeTest { inner class `Remove tests` { @Test - fun `remove single root`() { + fun `remove root without children`() { bst = BSTree() bst.set(2, "B") assertEquals("B", bst.remove(2)) @@ -120,7 +120,8 @@ class BSTreeTest { } @Test - fun `remove root with two children(list)`() { + fun `remove root with two children`() { + // successor root is root.right bst = BSTree() bst.set(2, "B") bst.set(3, "C") @@ -134,7 +135,8 @@ class BSTreeTest { } @Test - fun `remove root with two children`() { + fun `remove root with two children1`() { + // successor root is list bst = BSTree() bst.set(2, "B") bst.set(1, "A") @@ -149,6 +151,7 @@ class BSTreeTest { @Test fun `remove root with two children2`() { + // successor root has one child bst = BSTree() bst.set(2, "B") bst.set(1, "A") @@ -164,6 +167,7 @@ class BSTreeTest { @Test fun `remove root with two children3`() { + // successor root has a subtree bst = BSTree() bst.set(2, "B") bst.set(1, "A") From 7d58692859d6c03290d8ca52681f55f97c3c4876 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sun, 7 Apr 2024 00:43:00 +0300 Subject: [PATCH 111/130] refactor: make method inOrderTraversal more prettier --- lib/src/main/kotlin/tree/SearchTree.kt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index a12dcb5..5fad358 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -264,11 +264,12 @@ abstract class SearchTree, V, Node : BinaryTreeNode) -> (Unit)) { fun inOrder(node: Node?) { - if (node != null) { - inOrder(node.left) - action(Pair(node.key, node.value)) - inOrder(node.right) - } + if (node == null) return + + inOrder(node.left) + action(Pair(node.key, node.value)) + inOrder(node.right) + } inOrder(this.root) From 1764f72b160d05c8d67f6c8fb04290a578bc281e Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sun, 7 Apr 2024 00:44:48 +0300 Subject: [PATCH 112/130] refactor: delete empty line in method inOrderTraversal --- lib/src/main/kotlin/tree/SearchTree.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index 5fad358..b89dd88 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -269,7 +269,6 @@ abstract class SearchTree, V, Node : BinaryTreeNode Date: Sun, 7 Apr 2024 00:57:29 +0300 Subject: [PATCH 113/130] fix(STree): fix bug in method predecessor --- lib/src/main/kotlin/tree/SearchTree.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index b89dd88..ec4b216 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -219,7 +219,7 @@ abstract class SearchTree, V, Node : BinaryTreeNode { var node = root - var predecessor: Node? = root?.left + var predecessor: Node? = null while (node != null) { if (node.key < key) { From e9220f8776ac982d14f0b0b53163a29a97a0b84c Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sun, 7 Apr 2024 01:01:31 +0300 Subject: [PATCH 114/130] test(STree): add cases in successor and predecessor tests --- lib/src/test/kotlin/tree/SearchTreeTest.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/src/test/kotlin/tree/SearchTreeTest.kt b/lib/src/test/kotlin/tree/SearchTreeTest.kt index 1fafaed..a788e6c 100644 --- a/lib/src/test/kotlin/tree/SearchTreeTest.kt +++ b/lib/src/test/kotlin/tree/SearchTreeTest.kt @@ -75,6 +75,7 @@ class SearchTreeTest { assertEquals(Pair(6, "A"), bst.successor(5)) assertEquals(Pair(8, "A"), bst.successor(6)) assertEquals(Pair(10, "A"), bst.successor(8)) + assertEquals(Pair(null, null), bst.successor(10)) } @Test @@ -89,6 +90,7 @@ class SearchTreeTest { @Test fun `predecessor() test with existed keys`() { + assertEquals(Pair(null, null), bst.predecessor(1)) assertEquals(Pair(1, "A"), bst.predecessor(2)) assertEquals(Pair(2, "A"), bst.predecessor(3)) assertEquals(Pair(3, "A"), bst.predecessor(4)) From 2c2690448027c68583a5f14aac57b0e3234c0247 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sun, 7 Apr 2024 01:09:24 +0300 Subject: [PATCH 115/130] test(STree): refactor getting tests --- lib/src/test/kotlin/tree/SearchTreeTest.kt | 25 ++++++++-------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/lib/src/test/kotlin/tree/SearchTreeTest.kt b/lib/src/test/kotlin/tree/SearchTreeTest.kt index a788e6c..8b46cad 100644 --- a/lib/src/test/kotlin/tree/SearchTreeTest.kt +++ b/lib/src/test/kotlin/tree/SearchTreeTest.kt @@ -105,29 +105,22 @@ class SearchTreeTest { inner class `Getting test` { @Test fun `tree with node`() { - bst = BSTree() - bst.set(2, "B") - bst.set(3, "C") - bst.set(4, "D") - bst.set(6, "F") - bst.set(7, "G") - bst.set(8, "H") - - assertEquals(listOf(2, 3, 4, 6, 7, 8), bst.getKeys()) - assertEquals(listOf("B", "C", "D", "F", "G", "H"), bst.getValues()) + assertEquals(listOf(1, 2, 3, 4, 5, 6, 8, 10), bst.getKeys()) + assertEquals(listOf("A", "A", "A", "A", "A", "A", "A", "A"), bst.getValues()) assertEquals( - listOf(Pair(2, "B"), Pair(3, "C"), Pair(4, "D"), Pair(6, "F"), Pair(7, "G"), Pair(8, "H")), + listOf( + Pair(1, "A"), Pair(2, "A"), Pair(3, "A"), Pair(4, "A"), + Pair(5, "A"), Pair(6, "A"), Pair(8, "A"), Pair(10, "A") + ), bst.getEntities() ) } @Test fun `empty tree`() { - val bstEmpty = BSTree() - - assertEquals(listOf(), bstEmpty.getKeys()) - assertEquals(listOf(), bstEmpty.getValues()) - assertEquals(listOf>(), bstEmpty.getEntities()) + assertEquals(listOf(), bstWithoutNodes.getKeys()) + assertEquals(listOf(), bstWithoutNodes.getValues()) + assertEquals(listOf>(), bstWithoutNodes.getEntities()) } } From 9f20685994b31a924c4f9f7d8353a7d5c0df9af3 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sun, 7 Apr 2024 01:15:55 +0300 Subject: [PATCH 116/130] test(STree): add cases in successor and predecessor tests --- lib/src/test/kotlin/tree/SearchTreeTest.kt | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/lib/src/test/kotlin/tree/SearchTreeTest.kt b/lib/src/test/kotlin/tree/SearchTreeTest.kt index 8b46cad..c84077f 100644 --- a/lib/src/test/kotlin/tree/SearchTreeTest.kt +++ b/lib/src/test/kotlin/tree/SearchTreeTest.kt @@ -84,8 +84,13 @@ class SearchTreeTest { } @Test - fun `predecessor() if key don't exists it return previous key`() { - assertEquals(Pair(6, "A"), bst.predecessor(7)) + fun `successor() in empty tree`() { + assertEquals(Pair(null, null), bstWithoutNodes.successor(7)) + } + + @Test + fun `predecessor() in empty tree`() { + assertEquals(Pair(null, null), bstWithoutNodes.predecessor(7)) } @Test @@ -128,19 +133,12 @@ class SearchTreeTest { inner class `Search test` { @Test fun `tree with node`() { - bst = BSTree() - bst.set(2, "B") - bst.set(3, "C") - bst.set(4, "D") - - assertEquals("B", bst.search(2)) + assertEquals("A", bst.search(2)) } @Test fun `empty tree`() { - val bstEmpty = BSTree() - - assertEquals(null, bstEmpty.search(2)) + assertEquals(null, bstWithoutNodes.search(2)) } } From f70e08e034993e162091b6c20ec2cad0d25bfad5 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sun, 7 Apr 2024 02:52:19 +0300 Subject: [PATCH 117/130] test(STree): add remove tests and refactor search tests --- lib/src/test/kotlin/tree/SearchTreeTest.kt | 31 +++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/lib/src/test/kotlin/tree/SearchTreeTest.kt b/lib/src/test/kotlin/tree/SearchTreeTest.kt index c84077f..881679a 100644 --- a/lib/src/test/kotlin/tree/SearchTreeTest.kt +++ b/lib/src/test/kotlin/tree/SearchTreeTest.kt @@ -130,7 +130,7 @@ class SearchTreeTest { } @Nested - inner class `Search test` { + inner class `Search tests` { @Test fun `tree with node`() { assertEquals("A", bst.search(2)) @@ -142,6 +142,35 @@ class SearchTreeTest { } } + @Nested + inner class `Remove tests` { + @Test + fun `remove exist nodes`() { + assertEquals("A", bst.remove(2)) + assertEquals(listOf(1, 3, 4, 5, 6, 8, 10), bst.getKeys()) + + assertEquals(listOf("A", "A", "A"), bst.remove(arrayOf(1, 5, 10))) + assertEquals(listOf(3, 4, 6, 8), bst.getKeys()) + } + + @Test + fun `remove don't exists nodes`() { + assertEquals(null, bst.remove(0)) + assertEquals(listOf(1, 2, 3, 4, 5, 6, 8, 10), bst.getKeys()) + + assertEquals(listOf(null, null, null), bst.remove(arrayOf(11, 35, 100))) + assertEquals(listOf(1, 2, 3, 4, 5, 6, 8, 10), bst.getKeys()) + } + + @Test + fun `remove nodes from empty tree`() { + assertEquals(null, bstWithoutNodes.remove(2)) + assertEquals(listOf(), bstWithoutNodes.getKeys()) + + assertEquals(listOf(null, null, null), bstWithoutNodes.remove(arrayOf(1, 3, 10))) + assertEquals(listOf(), bstWithoutNodes.getKeys()) + } + } @Nested inner class `Traversal methods` { From 2691d72b3997d27800148afc4942ede9faeac39c Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sun, 7 Apr 2024 03:34:08 +0300 Subject: [PATCH 118/130] test(STree): add setting tests, add check in remove and search tests --- lib/src/test/kotlin/tree/SearchTreeTest.kt | 71 +++++++++++++++++++++- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/lib/src/test/kotlin/tree/SearchTreeTest.kt b/lib/src/test/kotlin/tree/SearchTreeTest.kt index 881679a..b699386 100644 --- a/lib/src/test/kotlin/tree/SearchTreeTest.kt +++ b/lib/src/test/kotlin/tree/SearchTreeTest.kt @@ -129,13 +129,71 @@ class SearchTreeTest { } } + @Nested + inner class `Setting tests` { + @Test + fun `set new nodes`() { + assertEquals(null, bst.set(19, "B")) + assertEquals(9, bst.size) + assertEquals(listOf(1, 2, 3, 4, 5, 6, 8, 10, 19), bst.getKeys()) + + assertEquals(listOf(null, null, null), bst.set(arrayOf(Pair(12, "B"), Pair(0, "B"), Pair(7, "B")))) + assertEquals(12, bst.size) + assertEquals(listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 19), bst.getKeys()) + } + + @Test + fun `set the same nodes`() { + assertEquals("A", bst.set(10, "B")) + assertEquals(8, bst.size) + assertEquals( + listOf( + Pair(1, "A"), Pair(2, "A"), Pair(3, "A"), Pair(4, "A"), + Pair(5, "A"), Pair(6, "A"), Pair(8, "A"), Pair(10, "B") + ), + bst.getEntities() + ) + + assertEquals(listOf("A", "A", "A"), bst.set(arrayOf(Pair(2, "B"), Pair(6, "B"), Pair(4, "B")))) + assertEquals(8, bst.size) + assertEquals( + listOf( + Pair(1, "A"), Pair(2, "B"), Pair(3, "A"), Pair(4, "B"), + Pair(5, "A"), Pair(6, "B"), Pair(8, "A"), Pair(10, "B") + ), + bst.getEntities() + ) + } + + @Test + fun `set nodes in empty tree`() { + assertEquals(null, bstWithoutNodes.set(19, "B")) + assertEquals(1, bstWithoutNodes.size) + assertEquals(listOf(Pair(19, "B")), bstWithoutNodes.getEntities()) + + bstWithoutNodes.remove(19) + + assertEquals( + listOf(null, null, null), + bstWithoutNodes.set(arrayOf(Pair(12, "B"), Pair(0, "B"), Pair(7, "B"))) + ) + assertEquals(3, bstWithoutNodes.size) + assertEquals(listOf(Pair(0, "B"), Pair(7, "B"), Pair(12, "B")), bstWithoutNodes.getEntities()) + } + } + @Nested inner class `Search tests` { @Test - fun `tree with node`() { + fun `search exist node`() { assertEquals("A", bst.search(2)) } + @Test + fun `search don't exist node`() { + assertEquals(null, bst.search(0)) + } + @Test fun `empty tree`() { assertEquals(null, bstWithoutNodes.search(2)) @@ -146,29 +204,38 @@ class SearchTreeTest { inner class `Remove tests` { @Test fun `remove exist nodes`() { + assertEquals(8, bst.size) assertEquals("A", bst.remove(2)) assertEquals(listOf(1, 3, 4, 5, 6, 8, 10), bst.getKeys()) + assertEquals(7, bst.size) assertEquals(listOf("A", "A", "A"), bst.remove(arrayOf(1, 5, 10))) assertEquals(listOf(3, 4, 6, 8), bst.getKeys()) + assertEquals(4, bst.size) } @Test - fun `remove don't exists nodes`() { + fun `remove don't exist nodes`() { + assertEquals(8, bst.size) assertEquals(null, bst.remove(0)) assertEquals(listOf(1, 2, 3, 4, 5, 6, 8, 10), bst.getKeys()) + assertEquals(8, bst.size) assertEquals(listOf(null, null, null), bst.remove(arrayOf(11, 35, 100))) assertEquals(listOf(1, 2, 3, 4, 5, 6, 8, 10), bst.getKeys()) + assertEquals(8, bst.size) } @Test fun `remove nodes from empty tree`() { + assertEquals(0, bstWithoutNodes.size) assertEquals(null, bstWithoutNodes.remove(2)) assertEquals(listOf(), bstWithoutNodes.getKeys()) + assertEquals(0, bstWithoutNodes.size) assertEquals(listOf(null, null, null), bstWithoutNodes.remove(arrayOf(1, 3, 10))) assertEquals(listOf(), bstWithoutNodes.getKeys()) + assertEquals(0, bstWithoutNodes.size) } } From dd776bdda380e3a48b32fa7bcae79ca97df1fb4d Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sun, 7 Apr 2024 03:57:35 +0300 Subject: [PATCH 119/130] test(STree): add setIfEmpty tests --- lib/src/test/kotlin/tree/SearchTreeTest.kt | 57 +++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/lib/src/test/kotlin/tree/SearchTreeTest.kt b/lib/src/test/kotlin/tree/SearchTreeTest.kt index b699386..a2c2429 100644 --- a/lib/src/test/kotlin/tree/SearchTreeTest.kt +++ b/lib/src/test/kotlin/tree/SearchTreeTest.kt @@ -181,7 +181,62 @@ class SearchTreeTest { assertEquals(listOf(Pair(0, "B"), Pair(7, "B"), Pair(12, "B")), bstWithoutNodes.getEntities()) } } - + + + @Nested + inner class `SetIfEmpty tests` { + @Test + fun `set new nodes`() { + assertEquals(null, bst.setIfEmpty(19, "B")) + assertEquals(9, bst.size) + assertEquals(listOf(1, 2, 3, 4, 5, 6, 8, 10, 19), bst.getKeys()) + + assertEquals(listOf(null, null, null), bst.setIfEmpty(arrayOf(Pair(12, "B"), Pair(0, "B"), Pair(7, "B")))) + assertEquals(12, bst.size) + assertEquals(listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 19), bst.getKeys()) + } + + @Test + fun `set the same nodes`() { + assertEquals("A", bst.setIfEmpty(10, "B")) + assertEquals(8, bst.size) + assertEquals( + listOf( + Pair(1, "A"), Pair(2, "A"), Pair(3, "A"), Pair(4, "A"), + Pair(5, "A"), Pair(6, "A"), Pair(8, "A"), Pair(10, "A") + ), + bst.getEntities() + ) + + assertEquals(listOf("A", "A", "A"), bst.setIfEmpty(arrayOf(Pair(2, "B"), Pair(6, "B"), Pair(4, "B")))) + assertEquals(8, bst.size) + assertEquals( + listOf( + Pair(1, "A"), Pair(2, "A"), Pair(3, "A"), Pair(4, "A"), + Pair(5, "A"), Pair(6, "A"), Pair(8, "A"), Pair(10, "A") + ), + bst.getEntities() + ) + } + + @Test + fun `set nodes in empty tree`() { + assertEquals(null, bstWithoutNodes.setIfEmpty(19, "B")) + assertEquals(1, bstWithoutNodes.size) + assertEquals(listOf(Pair(19, "B")), bstWithoutNodes.getEntities()) + + bstWithoutNodes.remove(19) + + assertEquals( + listOf(null, null, null), + bstWithoutNodes.setIfEmpty(arrayOf(Pair(12, "B"), Pair(0, "B"), Pair(7, "B"))) + ) + assertEquals(3, bstWithoutNodes.size) + assertEquals(listOf(Pair(0, "B"), Pair(7, "B"), Pair(12, "B")), bstWithoutNodes.getEntities()) + } + } + + @Nested inner class `Search tests` { @Test From 0a9ab7125bcc32037279fa1f6feaa13faf5bd297 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sun, 7 Apr 2024 04:03:12 +0300 Subject: [PATCH 120/130] test(STree): add Constructors tests --- lib/src/test/kotlin/tree/SearchTreeTest.kt | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/lib/src/test/kotlin/tree/SearchTreeTest.kt b/lib/src/test/kotlin/tree/SearchTreeTest.kt index a2c2429..09d3645 100644 --- a/lib/src/test/kotlin/tree/SearchTreeTest.kt +++ b/lib/src/test/kotlin/tree/SearchTreeTest.kt @@ -23,6 +23,31 @@ class SearchTreeTest { bst.set(10, "A") } + @Nested + inner class `Constructor tests` { + + @Test + fun `tree with one arg`() { + val bst = BSTree(1, "A") + assertEquals(listOf(Pair(1, "A")), bst.getEntities()) + } + + @Test + fun `tree with some args`() { + val bst: BSTree = BSTree( + arrayOf( + Pair(1, "A"), + Pair(2, "B"), + Pair(3, "C"), + ) + ) + + assertEquals(3, bst.size) + assertEquals(listOf(Pair(1, "A"), Pair(2, "B"), Pair(3, "C")), bst.getEntities()) + } + } + + @Nested inner class `Min and max tests` { @Test From ccb1090f4dbf9a8581da40dde956206dbf85c426 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sun, 7 Apr 2024 04:21:30 +0300 Subject: [PATCH 121/130] test(STree): add resently keys tests --- lib/src/test/kotlin/tree/SearchTreeTest.kt | 32 +++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/lib/src/test/kotlin/tree/SearchTreeTest.kt b/lib/src/test/kotlin/tree/SearchTreeTest.kt index 09d3645..48aaf83 100644 --- a/lib/src/test/kotlin/tree/SearchTreeTest.kt +++ b/lib/src/test/kotlin/tree/SearchTreeTest.kt @@ -47,7 +47,6 @@ class SearchTreeTest { } } - @Nested inner class `Min and max tests` { @Test @@ -261,7 +260,38 @@ class SearchTreeTest { } } + @Nested + inner class `Resently keys tests` { + @Test + fun `set in empty tree`() { + bstWithoutNodes.set(1, "B") + assertEquals(1, bstWithoutNodes.recentlyKey) + + bstWithoutNodes.remove(1) + + bstWithoutNodes.setIfEmpty(2, "B") + assertEquals(2, bstWithoutNodes.recentlyKey) + } + + @Test + fun `set new node in tree`() { + bst.set(0, "B") + assertEquals(0, bst.recentlyKey) + + bst.setIfEmpty(19, "B") + assertEquals(19, bst.recentlyKey) + } + @Test + fun `set the same node in tree`() { + bst.set(1, "B") + assertEquals(1, bst.recentlyKey) + + bst.setIfEmpty(10, "B") + assertEquals(1, bst.recentlyKey) + } + } + @Nested inner class `Search tests` { @Test From f234f69e0e187f19d3c86641e9a619d044984741 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sun, 7 Apr 2024 16:02:38 +0300 Subject: [PATCH 122/130] test(STree): group test of methods set --- lib/src/test/kotlin/tree/SearchTreeTest.kt | 122 ++++++++------------- 1 file changed, 43 insertions(+), 79 deletions(-) diff --git a/lib/src/test/kotlin/tree/SearchTreeTest.kt b/lib/src/test/kotlin/tree/SearchTreeTest.kt index 48aaf83..dd1134a 100644 --- a/lib/src/test/kotlin/tree/SearchTreeTest.kt +++ b/lib/src/test/kotlin/tree/SearchTreeTest.kt @@ -155,15 +155,26 @@ class SearchTreeTest { @Nested inner class `Setting tests` { + @Test fun `set new nodes`() { assertEquals(null, bst.set(19, "B")) assertEquals(9, bst.size) assertEquals(listOf(1, 2, 3, 4, 5, 6, 8, 10, 19), bst.getKeys()) - assertEquals(listOf(null, null, null), bst.set(arrayOf(Pair(12, "B"), Pair(0, "B"), Pair(7, "B")))) - assertEquals(12, bst.size) - assertEquals(listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 19), bst.getKeys()) + assertEquals(null, bst.setIfEmpty(11, "B")) + assertEquals(10, bst.size) + assertEquals(listOf(1, 2, 3, 4, 5, 6, 8, 10, 11, 19), bst.getKeys()) + + assertEquals(listOf(null, null, null), bst.set(arrayOf(Pair(20, "B"), Pair(-5, "B"), Pair(7, "B")))) + assertEquals(7, bst.recentlyKey) + assertEquals(13, bst.size) + assertEquals(listOf(-5, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 19, 20), bst.getKeys()) + + assertEquals(listOf(null, null, null), bst.setIfEmpty(arrayOf(Pair(9, "B"), Pair(0, "B"), Pair(22, "B")))) + assertEquals(22, bst.recentlyKey) + assertEquals(16, bst.size) + assertEquals(listOf(-5, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 19, 20, 22), bst.getKeys()) } @Test @@ -178,66 +189,34 @@ class SearchTreeTest { bst.getEntities() ) - assertEquals(listOf("A", "A", "A"), bst.set(arrayOf(Pair(2, "B"), Pair(6, "B"), Pair(4, "B")))) + assertEquals("A", bst.setIfEmpty(8, "B")) assertEquals(8, bst.size) assertEquals( listOf( - Pair(1, "A"), Pair(2, "B"), Pair(3, "A"), Pair(4, "B"), - Pair(5, "A"), Pair(6, "B"), Pair(8, "A"), Pair(10, "B") + Pair(1, "A"), Pair(2, "A"), Pair(3, "A"), Pair(4, "A"), + Pair(5, "A"), Pair(6, "A"), Pair(8, "A"), Pair(10, "B") ), bst.getEntities() ) - } - - @Test - fun `set nodes in empty tree`() { - assertEquals(null, bstWithoutNodes.set(19, "B")) - assertEquals(1, bstWithoutNodes.size) - assertEquals(listOf(Pair(19, "B")), bstWithoutNodes.getEntities()) - - bstWithoutNodes.remove(19) - - assertEquals( - listOf(null, null, null), - bstWithoutNodes.set(arrayOf(Pair(12, "B"), Pair(0, "B"), Pair(7, "B"))) - ) - assertEquals(3, bstWithoutNodes.size) - assertEquals(listOf(Pair(0, "B"), Pair(7, "B"), Pair(12, "B")), bstWithoutNodes.getEntities()) - } - } - - - @Nested - inner class `SetIfEmpty tests` { - @Test - fun `set new nodes`() { - assertEquals(null, bst.setIfEmpty(19, "B")) - assertEquals(9, bst.size) - assertEquals(listOf(1, 2, 3, 4, 5, 6, 8, 10, 19), bst.getKeys()) - assertEquals(listOf(null, null, null), bst.setIfEmpty(arrayOf(Pair(12, "B"), Pair(0, "B"), Pair(7, "B")))) - assertEquals(12, bst.size) - assertEquals(listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 19), bst.getKeys()) - } - - @Test - fun `set the same nodes`() { - assertEquals("A", bst.setIfEmpty(10, "B")) + assertEquals(listOf("A", "A", "A"), bst.set(arrayOf(Pair(2, "B"), Pair(6, "B"), Pair(4, "B")))) + assertEquals(4, bst.recentlyKey) assertEquals(8, bst.size) assertEquals( listOf( - Pair(1, "A"), Pair(2, "A"), Pair(3, "A"), Pair(4, "A"), - Pair(5, "A"), Pair(6, "A"), Pair(8, "A"), Pair(10, "A") + Pair(1, "A"), Pair(2, "B"), Pair(3, "A"), Pair(4, "B"), + Pair(5, "A"), Pair(6, "B"), Pair(8, "A"), Pair(10, "B") ), bst.getEntities() ) - assertEquals(listOf("A", "A", "A"), bst.setIfEmpty(arrayOf(Pair(2, "B"), Pair(6, "B"), Pair(4, "B")))) + assertEquals(listOf("A", "A", "A"), bst.setIfEmpty(arrayOf(Pair(1, "B"), Pair(5, "B"), Pair(3, "B")))) + assertEquals(4, bst.recentlyKey) assertEquals(8, bst.size) assertEquals( listOf( - Pair(1, "A"), Pair(2, "A"), Pair(3, "A"), Pair(4, "A"), - Pair(5, "A"), Pair(6, "A"), Pair(8, "A"), Pair(10, "A") + Pair(1, "A"), Pair(2, "B"), Pair(3, "A"), Pair(4, "B"), + Pair(5, "A"), Pair(6, "B"), Pair(8, "A"), Pair(10, "B") ), bst.getEntities() ) @@ -245,53 +224,38 @@ class SearchTreeTest { @Test fun `set nodes in empty tree`() { + assertEquals(null, bstWithoutNodes.set(19, "B")) + assertEquals(1, bstWithoutNodes.size) + assertEquals(listOf(Pair(19, "B")), bstWithoutNodes.getEntities()) + + bstWithoutNodes.clear() + assertEquals(null, bstWithoutNodes.setIfEmpty(19, "B")) assertEquals(1, bstWithoutNodes.size) assertEquals(listOf(Pair(19, "B")), bstWithoutNodes.getEntities()) - bstWithoutNodes.remove(19) + bstWithoutNodes.clear() assertEquals( listOf(null, null, null), - bstWithoutNodes.setIfEmpty(arrayOf(Pair(12, "B"), Pair(0, "B"), Pair(7, "B"))) + bstWithoutNodes.set(arrayOf(Pair(12, "B"), Pair(0, "B"), Pair(7, "B"))) ) + assertEquals(7, bstWithoutNodes.recentlyKey) assertEquals(3, bstWithoutNodes.size) assertEquals(listOf(Pair(0, "B"), Pair(7, "B"), Pair(12, "B")), bstWithoutNodes.getEntities()) - } - } - @Nested - inner class `Resently keys tests` { - @Test - fun `set in empty tree`() { - bstWithoutNodes.set(1, "B") - assertEquals(1, bstWithoutNodes.recentlyKey) - - bstWithoutNodes.remove(1) - - bstWithoutNodes.setIfEmpty(2, "B") - assertEquals(2, bstWithoutNodes.recentlyKey) - } - - @Test - fun `set new node in tree`() { - bst.set(0, "B") - assertEquals(0, bst.recentlyKey) - - bst.setIfEmpty(19, "B") - assertEquals(19, bst.recentlyKey) - } + bstWithoutNodes.clear() - @Test - fun `set the same node in tree`() { - bst.set(1, "B") - assertEquals(1, bst.recentlyKey) - - bst.setIfEmpty(10, "B") - assertEquals(1, bst.recentlyKey) + assertEquals( + listOf(null, null, null), + bstWithoutNodes.setIfEmpty(arrayOf(Pair(12, "B"), Pair(0, "B"), Pair(7, "B"))) + ) + assertEquals(7, bstWithoutNodes.recentlyKey) + assertEquals(3, bstWithoutNodes.size) + assertEquals(listOf(Pair(0, "B"), Pair(7, "B"), Pair(12, "B")), bstWithoutNodes.getEntities()) } } - + @Nested inner class `Search tests` { @Test From 6cc7249fe05d1519838ebd013cdd12d993075d7e Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sun, 7 Apr 2024 16:37:00 +0300 Subject: [PATCH 123/130] test(STree): add case to constructor test --- lib/src/test/kotlin/tree/SearchTreeTest.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/src/test/kotlin/tree/SearchTreeTest.kt b/lib/src/test/kotlin/tree/SearchTreeTest.kt index dd1134a..2b26cc6 100644 --- a/lib/src/test/kotlin/tree/SearchTreeTest.kt +++ b/lib/src/test/kotlin/tree/SearchTreeTest.kt @@ -25,6 +25,11 @@ class SearchTreeTest { @Nested inner class `Constructor tests` { + @Test + fun `tree without args`() { + val bst = BSTree() + assertEquals(0, bst.size) + } @Test fun `tree with one arg`() { From 74a11c2ff8018ed2f33c8e7a676d98be0c40b443 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sun, 7 Apr 2024 16:59:36 +0300 Subject: [PATCH 124/130] test(STree): make setting, remove tests prettier --- lib/src/test/kotlin/tree/SearchTreeTest.kt | 37 ---------------------- 1 file changed, 37 deletions(-) diff --git a/lib/src/test/kotlin/tree/SearchTreeTest.kt b/lib/src/test/kotlin/tree/SearchTreeTest.kt index 2b26cc6..8ef5af2 100644 --- a/lib/src/test/kotlin/tree/SearchTreeTest.kt +++ b/lib/src/test/kotlin/tree/SearchTreeTest.kt @@ -164,17 +164,11 @@ class SearchTreeTest { @Test fun `set new nodes`() { assertEquals(null, bst.set(19, "B")) - assertEquals(9, bst.size) - assertEquals(listOf(1, 2, 3, 4, 5, 6, 8, 10, 19), bst.getKeys()) assertEquals(null, bst.setIfEmpty(11, "B")) - assertEquals(10, bst.size) - assertEquals(listOf(1, 2, 3, 4, 5, 6, 8, 10, 11, 19), bst.getKeys()) assertEquals(listOf(null, null, null), bst.set(arrayOf(Pair(20, "B"), Pair(-5, "B"), Pair(7, "B")))) assertEquals(7, bst.recentlyKey) - assertEquals(13, bst.size) - assertEquals(listOf(-5, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 19, 20), bst.getKeys()) assertEquals(listOf(null, null, null), bst.setIfEmpty(arrayOf(Pair(9, "B"), Pair(0, "B"), Pair(22, "B")))) assertEquals(22, bst.recentlyKey) @@ -185,35 +179,11 @@ class SearchTreeTest { @Test fun `set the same nodes`() { assertEquals("A", bst.set(10, "B")) - assertEquals(8, bst.size) - assertEquals( - listOf( - Pair(1, "A"), Pair(2, "A"), Pair(3, "A"), Pair(4, "A"), - Pair(5, "A"), Pair(6, "A"), Pair(8, "A"), Pair(10, "B") - ), - bst.getEntities() - ) assertEquals("A", bst.setIfEmpty(8, "B")) - assertEquals(8, bst.size) - assertEquals( - listOf( - Pair(1, "A"), Pair(2, "A"), Pair(3, "A"), Pair(4, "A"), - Pair(5, "A"), Pair(6, "A"), Pair(8, "A"), Pair(10, "B") - ), - bst.getEntities() - ) assertEquals(listOf("A", "A", "A"), bst.set(arrayOf(Pair(2, "B"), Pair(6, "B"), Pair(4, "B")))) assertEquals(4, bst.recentlyKey) - assertEquals(8, bst.size) - assertEquals( - listOf( - Pair(1, "A"), Pair(2, "B"), Pair(3, "A"), Pair(4, "B"), - Pair(5, "A"), Pair(6, "B"), Pair(8, "A"), Pair(10, "B") - ), - bst.getEntities() - ) assertEquals(listOf("A", "A", "A"), bst.setIfEmpty(arrayOf(Pair(1, "B"), Pair(5, "B"), Pair(3, "B")))) assertEquals(4, bst.recentlyKey) @@ -283,7 +253,6 @@ class SearchTreeTest { inner class `Remove tests` { @Test fun `remove exist nodes`() { - assertEquals(8, bst.size) assertEquals("A", bst.remove(2)) assertEquals(listOf(1, 3, 4, 5, 6, 8, 10), bst.getKeys()) assertEquals(7, bst.size) @@ -295,10 +264,7 @@ class SearchTreeTest { @Test fun `remove don't exist nodes`() { - assertEquals(8, bst.size) assertEquals(null, bst.remove(0)) - assertEquals(listOf(1, 2, 3, 4, 5, 6, 8, 10), bst.getKeys()) - assertEquals(8, bst.size) assertEquals(listOf(null, null, null), bst.remove(arrayOf(11, 35, 100))) assertEquals(listOf(1, 2, 3, 4, 5, 6, 8, 10), bst.getKeys()) @@ -307,10 +273,7 @@ class SearchTreeTest { @Test fun `remove nodes from empty tree`() { - assertEquals(0, bstWithoutNodes.size) assertEquals(null, bstWithoutNodes.remove(2)) - assertEquals(listOf(), bstWithoutNodes.getKeys()) - assertEquals(0, bstWithoutNodes.size) assertEquals(listOf(null, null, null), bstWithoutNodes.remove(arrayOf(1, 3, 10))) assertEquals(listOf(), bstWithoutNodes.getKeys()) From 2f431efcf8d03e330df726851bdd3c6ab612029f Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Wed, 10 Apr 2024 01:37:59 +0300 Subject: [PATCH 125/130] fix(AVL-T): fix remove method in AVLTree --- lib/src/main/kotlin/tree/AVLTree.kt | 57 +++++++++++++++++------------ 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/lib/src/main/kotlin/tree/AVLTree.kt b/lib/src/main/kotlin/tree/AVLTree.kt index 1f44f50..62bc384 100644 --- a/lib/src/main/kotlin/tree/AVLTree.kt +++ b/lib/src/main/kotlin/tree/AVLTree.kt @@ -96,46 +96,57 @@ class AVLTree, V> : SearchTree>() { root = insertRecursive(root, node) } - private fun minValueNode(node: AVLTreeNode): AVLTreeNode { - var current: AVLTreeNode = node - var leftNode = current.left + private fun minValueNode(node: AVLTreeNode?): AVLTreeNode? { + var current = node - while (leftNode != null) { - current = leftNode - leftNode = current.left - } + while (current?.left != null) current = current.left return current } + private fun changeNode(oldNode: AVLTreeNode, newNode: AVLTreeNode?): AVLTreeNode? { + if (newNode == null) { + return null + } + + val node = createNode(newNode.key, newNode.value) + + node.right = oldNode.right + node.left = oldNode.left + node.height = oldNode.height + + return node + } private fun removeRecursive(root: AVLTreeNode?, node: AVLTreeNode): AVLTreeNode? { var rootNode = root - if (rootNode == null) { - return root - } + if (rootNode == null) return rootNode if (rootNode.key > node.key) { rootNode.left = removeRecursive(rootNode.left, node) - return rebalanced(rootNode, node) } else if (rootNode.key < node.key) { rootNode.right = removeRecursive(rootNode.right, node) - return rebalanced(rootNode, node) } + else{ + if (rootNode.left == null || rootNode.right == null) { + var newNode: AVLTreeNode? = null + newNode = rootNode.left ?: rootNode.right + if (newNode == null) { + rootNode = null + } else { + rootNode = newNode + } + } else { + val newNode = minValueNode(rootNode.right) + rootNode = changeNode(rootNode, newNode) - val rootNodeRight = rootNode.right - val rootNodeLeft = rootNode.left - if (rootNodeLeft == null || rootNodeRight == null) { - rootNode = rootNodeLeft ?: rootNodeRight - } else { - val mostLeftChild: AVLTreeNode = minValueNode(rootNodeRight) - rootNode = mostLeftChild - rootNode.right = removeRecursive(rootNode.right, rootNode) + if (rootNode != null) { + rootNode.right = newNode?.let { removeRecursive(rootNode.right, it) } + } + } } - if (rootNode == null) { - return root - } + if (rootNode == null) return rootNode return rebalanced(rootNode, node) } From 3e34279a12c9d933c0b30f8d22ee00bf1e4da288 Mon Sep 17 00:00:00 2001 From: Demon32123 Date: Wed, 10 Apr 2024 01:43:31 +0300 Subject: [PATCH 126/130] fix(AVL-T): add new tests in remove test --- lib/src/test/kotlin/tree/AVLTreeTest.kt | 45 +++++++++++++++++++------ 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/lib/src/test/kotlin/tree/AVLTreeTest.kt b/lib/src/test/kotlin/tree/AVLTreeTest.kt index a40a022..ef416b3 100644 --- a/lib/src/test/kotlin/tree/AVLTreeTest.kt +++ b/lib/src/test/kotlin/tree/AVLTreeTest.kt @@ -1,7 +1,6 @@ package tree import org.junit.jupiter.api.Assertions.* -import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import kotlin.random.Random @@ -97,12 +96,34 @@ class AVLTreeTest { @Test fun `base test`() { tree.set(1, 1) - tree.remove(1) - assertEquals(0, tree.size) + tree.set(2, 1) + tree.remove(2) + assertEquals(1, tree.size) + assertEquals(listOf(1), tree.getKeys()) } @Test - fun `many test`(){ + fun `remove root`(){ + tree.set(1, 1) + tree.set(2, 1) + tree.set(3, 1) + tree.remove(2) + assertEquals(2, tree.size) + assertEquals(listOf(1, 3), tree.getKeys()) + } + + @Test + fun `remove last node`(){ + tree.set(1, 1) + tree.set(2, 1) + tree.set(3, 1) + tree.remove(3) + assertEquals(2, tree.size) + assertEquals(listOf(1, 2), tree.getKeys()) + } + + @Test + fun `many node`() { val entities = arrayOf( Pair(35, 1), Pair(21, 1), @@ -117,13 +138,17 @@ class AVLTreeTest { ) tree.set(entities) - tree.remove(arrayOf( - 35, 12, 523 - )) + tree.remove( + arrayOf( + 35, 12, 523 + ) + ) assertEquals(7, tree.size) - assertEquals(listOf( - 21, 25, 62, 121, 122, 362, 621 - ), tree.getKeys()) + assertEquals( + listOf( + 21, 25, 62, 121, 122, 362, 621 + ), tree.getKeys() + ) } } } \ No newline at end of file From 8ab036c8271c9d2cc56861fcc7d1dfc6e8485aa8 Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sat, 13 Apr 2024 22:13:24 +0300 Subject: [PATCH 127/130] refactor(STree): change if to when in method searchNode --- lib/src/main/kotlin/tree/SearchTree.kt | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/src/main/kotlin/tree/SearchTree.kt b/lib/src/main/kotlin/tree/SearchTree.kt index ec4b216..f43fbc9 100644 --- a/lib/src/main/kotlin/tree/SearchTree.kt +++ b/lib/src/main/kotlin/tree/SearchTree.kt @@ -28,12 +28,10 @@ abstract class SearchTree, V, Node : BinaryTreeNode node.key) { - node = node.right - } else { - return node + when { + key < node.key -> node = node.left + key > node.key -> node = node.right + else -> return node } } From 30f48a3e4c056cd2a750424a4ccb51f96f0a584c Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sat, 13 Apr 2024 22:20:25 +0300 Subject: [PATCH 128/130] refactor(BST): change if to when in methods insertNode, identifyChild and make method createNode more prettier --- lib/src/main/kotlin/tree/BSTree.kt | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/lib/src/main/kotlin/tree/BSTree.kt b/lib/src/main/kotlin/tree/BSTree.kt index 4cf0c50..f42d707 100644 --- a/lib/src/main/kotlin/tree/BSTree.kt +++ b/lib/src/main/kotlin/tree/BSTree.kt @@ -21,12 +21,10 @@ class BSTree, V> : SearchTree> { } } - if (parentNode == null) { - root = node - } else if (node.key < parentNode.key) { - parentNode.left = node - } else { - parentNode.right = node + when { + parentNode == null -> root = node + node.key < parentNode.key -> parentNode.left = node + else -> parentNode.right = node } } @@ -52,12 +50,10 @@ class BSTree, V> : SearchTree> { } private fun identifyChild(parentNode: BSTreeNode?, node: BSTreeNode, value: BSTreeNode?) { - if (parentNode == null) { - root = value - } else if (parentNode.left == node) { - parentNode.left = value - } else { - parentNode.right = value + when { + parentNode == null -> root = value + parentNode.left == node -> parentNode.left = value + else -> parentNode.right = value } } @@ -85,7 +81,5 @@ class BSTree, V> : SearchTree> { identifyChild(parentNode, node, successor) } - override fun createNode(key: K, value: V): BSTreeNode { - return BSTreeNode(key, value) - } + override fun createNode(key: K, value: V): BSTreeNode = BSTreeNode(key, value) } \ No newline at end of file From c6be325027d869cabeeb7024812d04f79498e13f Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sat, 13 Apr 2024 22:25:56 +0300 Subject: [PATCH 129/130] test(STree): make set test in empty tree prettier --- lib/src/test/kotlin/tree/SearchTreeTest.kt | 80 ++++++++++++---------- 1 file changed, 42 insertions(+), 38 deletions(-) diff --git a/lib/src/test/kotlin/tree/SearchTreeTest.kt b/lib/src/test/kotlin/tree/SearchTreeTest.kt index 8ef5af2..03e3311 100644 --- a/lib/src/test/kotlin/tree/SearchTreeTest.kt +++ b/lib/src/test/kotlin/tree/SearchTreeTest.kt @@ -12,15 +12,12 @@ class SearchTreeTest { @BeforeEach fun setup() { - bst = BSTree() - bst.set(5, "A") - bst.set(8, "A") - bst.set(6, "A") - bst.set(1, "A") - bst.set(2, "A") - bst.set(4, "A") - bst.set(3, "A") - bst.set(10, "A") + bst = BSTree( + arrayOf( + Pair(5, "A"), Pair(8, "A"), Pair(6, "A"), Pair(1, "A"), + Pair(2, "A"), Pair(4, "A"), Pair(3, "A"), Pair(10, "A") + ) + ) } @Nested @@ -197,37 +194,44 @@ class SearchTreeTest { ) } - @Test - fun `set nodes in empty tree`() { - assertEquals(null, bstWithoutNodes.set(19, "B")) - assertEquals(1, bstWithoutNodes.size) - assertEquals(listOf(Pair(19, "B")), bstWithoutNodes.getEntities()) - - bstWithoutNodes.clear() - - assertEquals(null, bstWithoutNodes.setIfEmpty(19, "B")) - assertEquals(1, bstWithoutNodes.size) - assertEquals(listOf(Pair(19, "B")), bstWithoutNodes.getEntities()) - - bstWithoutNodes.clear() - - assertEquals( - listOf(null, null, null), - bstWithoutNodes.set(arrayOf(Pair(12, "B"), Pair(0, "B"), Pair(7, "B"))) - ) - assertEquals(7, bstWithoutNodes.recentlyKey) - assertEquals(3, bstWithoutNodes.size) - assertEquals(listOf(Pair(0, "B"), Pair(7, "B"), Pair(12, "B")), bstWithoutNodes.getEntities()) + @Nested + inner class `set nodes in empty tree` { + @Test + fun `set new node`() { + assertEquals(null, bstWithoutNodes.set(19, "B")) + assertEquals(1, bstWithoutNodes.size) + assertEquals(listOf(Pair(19, "B")), bstWithoutNodes.getEntities()) + } + + @Test + fun `setIfEmpty new node`() { + assertEquals(null, bstWithoutNodes.setIfEmpty(19, "B")) + assertEquals(1, bstWithoutNodes.size) + assertEquals(listOf(Pair(19, "B")), bstWithoutNodes.getEntities()) + } + + @Test + fun `set new nodes`() { + assertEquals( + listOf(null, null, null), + bstWithoutNodes.set(arrayOf(Pair(12, "B"), Pair(0, "B"), Pair(7, "B"))) + ) + assertEquals(7, bstWithoutNodes.recentlyKey) + assertEquals(3, bstWithoutNodes.size) + assertEquals(listOf(Pair(0, "B"), Pair(7, "B"), Pair(12, "B")), bstWithoutNodes.getEntities()) - bstWithoutNodes.clear() + } - assertEquals( - listOf(null, null, null), - bstWithoutNodes.setIfEmpty(arrayOf(Pair(12, "B"), Pair(0, "B"), Pair(7, "B"))) - ) - assertEquals(7, bstWithoutNodes.recentlyKey) - assertEquals(3, bstWithoutNodes.size) - assertEquals(listOf(Pair(0, "B"), Pair(7, "B"), Pair(12, "B")), bstWithoutNodes.getEntities()) + @Test + fun `setIfEmpty new nodes`() { + assertEquals( + listOf(null, null, null), + bstWithoutNodes.setIfEmpty(arrayOf(Pair(12, "B"), Pair(0, "B"), Pair(7, "B"))) + ) + assertEquals(7, bstWithoutNodes.recentlyKey) + assertEquals(3, bstWithoutNodes.size) + assertEquals(listOf(Pair(0, "B"), Pair(7, "B"), Pair(12, "B")), bstWithoutNodes.getEntities()) + } } } From 810d36b582b9bca32f74dca732945ba289145f3f Mon Sep 17 00:00:00 2001 From: KuzminaA Date: Sat, 13 Apr 2024 22:32:06 +0300 Subject: [PATCH 130/130] test(BST): use simplier way to create a tree to test --- lib/src/test/kotlin/tree/BSTreeTest.kt | 127 ++++++++++--------------- 1 file changed, 51 insertions(+), 76 deletions(-) diff --git a/lib/src/test/kotlin/tree/BSTreeTest.kt b/lib/src/test/kotlin/tree/BSTreeTest.kt index 87bd427..02f21e9 100644 --- a/lib/src/test/kotlin/tree/BSTreeTest.kt +++ b/lib/src/test/kotlin/tree/BSTreeTest.kt @@ -25,13 +25,7 @@ class BSTreeTest { @Test fun `tree with some args`() { - val bst: BSTree = BSTree( - arrayOf( - Pair(1, "A"), - Pair(2, "B"), - Pair(3, "C"), - ) - ) + val bst: BSTree = BSTree(arrayOf(Pair(1, "A"), Pair(2, "B"), Pair(3, "C"))) assertEquals(3, bst.size) assertEquals(listOf(Pair(1, "A"), Pair(2, "B"), Pair(3, "C")), bst.getEntities()) @@ -43,13 +37,12 @@ class BSTreeTest { inner class `Insert tests` { @BeforeEach fun setup() { - bst = BSTree() - bst.set(2, "B") - bst.set(3, "C") - bst.set(4, "D") - bst.set(6, "F") - bst.set(7, "G") - bst.set(8, "H") + bst = BSTree( + arrayOf( + Pair(2, "B"), Pair(3, "C"), Pair(4, "D"), + Pair(6, "F"), Pair(7, "G"), Pair(8, "H") + ) + ) } @Test @@ -70,8 +63,8 @@ class BSTreeTest { assertEquals(7, bst.size) assertEquals( listOf( - Pair(2, "B"), Pair(3, "C"), Pair(4, "D"), - Pair(6, "F"), Pair(7, "G"), Pair(8, "H"), Pair(9, "I") + Pair(2, "B"), Pair(3, "C"), Pair(4, "D"), Pair(6, "F"), + Pair(7, "G"), Pair(8, "H"), Pair(9, "I") ), bst.getEntities() ) } @@ -113,8 +106,8 @@ class BSTreeTest { @Test fun `remove root without children`() { - bst = BSTree() - bst.set(2, "B") + bst = BSTree(2, "B") + assertEquals("B", bst.remove(2)) assertEquals(0, bst.size) } @@ -122,13 +115,13 @@ class BSTreeTest { @Test fun `remove root with two children`() { // successor root is root.right - bst = BSTree() - bst.set(2, "B") - bst.set(3, "C") - bst.set(1, "A") - bst.set(0, "Z") - bst.set(5, "E") - bst.set(4, "D") + bst = BSTree( + arrayOf( + Pair(2, "B"), Pair(3, "C"), Pair(1, "A"), + Pair(0, "Z"), Pair(5, "E"), Pair(4, "D") + ) + ) + assertEquals("B", bst.remove(2)) assertEquals(5, bst.size) assertEquals(listOf(0, 1, 3, 4, 5), bst.getKeys()) @@ -137,13 +130,13 @@ class BSTreeTest { @Test fun `remove root with two children1`() { // successor root is list - bst = BSTree() - bst.set(2, "B") - bst.set(1, "A") - bst.set(0, "Z") - bst.set(6, "F") - bst.set(4, "D") - bst.set(5, "E") + bst = BSTree( + arrayOf( + Pair(2, "B"), Pair(1, "A"), Pair(0, "Z"), + Pair(6, "F"), Pair(4, "D"), Pair(5, "E") + ) + ) + assertEquals("B", bst.remove(2)) assertEquals(5, bst.size) assertEquals(listOf(0, 1, 4, 5, 6), bst.getKeys()) @@ -152,14 +145,13 @@ class BSTreeTest { @Test fun `remove root with two children2`() { // successor root has one child - bst = BSTree() - bst.set(2, "B") - bst.set(1, "A") - bst.set(0, "Z") - bst.set(6, "F") - bst.set(7, "G") - bst.set(4, "D") - bst.set(5, "E") + bst = BSTree( + arrayOf( + Pair(2, "B"), Pair(1, "A"), Pair(0, "Z"), Pair(6, "F"), + Pair(7, "G"), Pair(4, "D"), Pair(5, "E") + ) + ) + assertEquals("B", bst.remove(2)) assertEquals(6, bst.size) assertEquals(listOf(0, 1, 4, 5, 6, 7), bst.getKeys()) @@ -168,15 +160,13 @@ class BSTreeTest { @Test fun `remove root with two children3`() { // successor root has a subtree - bst = BSTree() - bst.set(2, "B") - bst.set(1, "A") - bst.set(0, "Z") - bst.set(8, "K") - bst.set(3, "C") - bst.set(5, "E") - bst.set(4, "D") - bst.set(6, "F") + bst = BSTree( + arrayOf( + Pair(2, "B"), Pair(1, "A"), Pair(0, "Z"), Pair(8, "K"), + Pair(3, "C"), Pair(5, "E"), Pair(4, "D"), Pair(6, "F") + ) + ) + assertEquals("B", bst.remove(2)) assertEquals(7, bst.size) assertEquals(listOf(0, 1, 3, 4, 5, 6, 8), bst.getKeys()) @@ -184,11 +174,8 @@ class BSTreeTest { @Test fun `remove root without left child`() { - bst = BSTree() - bst.set(2, "B") - bst.set(3, "C") - bst.set(5, "E") - bst.set(4, "D") + bst = BSTree(arrayOf(Pair(2, "B"), Pair(3, "C"), Pair(5, "E"), Pair(4, "D"))) + assertEquals("B", bst.remove(2)) assertEquals(3, bst.size) assertEquals(listOf(3, 4, 5), bst.getKeys()) @@ -196,11 +183,8 @@ class BSTreeTest { @Test fun `remove root without right child`() { - bst = BSTree() - bst.set(6, "F") - bst.set(3, "C") - bst.set(5, "E") - bst.set(4, "D") + bst = BSTree(arrayOf(Pair(6, "F"), Pair(3, "C"), Pair(5, "E"), Pair(4, "D"))) + assertEquals("F", bst.remove(6)) assertEquals(3, bst.size) assertEquals(listOf(3, 4, 5), bst.getKeys()) @@ -208,10 +192,8 @@ class BSTreeTest { @Test fun `remove key without left child`() { - bst = BSTree() - bst.set(1, "A") - bst.set(2, "B") - bst.set(3, "C") + bst = BSTree(arrayOf(Pair(1, "A"), Pair(2, "B"), Pair(3, "C"))) + assertEquals("B", bst.remove(2)) assertEquals(2, bst.size) assertEquals(listOf(Pair(1, "A"), Pair(3, "C")), bst.getEntities()) @@ -219,10 +201,8 @@ class BSTreeTest { @Test fun `remove key without right child`() { - bst = BSTree() - bst.set(3, "C") - bst.set(2, "B") - bst.set(1, "A") + bst = BSTree(arrayOf(Pair(3, "C"), Pair(2, "B"), Pair(1, "A"))) + assertEquals("B", bst.remove(2)) assertEquals(2, bst.size) assertEquals(listOf(Pair(1, "A"), Pair(3, "C")), bst.getEntities()) @@ -230,11 +210,8 @@ class BSTreeTest { @Test fun `remove key with two children`() { - bst = BSTree() - bst.set(1, "A") - bst.set(3, "C") - bst.set(2, "B") - bst.set(4, "D") + bst = BSTree(arrayOf(Pair(1, "A"), Pair(3, "C"), Pair(2, "B"), Pair(4, "D"))) + assertEquals("C", bst.remove(3)) assertEquals(3, bst.size) assertEquals(listOf(Pair(1, "A"), Pair(2, "B"), Pair(4, "D")), bst.getEntities()) @@ -242,10 +219,8 @@ class BSTreeTest { @Test fun `remove key that is not in the tree`() { - bst = BSTree() - bst.set(2, "B") - bst.set(3, "C") - bst.set(0, "Z") + bst = BSTree(arrayOf(Pair(2, "B"), Pair(3, "C"), Pair(0, "Z"))) + assertEquals(null, bst.remove(1)) assertEquals(3, bst.size) assertEquals(listOf(Pair(0, "Z"), Pair(2, "B"), Pair(3, "C")), bst.getEntities())