From 38ae41ee1a2ca12eea85c30fbdac1804c191fe7c Mon Sep 17 00:00:00 2001 From: "github-classroom[bot]" <66690702+github-classroom[bot]@users.noreply.github.com> Date: Wed, 13 Mar 2024 16:45:26 +0000 Subject: [PATCH 001/108] Setting up GitHub Classroom Feedback From a3c9bb9c9864c654a4085a3fc591c0ec434af820 Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Fri, 15 Mar 2024 20:33:14 +0300 Subject: [PATCH 002/108] Gradle Init --- .gitattributes | 9 + .github/workflows/CI_Test.yml | 30 +++ .github/workflows/MegaLinter.yml | 91 +++++++ .gitignore | 6 + README.md | 4 + 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 + 14 files changed, 588 insertions(+) create mode 100644 .gitattributes create mode 100644 .github/workflows/CI_Test.yml create mode 100644 .github/workflows/MegaLinter.yml create mode 100644 .gitignore create mode 100644 README.md 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/.github/workflows/CI_Test.yml b/.github/workflows/CI_Test.yml new file mode 100644 index 0000000..a38f7b4 --- /dev/null +++ b/.github/workflows/CI_Test.yml @@ -0,0 +1,30 @@ +name: CI_Test + +on: + push: + pull_request: + branches: + - main + +jobs: + CI_Test: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + + - name: Grant execute permission for gradlew + run: chmod +x ./gradlew + + - name: Check code cleanliness + run: ./gradlew clean build + continue-on-error: false + + - name: Run tests + run: ./gradlew test diff --git a/.github/workflows/MegaLinter.yml b/.github/workflows/MegaLinter.yml new file mode 100644 index 0000000..3767aa7 --- /dev/null +++ b/.github/workflows/MegaLinter.yml @@ -0,0 +1,91 @@ +--- +# MegaLinter GitHub Action configuration file +# More info at https://megalinter.io +name: MegaLinter + +on: + # Trigger mega-linter at every push. Action will also be visible from Pull Requests to main + push: # Comment this line to trigger action only on pull-requests (not recommended if you don't pay for GH Actions) + pull_request: + branches: [master, main] + +env: # Comment env block if you don't want to apply fixes + # Apply linter fixes configuration + APPLY_FIXES: all # When active, APPLY_FIXES must also be defined as environment variable (in github/workflows/mega-linter.yml or other CI tool) + APPLY_FIXES_EVENT: pull_request # Decide which event triggers application of fixes in a commit or a PR (pull_request, push, all) + APPLY_FIXES_MODE: commit # If APPLY_FIXES is used, defines if the fixes are directly committed (commit) or posted in a PR (pull_request) + ENABLE_LINTERS: KOTLIN_KTLINT +concurrency: + group: ${{ github.ref }}-${{ github.workflow }} + cancel-in-progress: true + +jobs: + megalinter: + name: MegaLinter + runs-on: ubuntu-latest + permissions: + # Give the default GITHUB_TOKEN write permission to commit and push, comment issues & post new PR + # Remove the ones you do not need + contents: write + issues: write + pull-requests: write + steps: + # Git Checkout + - name: Checkout Code + uses: actions/checkout@v3 + with: + token: ${{ secrets.PAT || secrets.GITHUB_TOKEN }} + fetch-depth: 0 # If you use VALIDATE_ALL_CODEBASE = true, you can remove this line to improve performances + + # MegaLinter + - name: MegaLinter + id: ml + # You can override MegaLinter flavor used to have faster performances + # More info at https://megalinter.io/flavors/ + uses: oxsecurity/megalinter@v7 + env: + # All available variables are described in documentation + # https://megalinter.io/configuration/ + VALIDATE_ALL_CODEBASE: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} # Validates all source when push on main, else just the git diff with main. Override with true if you always want to lint all sources + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # ADD YOUR CUSTOM ENV VARIABLES HERE OR DEFINE THEM IN A FILE .mega-linter.yml AT THE ROOT OF YOUR REPOSITORY + # DISABLE: COPYPASTE,SPELL # Uncomment to disable copy-paste and spell checks + + # Upload MegaLinter artifacts + - name: Archive production artifacts + if: success() || failure() + uses: actions/upload-artifact@v4 + with: + name: MegaLinter reports + path: | + megalinter-reports + mega-linter.log + + # Create pull request if applicable (for now works only on PR from same repository, not from forks) + - name: Create Pull Request with applied fixes + id: cpr + if: steps.ml.outputs.has_updated_sources == 1 && (env.APPLY_FIXES_EVENT == 'all' || env.APPLY_FIXES_EVENT == github.event_name) && env.APPLY_FIXES_MODE == 'pull_request' && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository) && !contains(github.event.head_commit.message, 'skip fix') + uses: peter-evans/create-pull-request@v6 + with: + token: ${{ secrets.PAT || secrets.GITHUB_TOKEN }} + commit-message: "[MegaLinter] Apply linters automatic fixes" + title: "[MegaLinter] Apply linters automatic fixes" + labels: bot + - name: Create PR output + if: steps.ml.outputs.has_updated_sources == 1 && (env.APPLY_FIXES_EVENT == 'all' || env.APPLY_FIXES_EVENT == github.event_name) && env.APPLY_FIXES_MODE == 'pull_request' && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository) && !contains(github.event.head_commit.message, 'skip fix') + run: | + echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}" + echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}" + + # Push new commit if applicable (for now works only on PR from same repository, not from forks) + - name: Prepare commit + if: steps.ml.outputs.has_updated_sources == 1 && (env.APPLY_FIXES_EVENT == 'all' || env.APPLY_FIXES_EVENT == github.event_name) && env.APPLY_FIXES_MODE == 'commit' && github.ref != 'refs/heads/main' && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository) && !contains(github.event.head_commit.message, 'skip fix') + run: sudo chown -Rc $UID .git/ + - name: Commit and push applied linter fixes + if: steps.ml.outputs.has_updated_sources == 1 && (env.APPLY_FIXES_EVENT == 'all' || env.APPLY_FIXES_EVENT == github.event_name) && env.APPLY_FIXES_MODE == 'commit' && github.ref != 'refs/heads/main' && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository) && !contains(github.event.head_commit.message, 'skip fix') + uses: stefanzweifel/git-auto-commit-action@v4 + with: + branch: ${{ github.event.pull_request.head.ref || github.head_ref || github.ref }} + commit_message: "[MegaLinter] Apply linters fixes" + commit_user_name: megalinter-bot + commit_user_email: nicolas.vuillamy@ox.security \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..889ee4e --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore Gradle build output directory +build +/.idea/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..5d2069d --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +# Binary Trees Project + +![MegaLinter](https://github.com/spbu-coding-2023/trees-8/workflows/MegaLinter.yml/badge.svg) +![CI Test](https://github.com/spbu-coding-2023/trees-8/actions/workflows/CI_Test.yml/badge.svg) \ No newline at end of file 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..f6cad6d --- /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(17) + } +} + +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..7ba494f --- /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-8" +include("lib") From 7728300f68ab3c15bc0b776b0d0dc1f9eb282497 Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Fri, 15 Mar 2024 20:43:15 +0300 Subject: [PATCH 003/108] Add Megalinter passing --- .github/workflows/CI_Test.yml | 1 + README.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/CI_Test.yml b/.github/workflows/CI_Test.yml index a38f7b4..f2c815b 100644 --- a/.github/workflows/CI_Test.yml +++ b/.github/workflows/CI_Test.yml @@ -17,6 +17,7 @@ jobs: - name: Set up JDK 17 uses: actions/setup-java@v4 with: + distribution: "oracle" java-version: '17' - name: Grant execute permission for gradlew diff --git a/README.md b/README.md index 5d2069d..6158784 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ # Binary Trees Project -![MegaLinter](https://github.com/spbu-coding-2023/trees-8/workflows/MegaLinter.yml/badge.svg) +![MegaLinter](https://github.com/spbu-coding-2023/trees-8/workflows/MegaLinter/badge.svg) ![CI Test](https://github.com/spbu-coding-2023/trees-8/actions/workflows/CI_Test.yml/badge.svg) \ No newline at end of file From 3d196a57f2c747dbd50deefe54f30b52dfbf040b Mon Sep 17 00:00:00 2001 From: Azamat Ishbaev <143432879+odiumuniverse@users.noreply.github.com> Date: Fri, 15 Mar 2024 22:36:42 +0300 Subject: [PATCH 004/108] Create LICENSE --- LICENSE | 674 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 674 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. From c83ea4ac2c4c0e85a6f351a76b679d844b16196a Mon Sep 17 00:00:00 2001 From: Azamat Ishbaev <143432879+odiumuniverse@users.noreply.github.com> Date: Fri, 15 Mar 2024 22:36:42 +0300 Subject: [PATCH 005/108] Create LICENSE Update README.md Update README.md --- LICENSE | 674 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 8 +- 2 files changed, 679 insertions(+), 3 deletions(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md index 6158784..c805690 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ -# Binary Trees Project - ![MegaLinter](https://github.com/spbu-coding-2023/trees-8/workflows/MegaLinter/badge.svg) -![CI Test](https://github.com/spbu-coding-2023/trees-8/actions/workflows/CI_Test.yml/badge.svg) \ No newline at end of file +![CI Test](https://github.com/spbu-coding-2023/trees-8/actions/workflows/CI_Test.yml/badge.svg) +[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) +[![CodeFactor](https://www.codefactor.io/repository/github/spbu-coding-2023/trees-8/badge)](https://www.codefactor.io/repository/github/spbu-coding-2023/trees-8) + +# Binary Trees Project From 16da8dc35465a55337f647fe51bf80441fd6c47e Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Sat, 16 Mar 2024 09:38:54 +0300 Subject: [PATCH 006/108] Add coverage CI test --- .github/workflows/coverage.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/workflows/coverage.yml diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 0000000..1225417 --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,21 @@ +name: Test coverage + +on: + pull_request: + +jobs: + + collect_coverage: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: stevenleadbeater/kotlin-kover-action@v1.0.3 + id: kover-tests + with: + coverage-threshold: 80 + repo-token: ${{ secrets.GITHUB_TOKEN }} + proxy-url: https://add-pr-comment-proxy-94idvmwyie-uc.a.run.app + - name: Check coverage + if: ${{(steps.kover-tests.outputs.line-coverage) < 80}} + shell: bash + run: exit "Line coverage expected to be > 80 but was ${{steps.kover-tests.outputs.line-coverage}}" \ No newline at end of file From ddb20f4abbc6d412cf5abd9108735337f6bd3277 Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Tue, 19 Mar 2024 16:30:24 +0300 Subject: [PATCH 007/108] Create README.md --- README.md | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c805690..0adbd53 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,44 @@ ![MegaLinter](https://github.com/spbu-coding-2023/trees-8/workflows/MegaLinter/badge.svg) -![CI Test](https://github.com/spbu-coding-2023/trees-8/actions/workflows/CI_Test.yml/badge.svg) +![CI_Test](https://github.com/spbu-coding-2023/trees-8/actions/workflows/CI_Test.yml/badge.svg) [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) [![CodeFactor](https://www.codefactor.io/repository/github/spbu-coding-2023/trees-8/badge)](https://www.codefactor.io/repository/github/spbu-coding-2023/trees-8) # Binary Trees Project + +Team #8's project on binary trees. + +## About + +Three trees are implemented in this library: [R&B](https://en.wikipedia.org/wiki/Red–black_tree), [AVL](https://en.wikipedia.org/wiki/AVL_tree) and [Binary Search Tree](https://en.wikipedia.org/wiki/Binary_search_tree). + +## Authors + +- [Aleksey Dmitrievtsev](https://github.com/admitrievtsev) - Red&Black Tree +- [Gleb Nasretdinov](https://github.com/Ycyken) - AVL Tree +- [Azamat Ishbaev](https://github.com/odiumuniverse) - Binary Search Tree + +## Technologies + +- Kotlin 1.9.22 +- JDK 17 +- [Gradle 8.6](https://gradle.org) + +## Library information + +Three trees are implemented, choose which one you want. +Standard methods are implemented in each tree: + ++ `insert()` - Inserting a tree node by key and value ++ `remove()` - Deleting a tree node by key ++ `find()` - Searching by key ++ `traverse()` - Traversing the tree depending on the selected path search + +AVL and R&B trees are self-balancing + +### Suggestions and wishes + +Suggestions can be made in code review or [Issues](https://github.com/spbu-coding-2023/trees-8/issues) on GitHub + +### Licence + +The library is distributed under the [GNU GPLv3 licence](https://www.gnu.org/licenses/gpl-3.0.html) From e42eebbf2f4916e7d9eafc5045524a074fca84a7 Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Sat, 16 Mar 2024 09:40:36 +0300 Subject: [PATCH 008/108] Set project structure, created templates -created files for required classes -created BSTree and Vertex templates -created vertices implementations for 3 all three types of trees --- .../kotlin/bstrees/implementations/AVLTree.kt | 4 + .../kotlin/bstrees/implementations/RBTree.kt | 4 + .../bstrees/implementations/SimpleBSTree.kt | 14 +++ .../bstrees/implementations/Vertices.kt | 17 ++++ .../bstrees/templates/BSTreeTemplate.kt | 93 +++++++++++++++++++ .../templates/BalanceBSTreeTemplate.kt | 2 + .../bstrees/templates/VertexTemplate.kt | 7 ++ lib/src/main/kotlin/org/example/Library.kt | 10 -- 8 files changed, 141 insertions(+), 10 deletions(-) create mode 100644 lib/src/main/kotlin/bstrees/implementations/AVLTree.kt create mode 100644 lib/src/main/kotlin/bstrees/implementations/RBTree.kt create mode 100644 lib/src/main/kotlin/bstrees/implementations/SimpleBSTree.kt create mode 100644 lib/src/main/kotlin/bstrees/implementations/Vertices.kt create mode 100644 lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt create mode 100644 lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt create mode 100644 lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt delete mode 100644 lib/src/main/kotlin/org/example/Library.kt diff --git a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt new file mode 100644 index 0000000..3f7349a --- /dev/null +++ b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt @@ -0,0 +1,4 @@ +package bstrees.implementations + +class AVLTree { +} \ No newline at end of file diff --git a/lib/src/main/kotlin/bstrees/implementations/RBTree.kt b/lib/src/main/kotlin/bstrees/implementations/RBTree.kt new file mode 100644 index 0000000..65a5cc9 --- /dev/null +++ b/lib/src/main/kotlin/bstrees/implementations/RBTree.kt @@ -0,0 +1,4 @@ +package bstrees.implementations + +class RBTree { +} \ No newline at end of file diff --git a/lib/src/main/kotlin/bstrees/implementations/SimpleBSTree.kt b/lib/src/main/kotlin/bstrees/implementations/SimpleBSTree.kt new file mode 100644 index 0000000..aba564f --- /dev/null +++ b/lib/src/main/kotlin/bstrees/implementations/SimpleBSTree.kt @@ -0,0 +1,14 @@ +package bstrees.implementations + +import bstrees.templates.BSTreeTemplate + +class SimpleBSTree, V> : BSTreeTemplate>() { + override fun remove(key: K): V? { + // remove implementation + return null + } + + override operator fun set(key: K, value: V) { + // set implemenation + } +} \ No newline at end of file diff --git a/lib/src/main/kotlin/bstrees/implementations/Vertices.kt b/lib/src/main/kotlin/bstrees/implementations/Vertices.kt new file mode 100644 index 0000000..d71538b --- /dev/null +++ b/lib/src/main/kotlin/bstrees/implementations/Vertices.kt @@ -0,0 +1,17 @@ +package bstrees.implementations + +import bstrees.templates.VertexTemplate + +class SimpleVertex,V>(key: K,value: V): VertexTemplate>(key,value) + +class AVLVertex,V>(key: K,value: V): VertexTemplate>(key,value){ + var height: Int = 0 +} +class RBVertex,V>(key:K,value:V): VertexTemplate>(key,value){ + var color : Color = Color.BLACK + + enum class Color{ + BLACK, + RED + } +} \ No newline at end of file diff --git a/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt b/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt new file mode 100644 index 0000000..9b006da --- /dev/null +++ b/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt @@ -0,0 +1,93 @@ +package bstrees.templates + +abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate> { + var root: Vertex_t? = null + var size: Int = 0 + private set(value) { + if (value >= 0) { + field = value + } else throw IllegalArgumentException("Tree size cannot be a negative number") + } + + /** + * Returns the value corresponding to the given key, or null if such a key is not present in the tree. + */ + operator fun get(key: K): V? { + var cur = root + while (cur != null) { + val result = cur.key.compareTo(key) + when { + result < 0 -> cur = cur.left + result > 0 -> cur = cur.right + result == 0 -> return cur.value + } + } + return null + } + + /** + * Returns the value corresponding to the given key, or defaultValue if such a key is not present in the tree. + */ + public fun getOrDefault(key: K, defaultValue: Any): Any { + return get(key) ?: defaultValue + } + + /** + * Associates the specified value with the specified key in the tree. + */ + public abstract operator fun set(key: K, value: V) + + /** + * Removes the entry for the specified key only if it is mapped with some value. + * Returns: removed value if key was mapped with it, otherwise null + */ + public abstract fun remove(key: K): V? + + public fun clear() { + size = 0 + root = null + } + + enum class Traversal { + INORDER, + PREORDER, + POSTORDER + } + + /** + * Returns a [MutableList] of all values in this tree. + */ + fun values(order: Traversal): List { + var result: MutableList = mutableListOf() + traverse(order, root, result) + return result + } + + + private fun traverse(order: Traversal, vertex: Vertex_t?, result: MutableList) { + if (vertex == null) { + return + } + when (order) { + Traversal.INORDER -> { + traverse(order, vertex.left, result) + result.add(vertex.value) + traverse(order, vertex.right, result) + } + + Traversal.PREORDER -> { + result.add(vertex.value) + traverse(order, vertex.left, result) + traverse(order, vertex.right, result) + } + + Traversal.POSTORDER -> { + traverse(order, vertex.left, result) + traverse(order, vertex.right, result) + result.add(vertex.value) + } + } + return + } + +} \ No newline at end of file diff --git a/lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt b/lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt new file mode 100644 index 0000000..6e657a8 --- /dev/null +++ b/lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt @@ -0,0 +1,2 @@ +package bstrees.templates + diff --git a/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt b/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt new file mode 100644 index 0000000..f1dda4c --- /dev/null +++ b/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt @@ -0,0 +1,7 @@ +package bstrees.templates + +abstract class VertexTemplate,V,Vertex_t: VertexTemplate>(val key: K,var value: V) { + var parent: Vertex_t? = null + var left: Vertex_t? = null + var right: Vertex_t? = null +} \ 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 - } -} From 0ac14b83e426c375451913e067912a97c6e125c7 Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Sat, 16 Mar 2024 10:00:25 +0300 Subject: [PATCH 009/108] Change: run test after false clean build --- .github/workflows/CI_Test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI_Test.yml b/.github/workflows/CI_Test.yml index f2c815b..f643467 100644 --- a/.github/workflows/CI_Test.yml +++ b/.github/workflows/CI_Test.yml @@ -25,7 +25,7 @@ jobs: - name: Check code cleanliness run: ./gradlew clean build - continue-on-error: false + continue-on-error: true - name: Run tests run: ./gradlew test From 1b300c6b3214fa2bdff1afcc18a57cd00339f7b4 Mon Sep 17 00:00:00 2001 From: Azamat Ishbaev <143432879+odiumuniverse@users.noreply.github.com> Date: Sat, 16 Mar 2024 10:30:10 +0300 Subject: [PATCH 010/108] Update README.md Add information --- README.md | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6158784..2d4db15 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,44 @@ +![MegaLinter](https://github.com/spbu-coding-2023/trees-8/workflows/MegaLinter/badge.svg) +![CITest](https://github.com/spbu-coding-2023/trees-8/actions/workflows/CI_Test.yml/badge.svg) +[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) +[![CodeFactor](https://www.codefactor.io/repository/github/spbu-coding-2023/trees-8/badge)](https://www.codefactor.io/repository/github/spbu-coding-2023/trees-8) + # Binary Trees Project -![MegaLinter](https://github.com/spbu-coding-2023/trees-8/workflows/MegaLinter/badge.svg) -![CI Test](https://github.com/spbu-coding-2023/trees-8/actions/workflows/CI_Test.yml/badge.svg) \ No newline at end of file +Team #8's project on binary trees. + +## About + +Three trees are implemented in this library: [R&B](https://en.wikipedia.org/wiki/Red–black_tree), [AVL](https://en.wikipedia.org/wiki/AVL_tree) and [Binary Search Tree](https://en.wikipedia.org/wiki/Binary_search_tree). + +## Authors + +- [Aleksey Dmitrievtsev](https://github.com/admitrievtsev) - Red&Black Tree +- [Gleb Nasretdinov](https://github.com/Ycyken) - AVL Tree +- [Azamat Ishbaev](https://github.com/odiumuniverse) - Binary Search Tree + +## Technologies + +- Kotlin 1.9.22 +- JDK 17 +- [Gradle 8.6](https://gradle.org) + +## Library information + +Three trees are implemented, choose which one you want. +Standard methods are implemented in each tree: + ++ `insert()` - Inserting a tree node by key and value ++ `remove()` - Deleting a tree node by key ++ `find()` - Searching by key ++ `traverse()` - Traversing the tree depending on the selected path search + +AVL and R&B trees are self-balancing + +### Suggestions and wishes + +Suggestions can be made in code review or [Issues](https://github.com/spbu-coding-2023/trees-8/issues) on GitHub + +### Licence + +The library is distributed under the [GNU GPLv3 licence](https://www.gnu.org/licenses/gpl-3.0.html) From b8d273e70810a9a83deb83a017470eb0654a9f1c Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Wed, 20 Mar 2024 12:55:35 +0300 Subject: [PATCH 011/108] Restructured abstract class BSTreeTemplate: -added min() and max() public methods -replaced traverse() method by iterator() --- .../bstrees/templates/BSTreeTemplate.kt | 95 +++++++++++-------- .../bstrees/templates/VertexTemplate.kt | 10 +- 2 files changed, 66 insertions(+), 39 deletions(-) diff --git a/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt b/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt index 9b006da..a8d5248 100644 --- a/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt +++ b/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt @@ -1,5 +1,7 @@ package bstrees.templates +import java.util.Stack + abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate> { var root: Vertex_t? = null var size: Int = 0 @@ -9,10 +11,15 @@ abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate> { + var cur = root + val stack = Stack() + override fun next(): Pair { + while (hasNext()) { + if (cur != null) { + cur?.let { + stack.push(it) + cur = it.left + } + } else { + val returnVert = stack.pop() + cur = returnVert.right + return returnVert.toPair() + } + } + throw IndexOutOfBoundsException() + } + + override fun hasNext(): Boolean { + return stack.isNotEmpty() or (cur != null) + } } /** - * Returns a [MutableList] of all values in this tree. + * Returns Pair by minimum key in the tree. If tree is empty then returns null */ - fun values(order: Traversal): List { - var result: MutableList = mutableListOf() - traverse(order, root, result) - return result + public fun min(): Pair? { + return minVertex(root)?.toPair() } - - private fun traverse(order: Traversal, vertex: Vertex_t?, result: MutableList) { - if (vertex == null) { - return + protected fun minVertex(vertex: Vertex_t?): Vertex_t? { + var cur = vertex + while (cur?.left != null) { + cur = cur.left } - when (order) { - Traversal.INORDER -> { - traverse(order, vertex.left, result) - result.add(vertex.value) - traverse(order, vertex.right, result) - } + return cur + } - Traversal.PREORDER -> { - result.add(vertex.value) - traverse(order, vertex.left, result) - traverse(order, vertex.right, result) - } + /** + * Returns Pair by maximum key in the tree. If tree is empty then returns null + */ + public fun max(): Pair? { + return maxVert(root)?.toPair() + } - Traversal.POSTORDER -> { - traverse(order, vertex.left, result) - traverse(order, vertex.right, result) - result.add(vertex.value) - } + protected fun maxVert(vertex: Vertex_t?): Vertex_t? { + var cur = vertex + while (cur?.right != null) { + cur = cur.right } - return + return cur + } + + fun clear() { + size = 0 + root = null } } \ No newline at end of file diff --git a/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt b/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt index f1dda4c..6e6c084 100644 --- a/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt +++ b/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt @@ -1,7 +1,15 @@ package bstrees.templates -abstract class VertexTemplate,V,Vertex_t: VertexTemplate>(val key: K,var value: V) { +abstract class VertexTemplate, V, Vertex_t : VertexTemplate>(val key: K, var value: V) { var parent: Vertex_t? = null var left: Vertex_t? = null var right: Vertex_t? = null + + operator fun compareTo(other: VertexTemplate): Int { + return key.compareTo(other.key) + } + + fun toPair(): Pair { + return Pair(key, value) + } } \ No newline at end of file From d3d4fcb367d5253a2c85615932655732e9f35cd3 Mon Sep 17 00:00:00 2001 From: Ycyken <135718038+Ycyken@users.noreply.github.com> Date: Thu, 21 Mar 2024 19:04:10 +0300 Subject: [PATCH 012/108] Update README.md --- README.md | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0adbd53..534bb00 100644 --- a/README.md +++ b/README.md @@ -28,10 +28,22 @@ Three trees are implemented in this library: [R&B](https://en.wikipedia.org/wiki Three trees are implemented, choose which one you want. Standard methods are implemented in each tree: -+ `insert()` - Inserting a tree node by key and value -+ `remove()` - Deleting a tree node by key -+ `find()` - Searching by key -+ `traverse()` - Traversing the tree depending on the selected path search ++ `set(key,value)` - Associates the specified value with the specified key in the tree. ++ `remove(key)` - Removes the specified key and its corresponding value from the tree. ++ `get(key)` - Returns the value corresponding to the given key ++ `iterator()` - Iteration by key-value pairs in order of keys + +There are also many other methods: + ++ `setIfAbsent(key,value)` ++ `getOrDefault(key, defaultValue)` ++ `getOrSet(key,defaultValue)` ++ `min()` ++ `max()` ++ `isEmpty()` ++ `isNotEmpty()` ++ `containsKey(key)` ++ `clear()` AVL and R&B trees are self-balancing From 657277778239548b6a01348c3521b3616e0c72cd Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Thu, 21 Mar 2024 07:29:59 +0300 Subject: [PATCH 013/108] Deleted test example and renamed class SimpleBSTree to SimpleTree --- .../{SimpleBSTree.kt => SimpleTree.kt} | 2 +- .../test/kotlin/org/example/LibraryTest.kt | 14 ---------- lib/src/test/kotlin/treesTests/AVLTreeTest.kt | 27 +++++++++++++++++++ 3 files changed, 28 insertions(+), 15 deletions(-) rename lib/src/main/kotlin/bstrees/implementations/{SimpleBSTree.kt => SimpleTree.kt} (74%) delete mode 100644 lib/src/test/kotlin/org/example/LibraryTest.kt create mode 100644 lib/src/test/kotlin/treesTests/AVLTreeTest.kt diff --git a/lib/src/main/kotlin/bstrees/implementations/SimpleBSTree.kt b/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt similarity index 74% rename from lib/src/main/kotlin/bstrees/implementations/SimpleBSTree.kt rename to lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt index aba564f..494a4eb 100644 --- a/lib/src/main/kotlin/bstrees/implementations/SimpleBSTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt @@ -2,7 +2,7 @@ package bstrees.implementations import bstrees.templates.BSTreeTemplate -class SimpleBSTree, V> : BSTreeTemplate>() { +class SimpleTree, V> : BSTreeTemplate>() { override fun remove(key: K): V? { // remove implementation return null 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'") - } -} diff --git a/lib/src/test/kotlin/treesTests/AVLTreeTest.kt b/lib/src/test/kotlin/treesTests/AVLTreeTest.kt new file mode 100644 index 0000000..a6432c7 --- /dev/null +++ b/lib/src/test/kotlin/treesTests/AVLTreeTest.kt @@ -0,0 +1,27 @@ +/* + * This Kotlin source file was generated by the Gradle 'init' task. + */ +package treesTests + +import bstrees.implementations.AVLTree +import org.junit.jupiter.api.BeforeEach +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +class AVLTreeTest { + private lateinit var avlTree: AVLTree + + @BeforeEach + fun setup() { + avlTree = AVLTree() + } + + /* @Test + fun someAVLTreeMethodTest() { + + val expectedResult = + val actualResult = + assertEquals(expectedResult, actualResult, "Assert text") + }*/ +} From ce5371e1a25e7580855941010b97fbad923e3100 Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Thu, 21 Mar 2024 10:27:44 +0300 Subject: [PATCH 014/108] Added more public methods to BSTreeTemplate and modified documentation --- .../bstrees/implementations/SimpleTree.kt | 3 +- .../bstrees/templates/BSTreeTemplate.kt | 46 ++++++++++++++++--- .../templates/BalanceBSTreeTemplate.kt | 5 ++ 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt b/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt index 494a4eb..8b53a6c 100644 --- a/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt @@ -8,7 +8,8 @@ class SimpleTree, V> : BSTreeTemplate return null } - override operator fun set(key: K, value: V) { + override operator fun set(key: K, value: V): V? { // set implemenation + return null } } \ No newline at end of file diff --git a/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt b/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt index a8d5248..a2411f8 100644 --- a/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt +++ b/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt @@ -12,12 +12,25 @@ abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate> : + BSTreeTemplate() { + +} + From d9601eeab4501eb87690721558a1056403b45e8a Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Thu, 21 Mar 2024 18:45:47 +0300 Subject: [PATCH 015/108] Implemented AVL methods, changed docs comments -implemented set public method, balance and rotates methods (with a lot of bugs yet) --- .../kotlin/bstrees/implementations/AVLTree.kt | 140 +++++++++++++++++- .../bstrees/implementations/Vertices.kt | 13 +- .../bstrees/templates/BSTreeTemplate.kt | 18 ++- .../templates/BalanceBSTreeTemplate.kt | 1 - .../{treesTests => trees}/AVLTreeTest.kt | 0 5 files changed, 156 insertions(+), 16 deletions(-) rename lib/src/test/kotlin/{treesTests => trees}/AVLTreeTest.kt (100%) diff --git a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt index 3f7349a..602e83d 100644 --- a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt @@ -1,4 +1,142 @@ package bstrees.implementations -class AVLTree { +import bstrees.templates.BalanceBSTreeTemplate + +class AVLTree, V> : BalanceBSTreeTemplate>() { + + public override fun set(key: K, value: V): V? { + val (currentVert, returnResult) = setWithoutBalance(key, value) + balance(currentVert) + return returnResult + } + + private fun setWithoutBalance(key: K, value: V): Pair, V?> { + if (root == null) { + val newVertex = AVLVertex(key, value) + root = newVertex + size += 1 + return Pair(newVertex, null) + } + + var cur = root ?: throw IllegalStateException("Case when root is null is processed above") + while (true) { + val result = cur.key.compareTo(key) + if (result < 0) { + if (cur.left == null) { + val newVertex = AVLVertex(key, value) + cur.left = newVertex + newVertex.parent = cur + size += 1 + return Pair(newVertex, null) + } + cur = cur.left ?: throw IllegalStateException("Case when cur.left is null is processed above") + } else if (result > 0) { + if (cur.right == null) { + val newVertex = AVLVertex(key, value) + cur.right = newVertex + newVertex.parent = cur + size += 1 + return Pair(newVertex, null) + } + cur = cur.right ?: throw IllegalStateException("Case when cur.rightt is null is processed above") + } else { + val oldValue = cur.value + cur.value = value + return Pair(cur, oldValue) + } + } + } + + private fun balance(vertex: AVLVertex) { + var cur = vertex + var prevKey = cur.key + while (cur.parent != null) { + cur = cur.parent ?: throw IllegalStateException("Parent can't be null due to while condition") + if (prevKey == cur.left?.key) { + cur.diffHeight += 1 + } else if (prevKey == cur.right?.key) { + cur.diffHeight -= 1 + } + + if (cur.diffHeight == 2) { + if (getDiffHeight(cur.left) >= 0) { + cur = rotateRight(cur) + } else if (getDiffHeight(cur.left) == -1) { + cur.left?.let { + cur = rotateLeft(it) + cur = rotateRight(cur) + } + } + + } else if (cur.diffHeight == -2) { + if (getDiffHeight(cur.right) <= 0) { + cur = rotateLeft(cur) + } else if (getDiffHeight(cur.right) == 1) { + cur.right?.let { + cur = rotateRight(cur) + cur = rotateLeft(cur) + } + } + } + + if (cur.diffHeight == 0) break + } + } + + private fun getDiffHeight(vertex: AVLVertex?): Int { + return vertex?.diffHeight ?: 0 + } + + private fun rotateRight(origin: AVLVertex): AVLVertex { + val left = origin.left + ?: throw IllegalStateException("difference of heights can't be 2 if left Vertex doesn't exist") + + left.parent = origin.parent + if (origin.parent?.left == origin) origin.parent?.left = left + else origin.parent?.right = left + + origin.parent = left + origin.left = left.right + + origin.left?.parent = origin + left.right?.parent = origin + + if (left.diffHeight == 0) { + origin.diffHeight = 1 + left.diffHeight = -1 + } else if (left.diffHeight == 1) { + origin.diffHeight = 0 + left.diffHeight = 0 + } + return left + } + + private fun rotateLeft(origin: AVLVertex): AVLVertex { + val right = origin.right + ?: throw IllegalStateException("difference of heights can't be 2 if left Vertex doesn't exist") + + right.parent = origin.parent + if (origin.parent?.left == origin) origin.parent?.left = right + else origin.parent?.right = right + + origin.parent = right + origin.left = right.right + + origin.left?.parent = origin + right.right?.parent = origin + + if (right.diffHeight == 0) { + origin.diffHeight = -1 + right.diffHeight = 1 + } else if (right.diffHeight == -1) { + origin.diffHeight = 0 + right.diffHeight = 0 + } + return right + } + + public override fun remove(key: K): V? { + + return TODO() + } } \ No newline at end of file diff --git a/lib/src/main/kotlin/bstrees/implementations/Vertices.kt b/lib/src/main/kotlin/bstrees/implementations/Vertices.kt index d71538b..1898778 100644 --- a/lib/src/main/kotlin/bstrees/implementations/Vertices.kt +++ b/lib/src/main/kotlin/bstrees/implementations/Vertices.kt @@ -2,15 +2,16 @@ package bstrees.implementations import bstrees.templates.VertexTemplate -class SimpleVertex,V>(key: K,value: V): VertexTemplate>(key,value) +class SimpleVertex, V>(key: K, value: V) : VertexTemplate>(key, value) -class AVLVertex,V>(key: K,value: V): VertexTemplate>(key,value){ - var height: Int = 0 +class AVLVertex, V>(key: K, value: V) : VertexTemplate>(key, value) { + var diffHeight: Int = 0 } -class RBVertex,V>(key:K,value:V): VertexTemplate>(key,value){ - var color : Color = Color.BLACK - enum class Color{ +class RBVertex, V>(key: K, value: V) : VertexTemplate>(key, value) { + var color: Color = Color.BLACK + + enum class Color { BLACK, RED } diff --git a/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt b/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt index a2411f8..26786a6 100644 --- a/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt +++ b/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt @@ -1,11 +1,12 @@ package bstrees.templates import java.util.Stack +import javax.swing.text.StyledEditorKit.BoldAction abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate> { var root: Vertex_t? = null var size: Int = 0 - private set(value) { + protected set(value) { if (value >= 0) { field = value } else throw IllegalArgumentException("Tree size cannot be a negative number") @@ -20,13 +21,14 @@ abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate> : BSTreeTemplate() { - } diff --git a/lib/src/test/kotlin/treesTests/AVLTreeTest.kt b/lib/src/test/kotlin/trees/AVLTreeTest.kt similarity index 100% rename from lib/src/test/kotlin/treesTests/AVLTreeTest.kt rename to lib/src/test/kotlin/trees/AVLTreeTest.kt From f5166775151cd8e2c74666459964adbbe2ac7aae Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Thu, 21 Mar 2024 18:48:33 +0300 Subject: [PATCH 016/108] Added primitive tests for avl tree --- lib/src/test/kotlin/trees/AVLTreeTest.kt | 63 +++++++++++++++++++----- 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/lib/src/test/kotlin/trees/AVLTreeTest.kt b/lib/src/test/kotlin/trees/AVLTreeTest.kt index a6432c7..6ab8515 100644 --- a/lib/src/test/kotlin/trees/AVLTreeTest.kt +++ b/lib/src/test/kotlin/trees/AVLTreeTest.kt @@ -1,27 +1,68 @@ /* * This Kotlin source file was generated by the Gradle 'init' task. */ -package treesTests +package trees import bstrees.implementations.AVLTree import org.junit.jupiter.api.BeforeEach -import kotlin.test.Test +import org.junit.jupiter.api.Test import kotlin.test.assertEquals -import kotlin.test.assertTrue class AVLTreeTest { - private lateinit var avlTree: AVLTree + private lateinit var avlTree: AVLTree @BeforeEach fun setup() { - avlTree = AVLTree() + avlTree = AVLTree() + } + + @Test + fun `simple array test`() { + val array = IntArray(100, { it + 1 }) + for (i in array) { + avlTree.set(i, -i) + } + val expectedGet = -15 + val actualGet = avlTree.get(15) + assertEquals(expectedGet, actualGet, "Get method must return associated with key value") + val expectedSize = 100 + val actualSize = avlTree.size + assertEquals(expectedSize, actualSize, "Size of avl tree must correspond to number key-value pairs") + } + + @Test + fun `size of avl tree with duplicate key`() { + for (i in 1..10) { + avlTree.set(i, 30 + i) + } + for (i in 6..10) { + avlTree.set(i, 0) + } + + val expectedSize = 10 + val actualSize = avlTree.size + assertEquals( + expectedSize, actualSize, + "Size of avl tree must not change with overwriting an existing key" + ) + } + + @Test + fun `set keys twice`() { + for (i in 1..10) { + avlTree.set(i, 30 + i) + } + for (i in 1..10) { + avlTree.set(i, 0) + } + + val expectedSize = 10 + val actualSize = avlTree.size + assertEquals( + expectedSize, actualSize, + "Size of avl tree must not change with overwriting an existing key" + ) } - /* @Test - fun someAVLTreeMethodTest() { - val expectedResult = - val actualResult = - assertEquals(expectedResult, actualResult, "Assert text") - }*/ } From 43a3973054452b846ee9f4569fb7fea7a0526610 Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Fri, 22 Mar 2024 06:20:44 +0300 Subject: [PATCH 017/108] Fixed rotations in avl tree + fixed root change after rotations --- .../kotlin/bstrees/implementations/AVLTree.kt | 19 ++++++++++++------- lib/src/test/kotlin/trees/AVLTreeTest.kt | 2 +- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt index 602e83d..6fa3fc0 100644 --- a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt @@ -20,7 +20,7 @@ class AVLTree, V> : BalanceBSTreeTemplate, V> : BalanceBSTreeTemplate, V> : BalanceBSTreeTemplate, V> : BalanceBSTreeTemplate, V> : BalanceBSTreeTemplate, V> : BalanceBSTreeTemplate Date: Fri, 22 Mar 2024 06:32:08 +0300 Subject: [PATCH 018/108] Fixed get method, changed `simple array test` for easier debug --- lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt | 2 +- lib/src/test/kotlin/trees/AVLTreeTest.kt | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt b/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt index 26786a6..3ef1c42 100644 --- a/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt +++ b/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt @@ -37,7 +37,7 @@ abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate cur = cur.left result > 0 -> cur = cur.right diff --git a/lib/src/test/kotlin/trees/AVLTreeTest.kt b/lib/src/test/kotlin/trees/AVLTreeTest.kt index 9cc7872..21c174e 100644 --- a/lib/src/test/kotlin/trees/AVLTreeTest.kt +++ b/lib/src/test/kotlin/trees/AVLTreeTest.kt @@ -18,14 +18,14 @@ class AVLTreeTest { @Test fun `simple array test`() { - val array = IntArray(100, { it + 1 }) + val array = intArrayOf(1, 2, 3, 4, 5) for (i in array) { avlTree.set(i, -i) } - val expectedGet = -15 - val actualGet = avlTree.get(15) + val expectedGet = -5 + val actualGet = avlTree.get(5) assertEquals(expectedGet, actualGet, "Get method must return associated with key value") - val expectedSize = 100 + val expectedSize = 5 val actualSize = avlTree.size assertEquals(expectedSize, actualSize, "Size of avl tree must correspond to number key-value pairs") } From 528fd61c751d455ff3eb5d032c4cad20738df729 Mon Sep 17 00:00:00 2001 From: Ycyken Date: Fri, 22 Mar 2024 04:23:32 +0000 Subject: [PATCH 019/108] [MegaLinter] Apply linters fixes --- .../kotlin/bstrees/implementations/AVLTree.kt | 39 +++-- .../kotlin/bstrees/implementations/RBTree.kt | 3 +- .../bstrees/implementations/SimpleTree.kt | 7 +- .../bstrees/implementations/Vertices.kt | 4 +- .../bstrees/templates/BSTreeTemplate.kt | 29 +++- .../templates/BalanceBSTreeTemplate.kt | 4 +- .../bstrees/templates/VertexTemplate.kt | 2 +- lib/src/test/kotlin/trees/AVLTreeTest.kt | 12 +- megalinter-reports/IDE-config.txt | 15 ++ .../linters_logs/SUCCESS-KOTLIN_KTLINT.log | 12 ++ megalinter-reports/megalinter.log | 63 +++++++ .../kotlin/bstrees/implementations/AVLTree.kt | 158 +++++++++++++++++ .../kotlin/bstrees/implementations/RBTree.kt | 3 + .../bstrees/implementations/SimpleTree.kt | 18 ++ .../bstrees/implementations/Vertices.kt | 18 ++ .../bstrees/templates/BSTreeTemplate.kt | 161 ++++++++++++++++++ .../templates/BalanceBSTreeTemplate.kt | 4 + .../bstrees/templates/VertexTemplate.kt | 15 ++ .../lib/src/test/kotlin/trees/AVLTreeTest.kt | 68 ++++++++ 19 files changed, 597 insertions(+), 38 deletions(-) create mode 100644 megalinter-reports/IDE-config.txt create mode 100644 megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log create mode 100644 megalinter-reports/megalinter.log create mode 100644 megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt create mode 100644 megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/RBTree.kt create mode 100644 megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt create mode 100644 megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/Vertices.kt create mode 100644 megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt create mode 100644 megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt create mode 100644 megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt create mode 100644 megalinter-reports/updated_sources/lib/src/test/kotlin/trees/AVLTreeTest.kt diff --git a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt index 6fa3fc0..f16468c 100644 --- a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt @@ -3,14 +3,19 @@ package bstrees.implementations import bstrees.templates.BalanceBSTreeTemplate class AVLTree, V> : BalanceBSTreeTemplate>() { - - public override fun set(key: K, value: V): V? { + public override fun set( + key: K, + value: V, + ): V? { val (currentVert, returnResult) = setWithoutBalance(key, value) balance(currentVert) return returnResult } - private fun setWithoutBalance(key: K, value: V): Pair, V?> { + private fun setWithoutBalance( + key: K, + value: V, + ): Pair, V?> { if (root == null) { val newVertex = AVLVertex(key, value) root = newVertex @@ -68,7 +73,6 @@ class AVLTree, V> : BalanceBSTreeTemplate, V> : BalanceBSTreeTemplate): AVLVertex { - val left = origin.left - ?: throw IllegalStateException("difference of heights can't be 2 if left Vertex doesn't exist") + val left = + origin.left + ?: throw IllegalStateException("difference of heights can't be 2 if left Vertex doesn't exist") left.parent = origin.parent - if (origin.parent?.left == origin) origin.parent?.left = left - else origin.parent?.right = left + if (origin.parent?.left == origin) { + origin.parent?.left = left + } else { + origin.parent?.right = left + } origin.parent = left origin.left = left.right @@ -115,12 +123,16 @@ class AVLTree, V> : BalanceBSTreeTemplate): AVLVertex { - val right = origin.right - ?: throw IllegalStateException("difference of heights can't be 2 if left Vertex doesn't exist") + val right = + origin.right + ?: throw IllegalStateException("difference of heights can't be 2 if left Vertex doesn't exist") right.parent = origin.parent - if (origin.parent?.left == origin) origin.parent?.left = right - else origin.parent?.right = right + if (origin.parent?.left == origin) { + origin.parent?.left = right + } else { + origin.parent?.right = right + } origin.parent = right origin.right = right.left @@ -141,7 +153,6 @@ class AVLTree, V> : BalanceBSTreeTemplate, V> : BSTreeTemplate return null } - override operator fun set(key: K, value: V): V? { + override operator fun set( + key: K, + value: V, + ): V? { // set implemenation return null } -} \ No newline at end of file +} diff --git a/lib/src/main/kotlin/bstrees/implementations/Vertices.kt b/lib/src/main/kotlin/bstrees/implementations/Vertices.kt index 1898778..c13eaac 100644 --- a/lib/src/main/kotlin/bstrees/implementations/Vertices.kt +++ b/lib/src/main/kotlin/bstrees/implementations/Vertices.kt @@ -13,6 +13,6 @@ class RBVertex, V>(key: K, value: V) : VertexTemplate, V, Vertex_t : VertexTemplate> { var root: Vertex_t? = null @@ -9,7 +8,9 @@ abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate= 0) { field = value - } else throw IllegalArgumentException("Tree size cannot be a negative number") + } else { + throw IllegalArgumentException("Tree size cannot be a negative number") + } } /** @@ -17,13 +18,19 @@ abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate> { var cur = root val stack = Stack() + override fun next(): Pair { while (hasNext()) { if (cur != null) { @@ -144,5 +158,4 @@ abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate> : - BSTreeTemplate() { -} - + BSTreeTemplate() diff --git a/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt b/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt index 6e6c084..8c0fcb0 100644 --- a/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt +++ b/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt @@ -12,4 +12,4 @@ abstract class VertexTemplate, V, Vertex_t : VertexTemplate { return Pair(key, value) } -} \ No newline at end of file +} diff --git a/lib/src/test/kotlin/trees/AVLTreeTest.kt b/lib/src/test/kotlin/trees/AVLTreeTest.kt index 21c174e..d7ac37b 100644 --- a/lib/src/test/kotlin/trees/AVLTreeTest.kt +++ b/lib/src/test/kotlin/trees/AVLTreeTest.kt @@ -42,8 +42,9 @@ class AVLTreeTest { val expectedSize = 10 val actualSize = avlTree.size assertEquals( - expectedSize, actualSize, - "Size of avl tree must not change with overwriting an existing key" + expectedSize, + actualSize, + "Size of avl tree must not change with overwriting an existing key", ) } @@ -59,10 +60,9 @@ class AVLTreeTest { val expectedSize = 10 val actualSize = avlTree.size assertEquals( - expectedSize, actualSize, - "Size of avl tree must not change with overwriting an existing key" + expectedSize, + actualSize, + "Size of avl tree must not change with overwriting an existing key", ) } - - } diff --git a/megalinter-reports/IDE-config.txt b/megalinter-reports/IDE-config.txt new file mode 100644 index 0000000..be5715f --- /dev/null +++ b/megalinter-reports/IDE-config.txt @@ -0,0 +1,15 @@ +MegaLinter can help you to define the same linter configuration locally + +INSTRUCTIONS + +- Copy the content of IDE-config folder at the root of your repository +- if you are using Visual Studio Code, just reopen your project after the copy, and you will be prompted to install recommended extensions +- If not, you can install extensions manually using the following links. + +IDE EXTENSIONS APPLICABLE TO YOUR PROJECT + +ktlint (KOTLIN) + - emacs: + - flycheck-kotlin: https://github.com/whirm/flycheck-kotlin + - vim: + - ale: https://github.com/w0rp/ale diff --git a/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log b/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log new file mode 100644 index 0000000..888ca70 --- /dev/null +++ b/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log @@ -0,0 +1,12 @@ +Results of ktlint linter (version 1.2.1) +See documentation on https://megalinter.io/7.10.0/descriptors/kotlin_ktlint/ +----------------------------------------------- + +✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/AVLTree.kt - FIXED +✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/RBTree.kt - FIXED +✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt - FIXED +✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/Vertices.kt - FIXED +✅ [SUCCESS] lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt - FIXED +✅ [SUCCESS] lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt - FIXED +✅ [SUCCESS] lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt - FIXED +✅ [SUCCESS] lib/src/test/kotlin/trees/AVLTreeTest.kt - FIXED diff --git a/megalinter-reports/megalinter.log b/megalinter-reports/megalinter.log new file mode 100644 index 0000000..ac06d2a --- /dev/null +++ b/megalinter-reports/megalinter.log @@ -0,0 +1,63 @@ +---------------------------------------------------------------------------------------------------- +------------------------------------ MegaLinter, by OX Security ------------------------------------ +---------------------------------------------------------------------------------------------------- + - Image Creation Date: 2024-03-10T20:25:08Z + - Image Revision: a7a0163b6c8ff7474a283d99a706e27483ddd80f + - Image Version: v7.10.0 +---------------------------------------------------------------------------------------------------- +The MegaLinter documentation can be found at: + - https://megalinter.io/7.10.0 +---------------------------------------------------------------------------------------------------- +::group::MegaLinter initialization (expand for details) +MegaLinter will analyze workspace [/github/workspace] +GITHUB_REPOSITORY: spbu-coding-2023/trees-8 +GITHUB_REF: refs/pull/4/merge +GITHUB_RUN_ID: 8385423086 + + +CLOJURE_CLJSTYLE has been temporary disabled in MegaLinter, please use a previous MegaLinter version or wait for the next one ! +MARKDOWN_REMARK_LINT has been temporary disabled in MegaLinter, please use a previous MegaLinter version or wait for the next one ! +Skipped linters: ACTION_ACTIONLINT, ANSIBLE_ANSIBLE_LINT, ARM_ARM_TTK, BASH_EXEC, BASH_SHELLCHECK, BASH_SHFMT, BICEP_BICEP_LINTER, CLOJURE_CLJSTYLE, CLOJURE_CLJ_KONDO, CLOUDFORMATION_CFN_LINT, COFFEE_COFFEELINT, COPYPASTE_JSCPD, CPP_CLANG_FORMAT, CPP_CPPLINT, CSHARP_CSHARPIER, CSHARP_DOTNET_FORMAT, CSHARP_ROSLYNATOR, CSS_SCSS_LINT, CSS_STYLELINT, C_CLANG_FORMAT, C_CPPLINT, DART_DARTANALYZER, DOCKERFILE_HADOLINT, EDITORCONFIG_EDITORCONFIG_CHECKER, ENV_DOTENV_LINTER, GHERKIN_GHERKIN_LINT, GO_GOLANGCI_LINT, GO_REVIVE, GRAPHQL_GRAPHQL_SCHEMA_LINTER, GROOVY_NPM_GROOVY_LINT, HTML_DJLINT, HTML_HTMLHINT, JAVASCRIPT_ES, JAVASCRIPT_PRETTIER, JAVASCRIPT_STANDARD, JAVA_CHECKSTYLE, JAVA_PMD, JSON_ESLINT_PLUGIN_JSONC, JSON_JSONLINT, JSON_NPM_PACKAGE_JSON_LINT, JSON_PRETTIER, JSON_V8R, JSX_ESLINT, KUBERNETES_HELM, KUBERNETES_KUBECONFORM, KUBERNETES_KUBESCAPE, LATEX_CHKTEX, LUA_LUACHECK, MAKEFILE_CHECKMAKE, MARKDOWN_MARKDOWNLINT, MARKDOWN_MARKDOWN_LINK_CHECK, MARKDOWN_MARKDOWN_TABLE_FORMATTER, MARKDOWN_REMARK_LINT, OPENAPI_SPECTRAL, PERL_PERLCRITIC, PHP_PHPCS, PHP_PHPLINT, PHP_PHPSTAN, PHP_PSALM, POWERSHELL_POWERSHELL, POWERSHELL_POWERSHELL_FORMATTER, PROTOBUF_PROTOLINT, PUPPET_PUPPET_LINT, PYTHON_BANDIT, PYTHON_BLACK, PYTHON_FLAKE8, PYTHON_ISORT, PYTHON_MYPY, PYTHON_PYLINT, PYTHON_PYRIGHT, PYTHON_RUFF, RAKU_RAKU, REPOSITORY_CHECKOV, REPOSITORY_DEVSKIM, REPOSITORY_DUSTILOCK, REPOSITORY_GITLEAKS, REPOSITORY_GIT_DIFF, REPOSITORY_GRYPE, REPOSITORY_KICS, REPOSITORY_SECRETLINT, REPOSITORY_SEMGREP, REPOSITORY_SYFT, REPOSITORY_TRIVY, REPOSITORY_TRIVY_SBOM, REPOSITORY_TRUFFLEHOG, RST_RSTCHECK, RST_RSTFMT, RST_RST_LINT, RUBY_RUBOCOP, RUST_CLIPPY, R_LINTR, SALESFORCE_LIGHTNING_FLOW_SCANNER, SALESFORCE_SFDX_SCANNER_APEX, SALESFORCE_SFDX_SCANNER_AURA, SALESFORCE_SFDX_SCANNER_LWC, SCALA_SCALAFIX, SNAKEMAKE_LINT, SNAKEMAKE_SNAKEFMT, SPELL_CSPELL, SPELL_LYCHEE, SPELL_PROSELINT, SPELL_VALE, SQL_SQLFLUFF, SQL_SQL_LINT, SQL_TSQLLINT, SWIFT_SWIFTLINT, TEKTON_TEKTON_LINT, TERRAFORM_TERRAFORM_FMT, TERRAFORM_TERRAGRUNT, TERRAFORM_TERRASCAN, TERRAFORM_TFLINT, TSX_ESLINT, TYPESCRIPT_ES, TYPESCRIPT_PRETTIER, TYPESCRIPT_STANDARD, VBDOTNET_DOTNET_FORMAT, XML_XMLLINT, YAML_PRETTIER, YAML_V8R, YAML_YAMLLINT +To receive reports as email, please set variable EMAIL_REPORTER_EMAIL +::endgroup:: +::group::MegaLinter now collects the files to analyse (expand for details) +Listing updated files in [/github/workspace] using git diff. +Modified files: +.github/workflows/CI_Test.yml +lib/src/main/kotlin/bstrees/implementations/AVLTree.kt +lib/src/main/kotlin/bstrees/implementations/RBTree.kt +lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt +lib/src/main/kotlin/bstrees/implementations/Vertices.kt +lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt +lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt +lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt +lib/src/main/kotlin/org/example/Library.kt +lib/src/test/kotlin/org/example/LibraryTest.kt +lib/src/test/kotlin/trees/AVLTreeTest.kt +- File extensions: .kt, .kts +- Excluding .gitignored files [0]: +Kept [8] files on [9] found files + ++----MATCHING LINTERS-+----------+----------------+------------+ +| Descriptor | Linter | Criteria | Matching files | Format/Fix | ++------------+--------+----------+----------------+------------+ +| KOTLIN | ktlint | .kt|.kts | 8 | yes | ++------------+--------+----------+----------------+------------+ +::endgroup:: +::group::✅ Linted [KOTLIN] files with [ktlint] successfully - (10.1s) (expand for details) +- Using [ktlint v1.2.1] https://megalinter.io/7.10.0/descriptors/kotlin_ktlint +- MegaLinter key: [KOTLIN_KTLINT] +- Rules config: identified by [ktlint] +- Number of files analyzed: [8] +::endgroup:: + ++----SUMMARY-+--------+------+-------+-------+--------+--------------+ +| Descriptor | Linter | Mode | Files | Fixed | Errors | Elapsed time | ++------------+--------+------+-------+-------+--------+--------------+ +| ✅ KOTLIN | ktlint | file | 8 | 8 | 0 | 10.1s | ++------------+--------+------+-------+-------+--------+--------------+ + +[Updated Sources Reporter] copied 8 fixed source files in folder /github/workspace/megalinter-reports/updated_sources. +Download it from artifacts then copy-paste it in your local repo to apply linters updates +[GitHub Comment Reporter] Posted summary as comment on spbu-coding-2023/trees-8 #PR4 +✅ Successfully linted all files without errors diff --git a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt new file mode 100644 index 0000000..f16468c --- /dev/null +++ b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt @@ -0,0 +1,158 @@ +package bstrees.implementations + +import bstrees.templates.BalanceBSTreeTemplate + +class AVLTree, V> : BalanceBSTreeTemplate>() { + public override fun set( + key: K, + value: V, + ): V? { + val (currentVert, returnResult) = setWithoutBalance(key, value) + balance(currentVert) + return returnResult + } + + private fun setWithoutBalance( + key: K, + value: V, + ): Pair, V?> { + if (root == null) { + val newVertex = AVLVertex(key, value) + root = newVertex + size += 1 + return Pair(newVertex, null) + } + + var cur = root ?: throw IllegalStateException("Case when root is null is processed above") + while (true) { + val result = key.compareTo(cur.key) + if (result < 0) { + if (cur.left == null) { + val newVertex = AVLVertex(key, value) + cur.left = newVertex + newVertex.parent = cur + size += 1 + return Pair(newVertex, null) + } + cur = cur.left ?: throw IllegalStateException("Case when cur.left is null is processed above") + } else if (result > 0) { + if (cur.right == null) { + val newVertex = AVLVertex(key, value) + cur.right = newVertex + newVertex.parent = cur + size += 1 + return Pair(newVertex, null) + } + cur = cur.right ?: throw IllegalStateException("Case when cur.rightt is null is processed above") + } else { + val oldValue = cur.value + cur.value = value + return Pair(cur, oldValue) + } + } + } + + private fun balance(vertex: AVLVertex) { + var cur = vertex + var prevKey = cur.key + while (cur.parent != null) { + prevKey = cur.key + cur = cur.parent ?: throw IllegalStateException("Parent can't be null due to while condition") + if (prevKey == cur.left?.key) { + cur.diffHeight += 1 + } else if (prevKey == cur.right?.key) { + cur.diffHeight -= 1 + } + + if (cur.diffHeight == 2) { + if (getDiffHeight(cur.left) >= 0) { + cur = rotateRight(cur) + } else if (getDiffHeight(cur.left) == -1) { + cur.left?.let { + cur = rotateLeft(it) + cur = rotateRight(cur) + } + } + } else if (cur.diffHeight == -2) { + if (getDiffHeight(cur.right) <= 0) { + cur = rotateLeft(cur) + } else if (getDiffHeight(cur.right) == 1) { + cur.right?.let { + cur = rotateRight(cur) + cur = rotateLeft(cur) + } + } + } + + if (cur.diffHeight == 0) break + } + } + + private fun getDiffHeight(vertex: AVLVertex?): Int { + return vertex?.diffHeight ?: 0 + } + + private fun rotateRight(origin: AVLVertex): AVLVertex { + val left = + origin.left + ?: throw IllegalStateException("difference of heights can't be 2 if left Vertex doesn't exist") + + left.parent = origin.parent + if (origin.parent?.left == origin) { + origin.parent?.left = left + } else { + origin.parent?.right = left + } + + origin.parent = left + origin.left = left.right + origin.left?.parent = origin + left.right = origin + + if (left.diffHeight == 0) { + origin.diffHeight = 1 + left.diffHeight = -1 + } else if (left.diffHeight == 1) { + origin.diffHeight = 0 + left.diffHeight = 0 + } + if (origin == root) { + root = left + } + return left + } + + private fun rotateLeft(origin: AVLVertex): AVLVertex { + val right = + origin.right + ?: throw IllegalStateException("difference of heights can't be 2 if left Vertex doesn't exist") + + right.parent = origin.parent + if (origin.parent?.left == origin) { + origin.parent?.left = right + } else { + origin.parent?.right = right + } + + origin.parent = right + origin.right = right.left + origin.right?.parent = origin + right.left = origin + + if (right.diffHeight == 0) { + origin.diffHeight = -1 + right.diffHeight = 1 + } else if (right.diffHeight == -1) { + origin.diffHeight = 0 + right.diffHeight = 0 + } + if (origin == root) { + root = right + } + return right + } + + public override fun remove(key: K): V? { + return TODO() + } +} diff --git a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/RBTree.kt b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/RBTree.kt new file mode 100644 index 0000000..c1c9ef5 --- /dev/null +++ b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/RBTree.kt @@ -0,0 +1,3 @@ +package bstrees.implementations + +class RBTree diff --git a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt new file mode 100644 index 0000000..79bcd1b --- /dev/null +++ b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt @@ -0,0 +1,18 @@ +package bstrees.implementations + +import bstrees.templates.BSTreeTemplate + +class SimpleTree, V> : BSTreeTemplate>() { + override fun remove(key: K): V? { + // remove implementation + return null + } + + override operator fun set( + key: K, + value: V, + ): V? { + // set implemenation + return null + } +} diff --git a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/Vertices.kt b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/Vertices.kt new file mode 100644 index 0000000..c13eaac --- /dev/null +++ b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/Vertices.kt @@ -0,0 +1,18 @@ +package bstrees.implementations + +import bstrees.templates.VertexTemplate + +class SimpleVertex, V>(key: K, value: V) : VertexTemplate>(key, value) + +class AVLVertex, V>(key: K, value: V) : VertexTemplate>(key, value) { + var diffHeight: Int = 0 +} + +class RBVertex, V>(key: K, value: V) : VertexTemplate>(key, value) { + var color: Color = Color.BLACK + + enum class Color { + BLACK, + RED, + } +} diff --git a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt new file mode 100644 index 0000000..5e9c759 --- /dev/null +++ b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt @@ -0,0 +1,161 @@ +package bstrees.templates + +import java.util.Stack + +abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate> { + var root: Vertex_t? = null + var size: Int = 0 + protected set(value) { + if (value >= 0) { + field = value + } else { + throw IllegalArgumentException("Tree size cannot be a negative number") + } + } + + /** + * Associates the specified [value] with the specified [key] in the tree. + * + * @return the previous value associated with the key, or `null` if the key was not present in the tree. + */ + public abstract operator fun set( + key: K, + value: V, + ): V? + + /** + * Associates the specified value with the specified key if this key is not in the tree. + * @return [true] if this key is not in the tree, otherwise [false] + */ + public fun setIfAbsent( + key: K, + value: V, + ): Boolean { + if (get(key) == null) { + set(key, value) + return true + } + return false + } + + /** + * Returns the value corresponding to the given [key], or `null` if such a key is not present in the tree. + */ + public operator fun get(key: K): V? { + var cur = root + while (cur != null) { + val result = key.compareTo(cur.key) + when { + result < 0 -> cur = cur.left + result > 0 -> cur = cur.right + result == 0 -> return cur.value + } + } + return null + } + + /** + * Returns the value corresponding to the given [key], or [defaultValue] if such a key is not present in the map. + */ + public fun getOrDefault( + key: K, + defaultValue: Any, + ): Any { + return get(key) ?: defaultValue + } + + /** + * Returns the value for the given [key] if the value is present and not `null`. + * Otherwise, calls the [set] function, + * set [defaultValue] into the tree under the given key and returns the call result. + */ + public fun getOrSet( + key: K, + defaultValue: V, + ): V? { + return get(key) ?: set(key, defaultValue) + } + + /** + * Removes the specified key and its corresponding value from the tree. + * + * @return the previous value associated with the key, or `null` if the key was not present in the map. + */ + public abstract fun remove(key: K): V? + + public operator fun iterator(): TreeIterator { + return TreeIterator() + } + + inner class TreeIterator : Iterator> { + var cur = root + val stack = Stack() + + override fun next(): Pair { + while (hasNext()) { + if (cur != null) { + cur?.let { + stack.push(it) + cur = it.left + } + } else { + val returnVert = stack.pop() + cur = returnVert.right + return returnVert.toPair() + } + } + throw IndexOutOfBoundsException() + } + + override fun hasNext(): Boolean { + return stack.isNotEmpty() or (cur != null) + } + } + + /** + * Returns Pair by minimum key in the tree. If tree is empty then returns null + */ + public fun min(): Pair? { + return minVertex(root)?.toPair() + } + + private fun minVertex(vertex: Vertex_t?): Vertex_t? { + var cur = vertex + while (cur?.left != null) { + cur = cur.left + } + return cur + } + + /** + * Returns Pair by maximum key in the tree. If tree is empty then returns null + */ + public fun max(): Pair? { + return maxVert(root)?.toPair() + } + + private fun maxVert(vertex: Vertex_t?): Vertex_t? { + var cur = vertex + while (cur?.right != null) { + cur = cur.right + } + return cur + } + + public fun isEmpty(): Boolean { + return size == 0 + } + + public fun isNotEmpty(): Boolean { + return size != 0 + } + + public fun containsKey(key: K): Boolean { + return get(key) != null + } + + public fun clear() { + size = 0 + root = null + } +} diff --git a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt new file mode 100644 index 0000000..1c2cb99 --- /dev/null +++ b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt @@ -0,0 +1,4 @@ +package bstrees.templates + +abstract class BalanceBSTreeTemplate, V, Vertex_t : VertexTemplate> : + BSTreeTemplate() diff --git a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt new file mode 100644 index 0000000..8c0fcb0 --- /dev/null +++ b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt @@ -0,0 +1,15 @@ +package bstrees.templates + +abstract class VertexTemplate, V, Vertex_t : VertexTemplate>(val key: K, var value: V) { + var parent: Vertex_t? = null + var left: Vertex_t? = null + var right: Vertex_t? = null + + operator fun compareTo(other: VertexTemplate): Int { + return key.compareTo(other.key) + } + + fun toPair(): Pair { + return Pair(key, value) + } +} diff --git a/megalinter-reports/updated_sources/lib/src/test/kotlin/trees/AVLTreeTest.kt b/megalinter-reports/updated_sources/lib/src/test/kotlin/trees/AVLTreeTest.kt new file mode 100644 index 0000000..d7ac37b --- /dev/null +++ b/megalinter-reports/updated_sources/lib/src/test/kotlin/trees/AVLTreeTest.kt @@ -0,0 +1,68 @@ +/* + * This Kotlin source file was generated by the Gradle 'init' task. + */ +package trees + +import bstrees.implementations.AVLTree +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals + +class AVLTreeTest { + private lateinit var avlTree: AVLTree + + @BeforeEach + fun setup() { + avlTree = AVLTree() + } + + @Test + fun `simple array test`() { + val array = intArrayOf(1, 2, 3, 4, 5) + for (i in array) { + avlTree.set(i, -i) + } + val expectedGet = -5 + val actualGet = avlTree.get(5) + assertEquals(expectedGet, actualGet, "Get method must return associated with key value") + val expectedSize = 5 + val actualSize = avlTree.size + assertEquals(expectedSize, actualSize, "Size of avl tree must correspond to number key-value pairs") + } + + @Test + fun `size of avl tree with duplicate keys`() { + for (i in 1..10) { + avlTree.set(i, 30 + i) + } + for (i in 6..10) { + avlTree.set(i, 0) + } + + val expectedSize = 10 + val actualSize = avlTree.size + assertEquals( + expectedSize, + actualSize, + "Size of avl tree must not change with overwriting an existing key", + ) + } + + @Test + fun `set keys twice`() { + for (i in 1..10) { + avlTree.set(i, 30 + i) + } + for (i in 1..10) { + avlTree.set(i, 0) + } + + val expectedSize = 10 + val actualSize = avlTree.size + assertEquals( + expectedSize, + actualSize, + "Size of avl tree must not change with overwriting an existing key", + ) + } +} From 1fc34b249f55a402b36a93485718f380000ae16f Mon Sep 17 00:00:00 2001 From: Ycyken <135718038+Ycyken@users.noreply.github.com> Date: Fri, 22 Mar 2024 17:34:19 +0300 Subject: [PATCH 020/108] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 534bb00..59b89d4 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,11 @@ Team #8's project on binary trees. ## About -Three trees are implemented in this library: [R&B](https://en.wikipedia.org/wiki/Red–black_tree), [AVL](https://en.wikipedia.org/wiki/AVL_tree) and [Binary Search Tree](https://en.wikipedia.org/wiki/Binary_search_tree). +Three trees are implemented in this library: [Red-Black](https://en.wikipedia.org/wiki/Red–black_tree), [AVL](https://en.wikipedia.org/wiki/AVL_tree) and [Binary Search Tree](https://en.wikipedia.org/wiki/Binary_search_tree). ## Authors -- [Aleksey Dmitrievtsev](https://github.com/admitrievtsev) - Red&Black Tree +- [Aleksey Dmitrievtsev](https://github.com/admitrievtsev) - Red-Black Tree - [Gleb Nasretdinov](https://github.com/Ycyken) - AVL Tree - [Azamat Ishbaev](https://github.com/odiumuniverse) - Binary Search Tree @@ -33,7 +33,7 @@ Standard methods are implemented in each tree: + `get(key)` - Returns the value corresponding to the given key + `iterator()` - Iteration by key-value pairs in order of keys -There are also many other methods: +There are also many others methods: + `setIfAbsent(key,value)` + `getOrDefault(key, defaultValue)` @@ -45,7 +45,7 @@ There are also many other methods: + `containsKey(key)` + `clear()` -AVL and R&B trees are self-balancing +AVL and Red-Black trees are self-balancing ### Suggestions and wishes From da34fe5a88ac47fb3043ac085a17b0a95a6a53f4 Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Fri, 22 Mar 2024 18:35:07 +0300 Subject: [PATCH 021/108] Add set method BSTree --- .../bstrees/implementations/SimpleTree.kt | 44 +++++++++++++++---- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt b/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt index 79bcd1b..523412f 100644 --- a/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt @@ -4,15 +4,43 @@ import bstrees.templates.BSTreeTemplate class SimpleTree, V> : BSTreeTemplate>() { override fun remove(key: K): V? { - // remove implementation return null } - override operator fun set( - key: K, - value: V, - ): V? { - // set implemenation - return null + override operator fun set(key: K, value: V): V? { + if (root == null){ + val vertex = SimpleVertex(key,value) + root = vertex + size+=1 + return null + } + + var current = root ?: throw IllegalStateException() + while (true){ + val result = current.key.compareTo(key) + if (result < 0){ + if(current.left == null){ + val newVertex = SimpleVertex(key, value) + current.left = newVertex + newVertex.parent = current + size+= 1 + return null + } + current = current.left ?: throw IllegalStateException() + } else if (result > 0){ + if (current.right == null){ + val newVertex = SimpleVertex(key, value) + current.right = newVertex + newVertex.parent = current + size += 1 + return null + } + current = current.right ?: throw IllegalStateException() + } else{ + val oldValue = current.value + current.value = value + return null + } + } } -} +} \ No newline at end of file From 603576f2225f0eacd621c47d76c0d80c8759b0d3 Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Fri, 22 Mar 2024 18:37:05 +0300 Subject: [PATCH 022/108] Added some private methods, changed key to var in vertices -remove in avl tree still doens't implemented --- .../kotlin/bstrees/implementations/AVLTree.kt | 86 ++++++++++++------- .../bstrees/templates/BSTreeTemplate.kt | 27 +++--- .../bstrees/templates/VertexTemplate.kt | 2 +- 3 files changed, 74 insertions(+), 41 deletions(-) diff --git a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt index 6fa3fc0..699f5ac 100644 --- a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt @@ -4,9 +4,9 @@ import bstrees.templates.BalanceBSTreeTemplate class AVLTree, V> : BalanceBSTreeTemplate>() { - public override fun set(key: K, value: V): V? { + public override operator fun set(key: K, value: V): V? { val (currentVert, returnResult) = setWithoutBalance(key, value) - balance(currentVert) + balanceAfterSet(currentVert) return returnResult } @@ -47,7 +47,7 @@ class AVLTree, V> : BalanceBSTreeTemplate) { + private fun balanceAfterSet(vertex: AVLVertex) { var cur = vertex var prevKey = cur.key while (cur.parent != null) { @@ -59,35 +59,68 @@ class AVLTree, V> : BalanceBSTreeTemplate= 0) { - cur = rotateRight(cur) - } else if (getDiffHeight(cur.left) == -1) { - cur.left?.let { - cur = rotateLeft(it) - cur = rotateRight(cur) - } - } + cur = balanceOnce(cur) + if (cur.diffHeight == 0) break + } + } - } else if (cur.diffHeight == -2) { - if (getDiffHeight(cur.right) <= 0) { - cur = rotateLeft(cur) - } else if (getDiffHeight(cur.right) == 1) { - cur.right?.let { - cur = rotateRight(cur) - cur = rotateLeft(cur) - } - } + public override fun remove(key: K): V? { + var toRemove = VertByKey(key) + var returnResult = toRemove?.value + var toBalance: AVLVertex? = null + if (toRemove == null) return null + + if ((toRemove.left == null) and (toRemove.right == null)) { + toBalance = toRemove.parent + toRemove = null + } else if (toRemove.right == null) { + toRemove.left?.parent = toRemove.parent + toRemove = toRemove.left + toBalance = toRemove?.parent + } else { + var minRight = minVertex(toRemove.right) + if (toRemove.right == minRight) { + } else { + minRight?.parent?.left = null + minRight?.right = toRemove.right } - - if (cur.diffHeight == 0) break + minRight?.left = toRemove.left + minRight?.parent = toRemove.parent + toRemove = minRight + toBalance = toRemove?.parent } + return TODO() } private fun getDiffHeight(vertex: AVLVertex?): Int { return vertex?.diffHeight ?: 0 } + private fun balanceOnce(vertex_: AVLVertex): AVLVertex { + var vertex = vertex_ + if (vertex.diffHeight == 2) { + if (getDiffHeight(vertex.left) >= 0) { + vertex = rotateRight(vertex) + } else if (getDiffHeight(vertex.left) == -1) { + vertex.left?.let { + vertex = rotateLeft(it) + vertex = rotateRight(vertex) + } + } + + } else if (vertex.diffHeight == -2) { + if (getDiffHeight(vertex.right) <= 0) { + vertex = rotateLeft(vertex) + } else if (getDiffHeight(vertex.right) == 1) { + vertex.right?.let { + vertex = rotateRight(vertex) + vertex = rotateLeft(vertex) + } + } + } + return vertex + } + private fun rotateRight(origin: AVLVertex): AVLVertex { val left = origin.left ?: throw IllegalStateException("difference of heights can't be 2 if left Vertex doesn't exist") @@ -139,9 +172,4 @@ class AVLTree, V> : BalanceBSTreeTemplate, V, Vertex_t : VertexTemplate cur = cur.left - result > 0 -> cur = cur.right - result == 0 -> return cur.value - } - } - return null + return VertByKey(key)?.value } /** @@ -105,7 +96,7 @@ abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate cur.key) { + cur = cur.right + } else if (key == cur.key) { + break + } + } + return cur + } + public fun isEmpty(): Boolean { return size == 0 } diff --git a/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt b/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt index 6e6c084..1c4bddb 100644 --- a/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt +++ b/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt @@ -1,6 +1,6 @@ package bstrees.templates -abstract class VertexTemplate, V, Vertex_t : VertexTemplate>(val key: K, var value: V) { +abstract class VertexTemplate, V, Vertex_t : VertexTemplate>(var key: K, var value: V) { var parent: Vertex_t? = null var left: Vertex_t? = null var right: Vertex_t? = null From 32c6a4ecc0d7b05a0c401c63266aaa946817fc00 Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Fri, 22 Mar 2024 19:25:22 +0300 Subject: [PATCH 023/108] Add remove method --- .../bstrees/implementations/SimpleTree.kt | 62 ++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt b/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt index 8b53a6c..1d51a3e 100644 --- a/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt @@ -4,10 +4,70 @@ import bstrees.templates.BSTreeTemplate class SimpleTree, V> : BSTreeTemplate>() { override fun remove(key: K): V? { - // remove implementation + if (containsKey(key)) { + val vertex = VertByKey(key) + val parent = vertex?.parent + if (vertex?.left == null && vertex?.right == null) { + when { + parent == null -> root = null + parent.left == vertex -> parent.left = null + else -> parent.right = null + } + } + else if (vertex.left != null && vertex.right == null) { + when { + parent == null -> { + root = vertex.left + root?.parent = null + } + parent.left == vertex -> { + parent.left = vertex.left + vertex.left?.parent = parent + } + else -> { + parent.right = vertex.left + vertex.left?.parent = parent + } + } + } + else if (vertex.left == null) { + when { + parent == null -> { + root = vertex.right + root?.parent = null + } + parent.left == vertex -> { + parent.left = vertex.right + vertex.right?.parent = parent + } + else -> { + parent.right = vertex.right + vertex.right?.parent = parent + } + } + } + else { + val successor = minVertex(vertex.right) + val successorParent = successor?.parent + + vertex.key = successor?.key ?: vertex.key + vertex.value = successor?.value ?: vertex.value + + when { + successorParent?.left == successor -> successorParent?.left = successor?.right + else -> successorParent?.right = successor?.right + } + + successor?.right?.parent = successorParent + } + + size-- + return vertex?.value + } return null } + override operator fun set(key: K, value: V): V? { // set implemenation return null From 1eed4a15af8f0156ffad1bc03d09f0b167f407dd Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Sat, 23 Mar 2024 11:42:21 +0300 Subject: [PATCH 024/108] Refactor remove method in SimpleTree -refactored since key in vertices is var now --- .../kotlin/bstrees/implementations/AVLTree.kt | 2 +- .../bstrees/implementations/SimpleTree.kt | 82 ++++++------------- .../bstrees/templates/BSTreeTemplate.kt | 4 +- 3 files changed, 28 insertions(+), 60 deletions(-) diff --git a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt index 699f5ac..f09cd39 100644 --- a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt @@ -65,7 +65,7 @@ class AVLTree, V> : BalanceBSTreeTemplate? = null if (toRemove == null) return null diff --git a/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt b/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt index 1d51a3e..f43eb97 100644 --- a/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt @@ -3,71 +3,39 @@ package bstrees.implementations import bstrees.templates.BSTreeTemplate class SimpleTree, V> : BSTreeTemplate>() { + override fun remove(key: K): V? { - if (containsKey(key)) { - val vertex = VertByKey(key) - val parent = vertex?.parent - if (vertex?.left == null && vertex?.right == null) { - when { - parent == null -> root = null - parent.left == vertex -> parent.left = null - else -> parent.right = null - } + val vertex = vertByKey(key) ?: return null + val parent = vertex.parent + val oldValue = vertex.value + if (vertex.left == null && vertex.right == null) { + when { + parent == null -> root = null + parent.left == vertex -> parent.left = null + else -> parent.right = null } - else if (vertex.left != null && vertex.right == null) { - when { - parent == null -> { - root = vertex.left - root?.parent = null - } - parent.left == vertex -> { - parent.left = vertex.left - vertex.left?.parent = parent - } - else -> { - parent.right = vertex.left - vertex.left?.parent = parent - } - } + } else if (vertex.right == null) { + vertex.left?.let { + vertex.key = it.key + vertex.value = it.value + vertex.left = null } - else if (vertex.left == null) { - when { - parent == null -> { - root = vertex.right - root?.parent = null - } - parent.left == vertex -> { - parent.left = vertex.right - vertex.right?.parent = parent - } - else -> { - parent.right = vertex.right - vertex.right?.parent = parent - } - } + } else { + val successor = minVertex(vertex.right) + val successorParent = successor?.parent + successor?.let { + vertex.key = successor.key + vertex.value = successor.value } - else { - val successor = minVertex(vertex.right) - val successorParent = successor?.parent - - vertex.key = successor?.key ?: vertex.key - vertex.value = successor?.value ?: vertex.value - - when { - successorParent?.left == successor -> successorParent?.left = successor?.right - else -> successorParent?.right = successor?.right - } - - successor?.right?.parent = successorParent + when { + successorParent?.left == successor -> successorParent?.left = null + else -> vertex.right = null } - - size-- - return vertex?.value } - return null + --size + return oldValue } - override operator fun set(key: K, value: V): V? { // set implemenation return null diff --git a/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt b/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt index 1846d1d..8cc91cb 100644 --- a/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt +++ b/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt @@ -35,7 +35,7 @@ abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate Date: Sat, 23 Mar 2024 15:18:01 +0300 Subject: [PATCH 025/108] Implemented remove method in AVL tree --- .../kotlin/bstrees/implementations/AVLTree.kt | 75 +++++++++++++------ .../bstrees/templates/BSTreeTemplate.kt | 4 +- 2 files changed, 56 insertions(+), 23 deletions(-) diff --git a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt index 699f5ac..91cf4e9 100644 --- a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt @@ -5,9 +5,9 @@ import bstrees.templates.BalanceBSTreeTemplate class AVLTree, V> : BalanceBSTreeTemplate>() { public override operator fun set(key: K, value: V): V? { - val (currentVert, returnResult) = setWithoutBalance(key, value) + val (currentVert, oldValue) = setWithoutBalance(key, value) balanceAfterSet(currentVert) - return returnResult + return oldValue } private fun setWithoutBalance(key: K, value: V): Pair, V?> { @@ -65,31 +65,64 @@ class AVLTree, V> : BalanceBSTreeTemplate? = null - if (toRemove == null) return null + val toRemove = vertByKey(key) ?: return null + val oldValue = toRemove.value + removeVert(toRemove) + return oldValue + } + private fun removeVert(toRemove: AVLVertex) { + val parent = toRemove.parent + val toBalance = parent if ((toRemove.left == null) and (toRemove.right == null)) { - toBalance = toRemove.parent - toRemove = null + when { + parent == null -> root = null + + parent.left == toRemove -> { + parent.left = null + parent.diffHeight -= 1 + } + + parent.right == toRemove -> { + parent.right = null + parent.diffHeight += 1 + } + } + size -= 1 + balanceAfterRemove(toBalance) } else if (toRemove.right == null) { - toRemove.left?.parent = toRemove.parent - toRemove = toRemove.left - toBalance = toRemove?.parent + toRemove.left?.let { + toRemove.key = it.key + toRemove.value = it.value + toRemove.left = null + toRemove.diffHeight = 0 + } + size -= 1 + balanceAfterRemove(toBalance) + when { + parent?.left == toRemove -> parent.diffHeight -= 1 + parent?.right == toRemove -> parent.diffHeight += 1 + } } else { - var minRight = minVertex(toRemove.right) - if (toRemove.right == minRight) { - } else { - minRight?.parent?.left = null - minRight?.right = toRemove.right + val minRight = minVertex(toRemove.right) + ?: throw IllegalStateException("min of subtree can't be null if it's contains at least one element") + toRemove.key = minRight.key + toRemove.value = minRight.value + removeVert(minRight) + } + } + + private fun balanceAfterRemove(vertex: AVLVertex?) { + var cur = vertex ?: return + while (cur.diffHeight != 0) { + cur = balanceOnce(cur) + if (cur.diffHeight != 0) { + when { + cur.parent?.left == cur -> cur.parent?.let { it.diffHeight -= 1 } + cur.parent?.right == cur -> cur.parent?.let { it.diffHeight += 1 } + } } - minRight?.left = toRemove.left - minRight?.parent = toRemove.parent - toRemove = minRight - toBalance = toRemove?.parent } - return TODO() } private fun getDiffHeight(vertex: AVLVertex?): Int { diff --git a/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt b/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt index 1846d1d..8cc91cb 100644 --- a/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt +++ b/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt @@ -35,7 +35,7 @@ abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate Date: Sat, 23 Mar 2024 16:07:35 +0300 Subject: [PATCH 026/108] Added docs to AVLTree methods and tiny refactor -added setter to diffHeights in AVLVertex --- .../kotlin/bstrees/implementations/AVLTree.kt | 30 +++++++++++++++---- .../bstrees/implementations/Vertices.kt | 6 ++++ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt index 91cf4e9..eaa27a4 100644 --- a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt @@ -10,6 +10,10 @@ class AVLTree, V> : BalanceBSTreeTemplate, V?> { if (root == null) { val newVertex = AVLVertex(key, value) @@ -47,6 +51,10 @@ class AVLTree, V> : BalanceBSTreeTemplate) { var cur = vertex var prevKey = cur.key @@ -71,10 +79,12 @@ class AVLTree, V> : BalanceBSTreeTemplate) { val parent = toRemove.parent - val toBalance = parent - if ((toRemove.left == null) and (toRemove.right == null)) { + if (toRemove.left == null && toRemove.right == null) { when { parent == null -> root = null @@ -89,7 +99,7 @@ class AVLTree, V> : BalanceBSTreeTemplate, V> : BalanceBSTreeTemplate parent.diffHeight -= 1 parent?.right == toRemove -> parent.diffHeight += 1 @@ -112,6 +122,10 @@ class AVLTree, V> : BalanceBSTreeTemplate?) { var cur = vertex ?: return while (cur.diffHeight != 0) { @@ -129,8 +143,12 @@ class AVLTree, V> : BalanceBSTreeTemplate): AVLVertex { - var vertex = vertex_ + /** + * Balances subtree by specified root, updates diffHeights of vertices + * @return new root of subtree + */ + private fun balanceOnce(_vertex: AVLVertex): AVLVertex { + var vertex = _vertex if (vertex.diffHeight == 2) { if (getDiffHeight(vertex.left) >= 0) { vertex = rotateRight(vertex) diff --git a/lib/src/main/kotlin/bstrees/implementations/Vertices.kt b/lib/src/main/kotlin/bstrees/implementations/Vertices.kt index 1898778..e68d4b2 100644 --- a/lib/src/main/kotlin/bstrees/implementations/Vertices.kt +++ b/lib/src/main/kotlin/bstrees/implementations/Vertices.kt @@ -6,6 +6,12 @@ class SimpleVertex, V>(key: K, value: V) : VertexTemplate, V>(key: K, value: V) : VertexTemplate>(key, value) { var diffHeight: Int = 0 + set(value) { + if (value !in -2..2) { + throw IllegalArgumentException("difference of heights can't be out of [-2,2]") + } + field = value + } } class RBVertex, V>(key: K, value: V) : VertexTemplate>(key, value) { From ed08a17690f0f8e1e0fee799594eb169baa1a08f Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Sat, 23 Mar 2024 16:47:53 +0300 Subject: [PATCH 027/108] Change `remove` method and add exception in `set` method --- .../bstrees/implementations/SimpleTree.kt | 41 +++++++++++++++++-- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt b/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt index f43eb97..9043dc9 100644 --- a/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt @@ -3,7 +3,7 @@ package bstrees.implementations import bstrees.templates.BSTreeTemplate class SimpleTree, V> : BSTreeTemplate>() { - + override fun remove(key: K): V? { val vertex = vertByKey(key) ?: return null val parent = vertex.parent @@ -37,7 +37,40 @@ class SimpleTree, V> : BSTreeTemplate } override operator fun set(key: K, value: V): V? { - // set implemenation - return null + + if (root == null) { + val vertex = SimpleVertex(key, value) + root = vertex + size += 1 + return null + } + + var current = root ?: throw IllegalStateException("Can't be null, there was a check above") + while (true) { + val result = current.key.compareTo(key) + if (result < 0) { + if (current.left == null) { + val newVertex = SimpleVertex(key, value) + current.left = newVertex + newVertex.parent = current + size += 1 + return null + } + current = current.left ?: throw IllegalStateException("Case when cur.left is null is processed above") + } else if (result > 0) { + if (current.right == null) { + val newVertex = SimpleVertex(key, value) + current.right = newVertex + newVertex.parent = current + size += 1 + return null + } + current = current.right ?: throw IllegalStateException("Case when cur.right is null is processed above") + } else { + val oldValue = current.value + current.value = value + return null + } + } } -} \ No newline at end of file +} From 9632af4fbf7bae44e3969590415b911698c9f528 Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Sat, 23 Mar 2024 16:59:02 +0300 Subject: [PATCH 028/108] Fixed set bug and added remove tests for avl tree -fixed bug when tree was trying to balance after setting value for already existing vertex (thx to diffHeights setter) -added remove tests for avl tree -a little refactor for set method in avl tree --- .../kotlin/bstrees/implementations/AVLTree.kt | 15 ++++---- lib/src/test/kotlin/trees/AVLTreeTest.kt | 38 +++++++++++++++++-- 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt index eaa27a4..05381db 100644 --- a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt @@ -6,19 +6,23 @@ class AVLTree, V> : BalanceBSTreeTemplate, V?> { if (root == null) { val newVertex = AVLVertex(key, value) root = newVertex - size += 1 return Pair(newVertex, null) } @@ -30,7 +34,6 @@ class AVLTree, V> : BalanceBSTreeTemplate, V> : BalanceBSTreeTemplate, V> : BalanceBSTreeTemplate, V> : BalanceBSTreeTemplate, V> : BalanceBSTreeTemplate parent.diffHeight -= 1 diff --git a/lib/src/test/kotlin/trees/AVLTreeTest.kt b/lib/src/test/kotlin/trees/AVLTreeTest.kt index 21c174e..84a8663 100644 --- a/lib/src/test/kotlin/trees/AVLTreeTest.kt +++ b/lib/src/test/kotlin/trees/AVLTreeTest.kt @@ -24,10 +24,10 @@ class AVLTreeTest { } val expectedGet = -5 val actualGet = avlTree.get(5) - assertEquals(expectedGet, actualGet, "Get method must return associated with key value") + assertEquals(expectedGet, actualGet, "Get method must return the value associated with the key") val expectedSize = 5 val actualSize = avlTree.size - assertEquals(expectedSize, actualSize, "Size of avl tree must correspond to number key-value pairs") + assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") } @Test @@ -43,7 +43,7 @@ class AVLTreeTest { val actualSize = avlTree.size assertEquals( expectedSize, actualSize, - "Size of avl tree must not change with overwriting an existing key" + "Size of the tree must not change after overwriting an existing key" ) } @@ -60,9 +60,39 @@ class AVLTreeTest { val actualSize = avlTree.size assertEquals( expectedSize, actualSize, - "Size of avl tree must not change with overwriting an existing key" + "Size of the tree must not change after overwriting an existing key" ) } + @Test + fun `simple remove`() { + avlTree[0] = 5 + + val expectedResult = 5 + val actualResult = avlTree.remove(0) + val expectedSize = 0 + val actualSize = avlTree.size + assertEquals( + expectedResult, actualResult, + "Remove must return removed value" + ) + assertEquals( + expectedSize, actualSize, + "Size tree must decrease after removing the existing key" + ) + } + + @Test + fun `remove a non-existent key`() { + avlTree[0] = 15 + avlTree.remove(0) + + val expectedResult = null + val actualResult = avlTree.remove(0) + assertEquals( + expectedResult, actualResult, + "Remove a non-existent key must return null" + ) + } } From a0e4a9a9caa55ab44a21d1e4a00ec1a466a17f29 Mon Sep 17 00:00:00 2001 From: Azamat Ishbaev <143432879+odiumuniverse@users.noreply.github.com> Date: Sat, 23 Mar 2024 17:45:56 +0300 Subject: [PATCH 029/108] Delete .github/workflows/coverage.yml Do not work actions --- .github/workflows/coverage.yml | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 .github/workflows/coverage.yml diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml deleted file mode 100644 index 1225417..0000000 --- a/.github/workflows/coverage.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Test coverage - -on: - pull_request: - -jobs: - - collect_coverage: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: stevenleadbeater/kotlin-kover-action@v1.0.3 - id: kover-tests - with: - coverage-threshold: 80 - repo-token: ${{ secrets.GITHUB_TOKEN }} - proxy-url: https://add-pr-comment-proxy-94idvmwyie-uc.a.run.app - - name: Check coverage - if: ${{(steps.kover-tests.outputs.line-coverage) < 80}} - shell: bash - run: exit "Line coverage expected to be > 80 but was ${{steps.kover-tests.outputs.line-coverage}}" \ No newline at end of file From aaaf315d8b337ec7bf112915106cdc18732ea634 Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Mon, 25 Mar 2024 11:48:57 +0300 Subject: [PATCH 030/108] Fixed bug in balanceOnce method AVLTree, added tests for avl tree -balanceOnce was rotating wrong vertices in double rotates -added iterator test, changed already existed tests --- .../kotlin/bstrees/implementations/AVLTree.kt | 4 ++-- lib/src/test/kotlin/trees/AVLTreeTest.kt | 24 +++++++++++++++---- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt index 05381db..2673c6f 100644 --- a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt @@ -155,7 +155,7 @@ class AVLTree, V> : BalanceBSTreeTemplate, V> : BalanceBSTreeTemplate = Array(5, { i -> -i }) + val actualGet: Array = Array(5, { i -> avlTree.get(i) }) + assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") val expectedSize = 5 val actualSize = avlTree.size assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") @@ -95,4 +96,19 @@ class AVLTreeTest { "Remove a non-existent key must return null" ) } + + @Test + fun `simple iterator test`() { + val keys = intArrayOf(1, 7, 4, 9, 2, -44, 3) + val values = intArrayOf(19, 14, 31, 17, 12, -34, 0) + for (i in 0.. = arrayOf(-34, 19, 12, 0, 31, 14, 17) + val iterator = avlTree.iterator() + val actualResult: Array = Array(7, { i -> iterator.next().second }) + assertContentEquals(expectedResult, actualResult, "Iterator must return vertices in keys order") + + } } From 2888681c18f0985ac95186bd6a390d9faf0af4f3 Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Mon, 25 Mar 2024 13:12:32 +0300 Subject: [PATCH 031/108] Fixed visibility mofidiers for setters of vertices properties and roots --- lib/src/main/kotlin/bstrees/implementations/RBTree.kt | 2 +- .../main/kotlin/bstrees/implementations/Vertices.kt | 5 +++-- .../main/kotlin/bstrees/templates/BSTreeTemplate.kt | 3 ++- .../kotlin/bstrees/templates/BalanceBSTreeTemplate.kt | 1 - .../main/kotlin/bstrees/templates/VertexTemplate.kt | 11 +++++++++-- 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/src/main/kotlin/bstrees/implementations/RBTree.kt b/lib/src/main/kotlin/bstrees/implementations/RBTree.kt index 65a5cc9..eb89270 100644 --- a/lib/src/main/kotlin/bstrees/implementations/RBTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/RBTree.kt @@ -1,4 +1,4 @@ package bstrees.implementations class RBTree { -} \ No newline at end of file +} diff --git a/lib/src/main/kotlin/bstrees/implementations/Vertices.kt b/lib/src/main/kotlin/bstrees/implementations/Vertices.kt index e68d4b2..5264300 100644 --- a/lib/src/main/kotlin/bstrees/implementations/Vertices.kt +++ b/lib/src/main/kotlin/bstrees/implementations/Vertices.kt @@ -6,7 +6,7 @@ class SimpleVertex, V>(key: K, value: V) : VertexTemplate, V>(key: K, value: V) : VertexTemplate>(key, value) { var diffHeight: Int = 0 - set(value) { + internal set(value) { if (value !in -2..2) { throw IllegalArgumentException("difference of heights can't be out of [-2,2]") } @@ -16,9 +16,10 @@ class AVLVertex, V>(key: K, value: V) : VertexTemplate, V>(key: K, value: V) : VertexTemplate>(key, value) { var color: Color = Color.BLACK + internal set enum class Color { BLACK, RED } -} \ No newline at end of file +} diff --git a/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt b/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt index 8cc91cb..2d9a282 100644 --- a/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt +++ b/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt @@ -5,6 +5,7 @@ import javax.swing.text.StyledEditorKit.BoldAction abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate> { var root: Vertex_t? = null + protected set var size: Int = 0 protected set(value) { if (value >= 0) { @@ -150,4 +151,4 @@ abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate> : BSTreeTemplate() { } - diff --git a/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt b/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt index 1c4bddb..31a2ff9 100644 --- a/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt +++ b/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt @@ -1,9 +1,16 @@ package bstrees.templates -abstract class VertexTemplate, V, Vertex_t : VertexTemplate>(var key: K, var value: V) { +abstract class VertexTemplate, V, Vertex_t : VertexTemplate>(key: K, value: V) { + var key = key + internal set + var value = value + internal set var parent: Vertex_t? = null + internal set var left: Vertex_t? = null + internal set var right: Vertex_t? = null + internal set operator fun compareTo(other: VertexTemplate): Int { return key.compareTo(other.key) @@ -12,4 +19,4 @@ abstract class VertexTemplate, V, Vertex_t : VertexTemplate { return Pair(key, value) } -} \ No newline at end of file +} From 4c8d45e58fe091fe4cb8c465f3b637fe3c0a7cb1 Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Mon, 25 Mar 2024 21:55:18 +0300 Subject: [PATCH 032/108] Added test function for avl invariant check -added single rotates rotateRight and rotateLeft tests -after every test added check for all vertices diffHeights check -`bug in avl rotates functions still doesn't fixed (wrong diffHeights changing)` --- lib/src/test/kotlin/trees/AVLTreeTest.kt | 81 ++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 7 deletions(-) diff --git a/lib/src/test/kotlin/trees/AVLTreeTest.kt b/lib/src/test/kotlin/trees/AVLTreeTest.kt index e5e57dd..a6762c5 100644 --- a/lib/src/test/kotlin/trees/AVLTreeTest.kt +++ b/lib/src/test/kotlin/trees/AVLTreeTest.kt @@ -4,14 +4,40 @@ package trees import bstrees.implementations.AVLTree +import bstrees.implementations.AVLVertex +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import kotlin.test.assertContentEquals import kotlin.test.assertEquals +import kotlin.test.assertNotNull class AVLTreeTest { private lateinit var avlTree: AVLTree + /** + * Traverse all vertices of the tree and asserts that their diffHeights are + * equal to real difference of the subtrees. + * @return height of the subtree with the root at the specified [vertex] + */ + fun checkVertexInvariant(vertex: AVLVertex<*, *>?): Int { + if (vertex == null) return 0 + + val leftSubtreeHeight = checkVertexInvariant(vertex.left) + val rightSubtreeHeight = checkVertexInvariant(vertex.right) + val difference = leftSubtreeHeight - rightSubtreeHeight + assertTrue( + difference in -1..1, + "Difference in the heights of subtrees must be in [-1,1]" + ) + assertEquals( + difference, vertex.diffHeight, + "Property diffHeights must match real difference in the heights of subtrees (key = ${vertex.key})" + ) + return maxOf(checkVertexInvariant(vertex.left), checkVertexInvariant(vertex.right)) + 1 + } + @BeforeEach fun setup() { avlTree = AVLTree() @@ -21,7 +47,7 @@ class AVLTreeTest { fun `simple array test`() { val array = intArrayOf(0, 1, 2, 3, 4) for (i in array) { - avlTree.set(i, -i) + avlTree[i] = -i } val expectedGet: Array = Array(5, { i -> -i }) val actualGet: Array = Array(5, { i -> avlTree.get(i) }) @@ -29,15 +55,16 @@ class AVLTreeTest { val expectedSize = 5 val actualSize = avlTree.size assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") + checkVertexInvariant(avlTree.root) } @Test fun `size of avl tree with duplicate keys`() { for (i in 1..10) { - avlTree.set(i, 30 + i) + avlTree[i] = i + 30 } for (i in 6..10) { - avlTree.set(i, 0) + avlTree[i] = 0 } val expectedSize = 10 @@ -46,15 +73,16 @@ class AVLTreeTest { expectedSize, actualSize, "Size of the tree must not change after overwriting an existing key" ) + checkVertexInvariant(avlTree.root) } @Test fun `set keys twice`() { for (i in 1..10) { - avlTree.set(i, 30 + i) + avlTree[i] = 30 + i } for (i in 1..10) { - avlTree.set(i, 0) + avlTree[i] = 0 } val expectedSize = 10 @@ -63,6 +91,7 @@ class AVLTreeTest { expectedSize, actualSize, "Size of the tree must not change after overwriting an existing key" ) + checkVertexInvariant(avlTree.root) } @Test @@ -98,7 +127,7 @@ class AVLTreeTest { } @Test - fun `simple iterator test`() { + fun `simple iteration`() { val keys = intArrayOf(1, 7, 4, 9, 2, -44, 3) val values = intArrayOf(19, 14, 31, 17, 12, -34, 0) for (i in 0.. = arrayOf(-34, 19, 12, 0, 31, 14, 17) val iterator = avlTree.iterator() - val actualResult: Array = Array(7, { i -> iterator.next().second }) + val actualResult: Array = Array(7, { iterator.next().second }) assertContentEquals(expectedResult, actualResult, "Iterator must return vertices in keys order") + checkVertexInvariant(avlTree.root) + + } + + @Test + fun `rotate left`() { + val keys = intArrayOf(0, -1, 3, 2, 5, 6) + for (i in keys) avlTree[i] = i + + val expectedResult = Array(keys.size, { i -> avlTree[i] }) + val actualResult = Array(keys.size, { i -> avlTree[i] }) + assertContentEquals(expectedResult, actualResult, "Get must return corresponding value") + checkVertexInvariant(avlTree.root) + +// 0 3 +// / \ / \ +// -1 3 0 5 +// / \ --> / \ \ +// 2 5 -1 2 6 +// \ +// 6 + } + fun `rotate right`() { + val keys = intArrayOf(0, 1, -3, -2, -5, -6) + for (i in keys) avlTree[i] = i + + val expectedResult = Array(keys.size, { i -> avlTree[i] }) + val actualResult = Array(keys.size, { i -> avlTree[i] }) + assertContentEquals(expectedResult, actualResult, "Get must return corresponding value") + checkVertexInvariant(avlTree.root) + +// 0 -3 +// / \ / \ +// -3 1 -5 0 +// / \ --> / / \ +// -5 -2 -6 -2 1 +// / +// -6 } } From d9c7cc431ad80f800d318467470ff37951789ac5 Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Tue, 26 Mar 2024 13:34:01 +0300 Subject: [PATCH 033/108] Fix 2 bugs in rotation and remove methods in AVLTree, add tests -Fix bug in rotations method: was incorrect updates height difference (only for cases with diffHeight -2 and 2) -Add exceptions when left.diffHeight = -1 and right.diffHeight = 1 for right and left rotations respectively -Fix bug in balanceAfterRemove method: was incorrect condition for continue balance upper vertices -Add 4 tests for single rotations --- .../kotlin/bstrees/implementations/AVLTree.kt | 99 +++++++++++++--- lib/src/test/kotlin/trees/AVLTreeTest.kt | 112 +++++++++++++----- 2 files changed, 164 insertions(+), 47 deletions(-) diff --git a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt index 2673c6f..3100721 100644 --- a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt @@ -129,14 +129,15 @@ class AVLTree, V> : BalanceBSTreeTemplate?) { var cur = vertex ?: return - while (cur.diffHeight != 0) { + while (cur.diffHeight != 1 && cur.diffHeight != -1) { cur = balanceOnce(cur) - if (cur.diffHeight != 0) { + if (cur.diffHeight != 1 && cur.diffHeight != -1) { when { cur.parent?.left == cur -> cur.parent?.let { it.diffHeight -= 1 } cur.parent?.right == cur -> cur.parent?.let { it.diffHeight += 1 } } } + cur = cur.parent ?: return } } @@ -175,7 +176,7 @@ class AVLTree, V> : BalanceBSTreeTemplate): AVLVertex { val left = origin.left - ?: throw IllegalStateException("difference of heights can't be 2 if left Vertex doesn't exist") + ?: throw IllegalStateException("Height difference can't be 2 if left Vertex doesn't exist") left.parent = origin.parent if (origin.parent?.left == origin) origin.parent?.left = left @@ -186,13 +187,46 @@ class AVLTree, V> : BalanceBSTreeTemplate { + when (left.diffHeight) { + 0 -> { + origin.diffHeight = 1 + left.diffHeight = -1 + } + + 1 -> { + origin.diffHeight = 0 + left.diffHeight = 0 + } + + else -> throw IllegalStateException( + "Right rotate is possible only when left subtree diffHeight in [0,1]" + ) + } + } + + 1 -> { + when (left.diffHeight) { + 0 -> { + origin.diffHeight = 0 + left.diffHeight = -1 + } + + 1 -> { + origin.diffHeight = -1 + left.diffHeight = -1 + + } + + else -> throw IllegalStateException( + "Right rotate is possible only when left subtree diffHeight in [0,1]" + ) + + } + } } + if (origin == root) { root = left } @@ -201,7 +235,7 @@ class AVLTree, V> : BalanceBSTreeTemplate): AVLVertex { val right = origin.right - ?: throw IllegalStateException("difference of heights can't be 2 if left Vertex doesn't exist") + ?: throw IllegalStateException("Height difference can't be 2 if left Vertex doesn't exist") right.parent = origin.parent if (origin.parent?.left == origin) origin.parent?.left = right @@ -212,13 +246,46 @@ class AVLTree, V> : BalanceBSTreeTemplate { + when (right.diffHeight) { + 0 -> { + origin.diffHeight = -1 + right.diffHeight = 1 + } + + -1 -> { + origin.diffHeight = 0 + right.diffHeight = 0 + } + + else -> throw IllegalStateException( + "Left rotate is possible only when right subtree diffHeight in [-1,0]" + ) + } + } + + -1 -> { + when (right.diffHeight) { + 0 -> { + origin.diffHeight = 0 + right.diffHeight = 1 + } + + 1 -> { + origin.diffHeight = 1 + right.diffHeight = 1 + + } + + else -> throw IllegalStateException( + "Left rotate is possible only when right subtree diffHeight in [-1,0]" + ) + + } + } } + if (origin == root) { root = right } diff --git a/lib/src/test/kotlin/trees/AVLTreeTest.kt b/lib/src/test/kotlin/trees/AVLTreeTest.kt index a6762c5..73c82d5 100644 --- a/lib/src/test/kotlin/trees/AVLTreeTest.kt +++ b/lib/src/test/kotlin/trees/AVLTreeTest.kt @@ -5,20 +5,18 @@ package trees import bstrees.implementations.AVLTree import bstrees.implementations.AVLVertex -import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import kotlin.test.assertContentEquals import kotlin.test.assertEquals -import kotlin.test.assertNotNull class AVLTreeTest { private lateinit var avlTree: AVLTree /** * Traverse all vertices of the tree and asserts that their diffHeights are - * equal to real difference of the subtrees. + * equal to real height difference of the subtrees. * @return height of the subtree with the root at the specified [vertex] */ fun checkVertexInvariant(vertex: AVLVertex<*, *>?): Int { @@ -29,11 +27,11 @@ class AVLTreeTest { val difference = leftSubtreeHeight - rightSubtreeHeight assertTrue( difference in -1..1, - "Difference in the heights of subtrees must be in [-1,1]" + "Height difference of subtrees must be in [-1,1]" ) assertEquals( difference, vertex.diffHeight, - "Property diffHeights must match real difference in the heights of subtrees (key = ${vertex.key})" + "Property diffHeights must match real Height difference of subtrees (key = ${vertex.key})" ) return maxOf(checkVertexInvariant(vertex.left), checkVertexInvariant(vertex.right)) + 1 } @@ -143,39 +141,91 @@ class AVLTreeTest { } @Test - fun `rotate left`() { - val keys = intArrayOf(0, -1, 3, 2, 5, 6) - for (i in keys) avlTree[i] = i + fun `rotate left, right diffHeight = -1`() { + val keys = intArrayOf(0, -1, 2, 1, 3, 4) + for (key in keys) avlTree[key] = key - val expectedResult = Array(keys.size, { i -> avlTree[i] }) - val actualResult = Array(keys.size, { i -> avlTree[i] }) - assertContentEquals(expectedResult, actualResult, "Get must return corresponding value") + val expectedResult = Array(keys.size, { i -> keys[i] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, actualResult, + "Get must return corresponding values after left rotate ( right.diffHeight = -1)" + ) checkVertexInvariant(avlTree.root) -// 0 3 -// / \ / \ -// -1 3 0 5 -// / \ --> / \ \ -// 2 5 -1 2 6 -// \ -// 6 +// 0 0 2 +// / \ / \ / \ +// -1 2 -1 2 0 3 +// / \ --> / \ --> / \ \ +// 1 3 1 3 -1 1 4 +// \ +// 4 } - fun `rotate right`() { - val keys = intArrayOf(0, 1, -3, -2, -5, -6) - for (i in keys) avlTree[i] = i + @Test + fun `rotate left, right diffHeiht = 0`() { + val keys = intArrayOf(0, -1, 4, 2, 6, -2, 1, 3, 5, 7) + for (key in keys) avlTree[key] = key + avlTree.remove(-2) + + val expectedResult = arrayOf(0, -1, 4, 2, 6, null, 1, 3, 5, 7) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, actualResult, + "Get must return corresponding values after left rotate (right.diffHeight = 0)" + ) + checkVertexInvariant(avlTree.root) +// 0 0 4 +// / \ / \ / \ +// -1 4 -1 4 0 6 +// / / \ --> / \ --> / \ / \ +// -2 2 6 2 6 -1 2 5 7 +// / \ / \ / \ / \ / \ +// 1 3 5 7 1 3 5 7 1 3 + } + + @Test + fun `rotate right, left diffHeight = 1`() { + val keys = intArrayOf(0, 1, -1, -3, -2, -4) + for (key in keys) avlTree[key] = key + + val expectedResult = Array(keys.size, { i -> keys[i] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, actualResult, + "Get must return corresponding values after right rotate (left.diffHeight = 1)" + ) + checkVertexInvariant(avlTree.root) - val expectedResult = Array(keys.size, { i -> avlTree[i] }) - val actualResult = Array(keys.size, { i -> avlTree[i] }) - assertContentEquals(expectedResult, actualResult, "Get must return corresponding value") +// 0 0 -1 +// / \ / \ / \ +// -1 1 -1 1 -3 0 +// / \ --> / \ --> / / \ +// -3 -2 -3 -2 -4 -2 1 +// / +// -4 + } + + @Test + fun `rotate right, left diffHeight = 0`() { + val keys = intArrayOf(7, 3, 8, 9, 1, 5, 0, 2, 4, 6) + for (key in keys) avlTree[key] = key + avlTree.remove(9) + + val expectedResult = arrayOf(7, 3, 8, null, 1, 5, 0, 2, 4, 6) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, actualResult, + "Get must return corresponding values after right rotate (left.diffHeight = 0)" + ) checkVertexInvariant(avlTree.root) -// 0 -3 -// / \ / \ -// -3 1 -5 0 -// / \ --> / / \ -// -5 -2 -6 -2 1 -// / -// -6 +// 7 7 3 +// / \ / \ / \ +// 3 8 3 8 1 7 +// / \ \ --> / \ --> / \ / \ +// 1 5 9 1 5 0 2 5 8 +// / \ / \ / \ / \ / \ +// 0 2 4 6 0 2 4 6 4 6 } } From 51d137aeca46773e3726419c6083da1dcd88c8b0 Mon Sep 17 00:00:00 2001 From: OGchukh Date: Tue, 26 Mar 2024 07:31:00 -0400 Subject: [PATCH 034/108] add: unbalanced set for RBTree --- .../kotlin/bstrees/implementations/RBTree.kt | 48 ++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/bstrees/implementations/RBTree.kt b/lib/src/main/kotlin/bstrees/implementations/RBTree.kt index c1c9ef5..128289e 100644 --- a/lib/src/main/kotlin/bstrees/implementations/RBTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/RBTree.kt @@ -1,3 +1,49 @@ package bstrees.implementations -class RBTree +import bstrees.templates.BalanceBSTreeTemplate + +class RBTree, V> : BalanceBSTreeTemplate>() { + override fun set(key: K, value: V): V? { + val (currentVert, returnResult) = unbalancedSet(key, value) + //balance(currentVert) + return returnResult + } + private fun unbalancedSet(key: K, value: V): Pair, V?> { + if (root == null){ + val newVertex = RBVertex(key, value) + root = newVertex + size += 1 + return Pair(newVertex, null) + } + var currentVertex = root ?: throw IllegalStateException() + while (true){ + val result = currentVertex.key.compareTo(key) + if (result < 0){ + if(currentVertex.left == null){ + val newVertex = RBVertex(key, value) + currentVertex.left = newVertex + newVertex.parent = currentVertex + size+= 1 + return Pair(newVertex, null) + } + currentVertex = currentVertex.left ?: throw IllegalStateException() + } else if (result > 0){ + if (currentVertex.right == null){ + val newVertex = RBVertex(key, value) + currentVertex.right = newVertex + newVertex.parent = currentVertex + size += 1 + return Pair(newVertex, null) + } + currentVertex = currentVertex.right ?: throw IllegalStateException() + } else{ + val oldValue = currentVertex.value + currentVertex.value = value + return Pair(currentVertex, oldValue) + } + } + } + override fun remove(key: K): V?{ + return null + } +} From 8ae91ea7818e70055712b75c0433cdbf305d0e12 Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Tue, 26 Mar 2024 15:22:17 +0300 Subject: [PATCH 035/108] Add remove tests for avl tree --- lib/src/test/kotlin/trees/AVLTreeTest.kt | 105 ++++++++++++++++++++--- 1 file changed, 92 insertions(+), 13 deletions(-) diff --git a/lib/src/test/kotlin/trees/AVLTreeTest.kt b/lib/src/test/kotlin/trees/AVLTreeTest.kt index 73c82d5..99d95aa 100644 --- a/lib/src/test/kotlin/trees/AVLTreeTest.kt +++ b/lib/src/test/kotlin/trees/AVLTreeTest.kt @@ -19,11 +19,11 @@ class AVLTreeTest { * equal to real height difference of the subtrees. * @return height of the subtree with the root at the specified [vertex] */ - fun checkVertexInvariant(vertex: AVLVertex<*, *>?): Int { + fun checkTreeInvariant(vertex: AVLVertex<*, *>?): Int { if (vertex == null) return 0 - val leftSubtreeHeight = checkVertexInvariant(vertex.left) - val rightSubtreeHeight = checkVertexInvariant(vertex.right) + val leftSubtreeHeight = checkTreeInvariant(vertex.left) + val rightSubtreeHeight = checkTreeInvariant(vertex.right) val difference = leftSubtreeHeight - rightSubtreeHeight assertTrue( difference in -1..1, @@ -33,7 +33,7 @@ class AVLTreeTest { difference, vertex.diffHeight, "Property diffHeights must match real Height difference of subtrees (key = ${vertex.key})" ) - return maxOf(checkVertexInvariant(vertex.left), checkVertexInvariant(vertex.right)) + 1 + return maxOf(checkTreeInvariant(vertex.left), checkTreeInvariant(vertex.right)) + 1 } @BeforeEach @@ -53,7 +53,7 @@ class AVLTreeTest { val expectedSize = 5 val actualSize = avlTree.size assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") - checkVertexInvariant(avlTree.root) + checkTreeInvariant(avlTree.root) } @Test @@ -71,7 +71,7 @@ class AVLTreeTest { expectedSize, actualSize, "Size of the tree must not change after overwriting an existing key" ) - checkVertexInvariant(avlTree.root) + checkTreeInvariant(avlTree.root) } @Test @@ -89,7 +89,7 @@ class AVLTreeTest { expectedSize, actualSize, "Size of the tree must not change after overwriting an existing key" ) - checkVertexInvariant(avlTree.root) + checkTreeInvariant(avlTree.root) } @Test @@ -107,10 +107,89 @@ class AVLTreeTest { ) assertEquals( expectedSize, actualSize, - "Size tree must decrease after removing the existing key" + "Size of the tree must decrease after removing the existing key" ) } + @Test + fun `remove with left vertex`() { + val keys = intArrayOf(0, -1, 1, -2) + for (key in keys) avlTree[key] = key + avlTree.remove(-1) + + val expectedResult = arrayOf(0, null, 1, -2) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, actualResult, + "Tree must save all other vertices after remove vertex with existing left vertex" + ) + checkTreeInvariant(avlTree.root) + } + + @Test + fun `remove with right subtree of height 1`() { + val keys = intArrayOf(0, -1, 3, 1, 2) + for (key in keys) avlTree[key] = key + avlTree.remove(3) + + val expectedResult = arrayOf(0, -1, null, 1, 2) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, actualResult, + "Tree must save all other vertices after remove vertex with right subtree of height 1" + ) + checkTreeInvariant(avlTree.root) + } + + @Test + fun `remove with right subtree of height more than 1`() { + val keys = intArrayOf(0, -1, 3, -2, 1, 6, 4, 7) + for (key in keys) avlTree[key] = key + avlTree.remove(3) + + val expectedResult = arrayOf(0, -1, null, -2, 1, 6, 4, 7) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, actualResult, + "Tree must save all other vertices after remove vertex with right subtree of height >1" + ) + checkTreeInvariant(avlTree.root) + avlTree[5] = 5 + checkTreeInvariant(avlTree.root) + } + + @Test + fun `remove with necessary double rotate`() { + val keys = intArrayOf(5, 0, 7, -1, 2, 6, 9, -2, 1, 3, 8, 4) + for (key in keys) avlTree[key] = key + avlTree.remove(7) + + val expectedResult = arrayOf(5, 0, null, -1, 2, 6, 9, -2, 1, 3, 8, 4) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, actualResult, + "Tree must save all other vertices after remove that creates unbalance situation" + ) + checkTreeInvariant(avlTree.root) + } + + @Test + fun `remove root with double rotate`() { + val keys = intArrayOf(4, 1, 6, 0, 3, 5, 2) + for (key in keys) avlTree[key] = key + avlTree.remove(4) + + assertTrue(avlTree.root != null) + val expectedResult = arrayOf(null, 1, 6, 0, 3, 5, 2) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, actualResult, + "Tree must save all other vertices after root remove" + ) + checkTreeInvariant(avlTree.root) + + } + @Test fun `remove a non-existent key`() { avlTree[0] = 15 @@ -136,7 +215,7 @@ class AVLTreeTest { val iterator = avlTree.iterator() val actualResult: Array = Array(7, { iterator.next().second }) assertContentEquals(expectedResult, actualResult, "Iterator must return vertices in keys order") - checkVertexInvariant(avlTree.root) + checkTreeInvariant(avlTree.root) } @@ -151,7 +230,7 @@ class AVLTreeTest { expectedResult, actualResult, "Get must return corresponding values after left rotate ( right.diffHeight = -1)" ) - checkVertexInvariant(avlTree.root) + checkTreeInvariant(avlTree.root) // 0 0 2 // / \ / \ / \ @@ -174,7 +253,7 @@ class AVLTreeTest { expectedResult, actualResult, "Get must return corresponding values after left rotate (right.diffHeight = 0)" ) - checkVertexInvariant(avlTree.root) + checkTreeInvariant(avlTree.root) // 0 0 4 // / \ / \ / \ // -1 4 -1 4 0 6 @@ -195,7 +274,7 @@ class AVLTreeTest { expectedResult, actualResult, "Get must return corresponding values after right rotate (left.diffHeight = 1)" ) - checkVertexInvariant(avlTree.root) + checkTreeInvariant(avlTree.root) // 0 0 -1 // / \ / \ / \ @@ -218,7 +297,7 @@ class AVLTreeTest { expectedResult, actualResult, "Get must return corresponding values after right rotate (left.diffHeight = 0)" ) - checkVertexInvariant(avlTree.root) + checkTreeInvariant(avlTree.root) // 7 7 3 // / \ / \ / \ From 1e3021359f6fffb7c03f3af362ba78941c03f0fd Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Tue, 26 Mar 2024 16:36:31 +0300 Subject: [PATCH 036/108] Fix bug in double rotations of avl tree -Removed exceptions when left.diffHeight = -1 and right.diffHeight = 1 for right and left rotations respectively. This situations were considered as Exceptions although they were correct and necessary in some double rotations. Add diffHeight changing for this cases. --- .../kotlin/bstrees/implementations/AVLTree.kt | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt index 3100721..98bbdd5 100644 --- a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt @@ -166,7 +166,7 @@ class AVLTree, V> : BalanceBSTreeTemplate, V> : BalanceBSTreeTemplate throw IllegalStateException( - "Right rotate is possible only when left subtree diffHeight in [0,1]" - ) + 2 -> { + origin.diffHeight = -1 + left.diffHeight = 0 + } } } @@ -219,9 +220,10 @@ class AVLTree, V> : BalanceBSTreeTemplate throw IllegalStateException( - "Right rotate is possible only when left subtree diffHeight in [0,1]" - ) + -1 -> { + origin.diffHeight = 0 + left.diffHeight = -2 + } } } @@ -259,9 +261,10 @@ class AVLTree, V> : BalanceBSTreeTemplate throw IllegalStateException( - "Left rotate is possible only when right subtree diffHeight in [-1,0]" - ) + -2 -> { + origin.diffHeight = 1 + right.diffHeight = 0 + } } } @@ -272,15 +275,16 @@ class AVLTree, V> : BalanceBSTreeTemplate { + -1 -> { origin.diffHeight = 1 right.diffHeight = 1 } - else -> throw IllegalStateException( - "Left rotate is possible only when right subtree diffHeight in [-1,0]" - ) + 1 -> { + origin.diffHeight = 0 + right.diffHeight = 2 + } } } From cefb90b43ca2fb379f681c5ec55a2c697f0b87af Mon Sep 17 00:00:00 2001 From: Ycyken Date: Tue, 26 Mar 2024 14:34:01 +0000 Subject: [PATCH 037/108] [MegaLinter] Apply linters fixes --- .../kotlin/bstrees/implementations/AVLTree.kt | 31 +- .../kotlin/bstrees/implementations/RBTree.kt | 3 +- .../bstrees/implementations/SimpleTree.kt | 7 +- .../templates/BalanceBSTreeTemplate.kt | 3 +- lib/src/test/kotlin/trees/AVLTreeTest.kt | 79 ++--- .../linters_logs/SUCCESS-KOTLIN_KTLINT.log | 6 +- megalinter-reports/megalinter.log | 16 +- .../kotlin/bstrees/implementations/AVLTree.kt | 235 ++++++++++++--- .../bstrees/implementations/SimpleTree.kt | 67 ++++- .../lib/src/test/kotlin/trees/AVLTreeTest.kt | 279 +++++++++++++++++- .../linters_logs/SUCCESS-KOTLIN_KTLINT.log | 12 + .../megalinter-reports/megalinter.log | 57 ++++ 12 files changed, 670 insertions(+), 125 deletions(-) create mode 100644 megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log create mode 100644 megalinter-reports/updated_sources/megalinter-reports/megalinter.log diff --git a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt index 9e86a8b..77f2377 100644 --- a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt @@ -3,8 +3,10 @@ package bstrees.implementations import bstrees.templates.BalanceBSTreeTemplate class AVLTree, V> : BalanceBSTreeTemplate>() { - - public override operator fun set(key: K, value: V): V? { + public override operator fun set( + key: K, + value: V, + ): V? { val (currentVert, oldValue) = setWithoutBalance(key, value) if (oldValue == null) { size += 1 @@ -19,7 +21,10 @@ class AVLTree, V> : BalanceBSTreeTemplate, V?> { + private fun setWithoutBalance( + key: K, + value: V, + ): Pair, V?> { if (root == null) { val newVertex = AVLVertex(key, value) root = newVertex @@ -115,8 +120,9 @@ class AVLTree, V> : BalanceBSTreeTemplate parent.diffHeight += 1 } } else { - val minRight = minVertex(toRemove.right) - ?: throw IllegalStateException("min of subtree can't be null if it's contains at least one element") + val minRight = + minVertex(toRemove.right) + ?: throw IllegalStateException("min of subtree can't be null if it's contains at least one element") toRemove.key = minRight.key toRemove.value = minRight.value removeVert(minRight) @@ -160,7 +166,6 @@ class AVLTree, V> : BalanceBSTreeTemplate, V> : BalanceBSTreeTemplate): AVLVertex { - val left = origin.left - ?: throw IllegalStateException("Height difference can't be 2 if left Vertex doesn't exist") + val left = + origin.left + ?: throw IllegalStateException("Height difference can't be 2 if left Vertex doesn't exist") left.parent = origin.parent if (origin.parent?.left == origin) { @@ -220,14 +226,12 @@ class AVLTree, V> : BalanceBSTreeTemplate { origin.diffHeight = -1 left.diffHeight = -1 - } -1 -> { origin.diffHeight = 0 left.diffHeight = -2 } - } } } @@ -239,8 +243,9 @@ class AVLTree, V> : BalanceBSTreeTemplate): AVLVertex { - val right = origin.right - ?: throw IllegalStateException("Height difference can't be 2 if left Vertex doesn't exist") + val right = + origin.right + ?: throw IllegalStateException("Height difference can't be 2 if left Vertex doesn't exist") right.parent = origin.parent if (origin.parent?.left == origin) { @@ -284,14 +289,12 @@ class AVLTree, V> : BalanceBSTreeTemplate { origin.diffHeight = 1 right.diffHeight = 1 - } 1 -> { origin.diffHeight = 0 right.diffHeight = 2 } - } } } diff --git a/lib/src/main/kotlin/bstrees/implementations/RBTree.kt b/lib/src/main/kotlin/bstrees/implementations/RBTree.kt index eb89270..c1c9ef5 100644 --- a/lib/src/main/kotlin/bstrees/implementations/RBTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/RBTree.kt @@ -1,4 +1,3 @@ package bstrees.implementations -class RBTree { -} +class RBTree diff --git a/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt b/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt index 9043dc9..eae8bf1 100644 --- a/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt @@ -3,7 +3,6 @@ package bstrees.implementations import bstrees.templates.BSTreeTemplate class SimpleTree, V> : BSTreeTemplate>() { - override fun remove(key: K): V? { val vertex = vertByKey(key) ?: return null val parent = vertex.parent @@ -36,8 +35,10 @@ class SimpleTree, V> : BSTreeTemplate return oldValue } - override operator fun set(key: K, value: V): V? { - + override operator fun set( + key: K, + value: V, + ): V? { if (root == null) { val vertex = SimpleVertex(key, value) root = vertex diff --git a/lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt b/lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt index 8dc8626..1c2cb99 100644 --- a/lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt +++ b/lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt @@ -1,5 +1,4 @@ package bstrees.templates abstract class BalanceBSTreeTemplate, V, Vertex_t : VertexTemplate> : - BSTreeTemplate() { -} + BSTreeTemplate() diff --git a/lib/src/test/kotlin/trees/AVLTreeTest.kt b/lib/src/test/kotlin/trees/AVLTreeTest.kt index 99d95aa..712bf2d 100644 --- a/lib/src/test/kotlin/trees/AVLTreeTest.kt +++ b/lib/src/test/kotlin/trees/AVLTreeTest.kt @@ -27,11 +27,12 @@ class AVLTreeTest { val difference = leftSubtreeHeight - rightSubtreeHeight assertTrue( difference in -1..1, - "Height difference of subtrees must be in [-1,1]" + "Height difference of subtrees must be in [-1,1]", ) assertEquals( - difference, vertex.diffHeight, - "Property diffHeights must match real Height difference of subtrees (key = ${vertex.key})" + difference, + vertex.diffHeight, + "Property diffHeights must match real Height difference of subtrees (key = ${vertex.key})", ) return maxOf(checkTreeInvariant(vertex.left), checkTreeInvariant(vertex.right)) + 1 } @@ -68,8 +69,9 @@ class AVLTreeTest { val expectedSize = 10 val actualSize = avlTree.size assertEquals( - expectedSize, actualSize, - "Size of the tree must not change after overwriting an existing key" + expectedSize, + actualSize, + "Size of the tree must not change after overwriting an existing key", ) checkTreeInvariant(avlTree.root) } @@ -86,8 +88,9 @@ class AVLTreeTest { val expectedSize = 10 val actualSize = avlTree.size assertEquals( - expectedSize, actualSize, - "Size of the tree must not change after overwriting an existing key" + expectedSize, + actualSize, + "Size of the tree must not change after overwriting an existing key", ) checkTreeInvariant(avlTree.root) } @@ -102,12 +105,14 @@ class AVLTreeTest { val actualSize = avlTree.size assertEquals( - expectedResult, actualResult, - "Remove must return removed value" + expectedResult, + actualResult, + "Remove must return removed value", ) assertEquals( - expectedSize, actualSize, - "Size of the tree must decrease after removing the existing key" + expectedSize, + actualSize, + "Size of the tree must decrease after removing the existing key", ) } @@ -120,8 +125,9 @@ class AVLTreeTest { val expectedResult = arrayOf(0, null, 1, -2) val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( - expectedResult, actualResult, - "Tree must save all other vertices after remove vertex with existing left vertex" + expectedResult, + actualResult, + "Tree must save all other vertices after remove vertex with existing left vertex", ) checkTreeInvariant(avlTree.root) } @@ -135,8 +141,9 @@ class AVLTreeTest { val expectedResult = arrayOf(0, -1, null, 1, 2) val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( - expectedResult, actualResult, - "Tree must save all other vertices after remove vertex with right subtree of height 1" + expectedResult, + actualResult, + "Tree must save all other vertices after remove vertex with right subtree of height 1", ) checkTreeInvariant(avlTree.root) } @@ -150,8 +157,9 @@ class AVLTreeTest { val expectedResult = arrayOf(0, -1, null, -2, 1, 6, 4, 7) val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( - expectedResult, actualResult, - "Tree must save all other vertices after remove vertex with right subtree of height >1" + expectedResult, + actualResult, + "Tree must save all other vertices after remove vertex with right subtree of height >1", ) checkTreeInvariant(avlTree.root) avlTree[5] = 5 @@ -167,8 +175,9 @@ class AVLTreeTest { val expectedResult = arrayOf(5, 0, null, -1, 2, 6, 9, -2, 1, 3, 8, 4) val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( - expectedResult, actualResult, - "Tree must save all other vertices after remove that creates unbalance situation" + expectedResult, + actualResult, + "Tree must save all other vertices after remove that creates unbalance situation", ) checkTreeInvariant(avlTree.root) } @@ -183,11 +192,11 @@ class AVLTreeTest { val expectedResult = arrayOf(null, 1, 6, 0, 3, 5, 2) val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( - expectedResult, actualResult, - "Tree must save all other vertices after root remove" + expectedResult, + actualResult, + "Tree must save all other vertices after root remove", ) checkTreeInvariant(avlTree.root) - } @Test @@ -198,8 +207,9 @@ class AVLTreeTest { val expectedResult = null val actualResult = avlTree.remove(0) assertEquals( - expectedResult, actualResult, - "Remove a non-existent key must return null" + expectedResult, + actualResult, + "Remove a non-existent key must return null", ) } @@ -216,7 +226,6 @@ class AVLTreeTest { val actualResult: Array = Array(7, { iterator.next().second }) assertContentEquals(expectedResult, actualResult, "Iterator must return vertices in keys order") checkTreeInvariant(avlTree.root) - } @Test @@ -227,8 +236,9 @@ class AVLTreeTest { val expectedResult = Array(keys.size, { i -> keys[i] }) val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( - expectedResult, actualResult, - "Get must return corresponding values after left rotate ( right.diffHeight = -1)" + expectedResult, + actualResult, + "Get must return corresponding values after left rotate ( right.diffHeight = -1)", ) checkTreeInvariant(avlTree.root) @@ -250,8 +260,9 @@ class AVLTreeTest { val expectedResult = arrayOf(0, -1, 4, 2, 6, null, 1, 3, 5, 7) val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( - expectedResult, actualResult, - "Get must return corresponding values after left rotate (right.diffHeight = 0)" + expectedResult, + actualResult, + "Get must return corresponding values after left rotate (right.diffHeight = 0)", ) checkTreeInvariant(avlTree.root) // 0 0 4 @@ -271,8 +282,9 @@ class AVLTreeTest { val expectedResult = Array(keys.size, { i -> keys[i] }) val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( - expectedResult, actualResult, - "Get must return corresponding values after right rotate (left.diffHeight = 1)" + expectedResult, + actualResult, + "Get must return corresponding values after right rotate (left.diffHeight = 1)", ) checkTreeInvariant(avlTree.root) @@ -294,8 +306,9 @@ class AVLTreeTest { val expectedResult = arrayOf(7, 3, 8, null, 1, 5, 0, 2, 4, 6) val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( - expectedResult, actualResult, - "Get must return corresponding values after right rotate (left.diffHeight = 0)" + expectedResult, + actualResult, + "Get must return corresponding values after right rotate (left.diffHeight = 0)", ) checkTreeInvariant(avlTree.root) diff --git a/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log b/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log index 888ca70..9913267 100644 --- a/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log +++ b/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log @@ -5,8 +5,8 @@ See documentation on https://megalinter.io/7.10.0/descriptors/kotlin_ktlint/ ✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/AVLTree.kt - FIXED ✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/RBTree.kt - FIXED ✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt - FIXED -✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/Vertices.kt - FIXED -✅ [SUCCESS] lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt - FIXED +✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/Vertices.kt +✅ [SUCCESS] lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt ✅ [SUCCESS] lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt - FIXED -✅ [SUCCESS] lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt - FIXED +✅ [SUCCESS] lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt ✅ [SUCCESS] lib/src/test/kotlin/trees/AVLTreeTest.kt - FIXED diff --git a/megalinter-reports/megalinter.log b/megalinter-reports/megalinter.log index ac06d2a..a2359ee 100644 --- a/megalinter-reports/megalinter.log +++ b/megalinter-reports/megalinter.log @@ -11,8 +11,8 @@ The MegaLinter documentation can be found at: ::group::MegaLinter initialization (expand for details) MegaLinter will analyze workspace [/github/workspace] GITHUB_REPOSITORY: spbu-coding-2023/trees-8 -GITHUB_REF: refs/pull/4/merge -GITHUB_RUN_ID: 8385423086 +GITHUB_REF: refs/pull/10/merge +GITHUB_RUN_ID: 8437735818 CLOJURE_CLJSTYLE has been temporary disabled in MegaLinter, please use a previous MegaLinter version or wait for the next one ! @@ -23,7 +23,6 @@ To receive reports as email, please set variable EMAIL_REPORTER_EMAIL ::group::MegaLinter now collects the files to analyse (expand for details) Listing updated files in [/github/workspace] using git diff. Modified files: -.github/workflows/CI_Test.yml lib/src/main/kotlin/bstrees/implementations/AVLTree.kt lib/src/main/kotlin/bstrees/implementations/RBTree.kt lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt @@ -31,9 +30,8 @@ lib/src/main/kotlin/bstrees/implementations/Vertices.kt lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt -lib/src/main/kotlin/org/example/Library.kt -lib/src/test/kotlin/org/example/LibraryTest.kt lib/src/test/kotlin/trees/AVLTreeTest.kt +megalinter-reports/megalinter.log - File extensions: .kt, .kts - Excluding .gitignored files [0]: Kept [8] files on [9] found files @@ -44,7 +42,7 @@ Kept [8] files on [9] found files | KOTLIN | ktlint | .kt|.kts | 8 | yes | +------------+--------+----------+----------------+------------+ ::endgroup:: -::group::✅ Linted [KOTLIN] files with [ktlint] successfully - (10.1s) (expand for details) +::group::✅ Linted [KOTLIN] files with [ktlint] successfully - (11.15s) (expand for details) - Using [ktlint v1.2.1] https://megalinter.io/7.10.0/descriptors/kotlin_ktlint - MegaLinter key: [KOTLIN_KTLINT] - Rules config: identified by [ktlint] @@ -54,10 +52,10 @@ Kept [8] files on [9] found files +----SUMMARY-+--------+------+-------+-------+--------+--------------+ | Descriptor | Linter | Mode | Files | Fixed | Errors | Elapsed time | +------------+--------+------+-------+-------+--------+--------------+ -| ✅ KOTLIN | ktlint | file | 8 | 8 | 0 | 10.1s | +| ✅ KOTLIN | ktlint | file | 8 | 5 | 0 | 11.15s | +------------+--------+------+-------+-------+--------+--------------+ -[Updated Sources Reporter] copied 8 fixed source files in folder /github/workspace/megalinter-reports/updated_sources. +[Updated Sources Reporter] copied 7 fixed source files in folder /github/workspace/megalinter-reports/updated_sources. Download it from artifacts then copy-paste it in your local repo to apply linters updates -[GitHub Comment Reporter] Posted summary as comment on spbu-coding-2023/trees-8 #PR4 +[GitHub Comment Reporter] Posted summary as comment on spbu-coding-2023/trees-8 #PR10 ✅ Successfully linted all files without errors diff --git a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt index f16468c..77f2377 100644 --- a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt +++ b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt @@ -3,15 +3,24 @@ package bstrees.implementations import bstrees.templates.BalanceBSTreeTemplate class AVLTree, V> : BalanceBSTreeTemplate>() { - public override fun set( + public override operator fun set( key: K, value: V, ): V? { - val (currentVert, returnResult) = setWithoutBalance(key, value) - balance(currentVert) - return returnResult + val (currentVert, oldValue) = setWithoutBalance(key, value) + if (oldValue == null) { + size += 1 + balanceAfterSet(currentVert) + } + return oldValue } + /** + * Set specified value by specified key + * + * Returns: a pair of set vertex and old value. + * If key didn't exist, the returned value is null. + */ private fun setWithoutBalance( key: K, value: V, @@ -19,7 +28,6 @@ class AVLTree, V> : BalanceBSTreeTemplate, V> : BalanceBSTreeTemplate, V> : BalanceBSTreeTemplate, V> : BalanceBSTreeTemplate) { + /** + * Climbing up the tree, updates diffHeights of vertices after set and calls + * [balanceOnce] if vertex became unbalanced + */ + private fun balanceAfterSet(vertex: AVLVertex) { var cur = vertex var prevKey = cur.key while (cur.parent != null) { @@ -64,27 +74,76 @@ class AVLTree, V> : BalanceBSTreeTemplate= 0) { - cur = rotateRight(cur) - } else if (getDiffHeight(cur.left) == -1) { - cur.left?.let { - cur = rotateLeft(it) - cur = rotateRight(cur) - } + cur = balanceOnce(cur) + if (cur.diffHeight == 0) break + } + } + + public override fun remove(key: K): V? { + val toRemove = vertByKey(key) ?: return null + val oldValue = toRemove.value + removeVert(toRemove) + size -= 1 + return oldValue + } + + /** + * Removes specified vertex and balances the tree + */ + private fun removeVert(toRemove: AVLVertex) { + val parent = toRemove.parent + if (toRemove.left == null && toRemove.right == null) { + when { + parent == null -> root = null + + parent.left == toRemove -> { + parent.left = null + parent.diffHeight -= 1 } - } else if (cur.diffHeight == -2) { - if (getDiffHeight(cur.right) <= 0) { - cur = rotateLeft(cur) - } else if (getDiffHeight(cur.right) == 1) { - cur.right?.let { - cur = rotateRight(cur) - cur = rotateLeft(cur) - } + + parent.right == toRemove -> { + parent.right = null + parent.diffHeight += 1 } } + balanceAfterRemove(parent) + } else if (toRemove.right == null) { + toRemove.left?.let { + toRemove.key = it.key + toRemove.value = it.value + toRemove.left = null + toRemove.diffHeight = 0 + } + balanceAfterRemove(parent) + when { + parent?.left == toRemove -> parent.diffHeight -= 1 + parent?.right == toRemove -> parent.diffHeight += 1 + } + } else { + val minRight = + minVertex(toRemove.right) + ?: throw IllegalStateException("min of subtree can't be null if it's contains at least one element") + toRemove.key = minRight.key + toRemove.value = minRight.value + removeVert(minRight) + } + } - if (cur.diffHeight == 0) break + /** + * Climbing up the tree, updates diffHeights of vertices after remove and calls + * [balanceOnce] if vertex became unbalanced + */ + private fun balanceAfterRemove(vertex: AVLVertex?) { + var cur = vertex ?: return + while (cur.diffHeight != 1 && cur.diffHeight != -1) { + cur = balanceOnce(cur) + if (cur.diffHeight != 1 && cur.diffHeight != -1) { + when { + cur.parent?.left == cur -> cur.parent?.let { it.diffHeight -= 1 } + cur.parent?.right == cur -> cur.parent?.let { it.diffHeight += 1 } + } + } + cur = cur.parent ?: return } } @@ -92,10 +151,38 @@ class AVLTree, V> : BalanceBSTreeTemplate): AVLVertex { + var vertex = _vertex + if (vertex.diffHeight == 2) { + if (getDiffHeight(vertex.left) >= 0) { + vertex = rotateRight(vertex) + } else if (getDiffHeight(vertex.left) == -1) { + vertex.left?.let { + vertex.left = rotateLeft(it) + vertex = rotateRight(vertex) + } + } + } else if (vertex.diffHeight == -2) { + if (getDiffHeight(vertex.right) <= 0) { + vertex = rotateLeft(vertex) + } else if (getDiffHeight(vertex.right) == 1) { + vertex.right?.let { + rotateRight(it) + vertex = rotateLeft(vertex) + } + } + } + return vertex + } + private fun rotateRight(origin: AVLVertex): AVLVertex { val left = origin.left - ?: throw IllegalStateException("difference of heights can't be 2 if left Vertex doesn't exist") + ?: throw IllegalStateException("Height difference can't be 2 if left Vertex doesn't exist") left.parent = origin.parent if (origin.parent?.left == origin) { @@ -109,13 +196,46 @@ class AVLTree, V> : BalanceBSTreeTemplate { + when (left.diffHeight) { + 0 -> { + origin.diffHeight = 1 + left.diffHeight = -1 + } + + 1 -> { + origin.diffHeight = 0 + left.diffHeight = 0 + } + + 2 -> { + origin.diffHeight = -1 + left.diffHeight = 0 + } + } + } + + 1 -> { + when (left.diffHeight) { + 0 -> { + origin.diffHeight = 0 + left.diffHeight = -1 + } + + 1 -> { + origin.diffHeight = -1 + left.diffHeight = -1 + } + + -1 -> { + origin.diffHeight = 0 + left.diffHeight = -2 + } + } + } } + if (origin == root) { root = left } @@ -125,7 +245,7 @@ class AVLTree, V> : BalanceBSTreeTemplate): AVLVertex { val right = origin.right - ?: throw IllegalStateException("difference of heights can't be 2 if left Vertex doesn't exist") + ?: throw IllegalStateException("Height difference can't be 2 if left Vertex doesn't exist") right.parent = origin.parent if (origin.parent?.left == origin) { @@ -139,20 +259,49 @@ class AVLTree, V> : BalanceBSTreeTemplate { + when (right.diffHeight) { + 0 -> { + origin.diffHeight = -1 + right.diffHeight = 1 + } + + -1 -> { + origin.diffHeight = 0 + right.diffHeight = 0 + } + + -2 -> { + origin.diffHeight = 1 + right.diffHeight = 0 + } + } + } + + -1 -> { + when (right.diffHeight) { + 0 -> { + origin.diffHeight = 0 + right.diffHeight = 1 + } + + -1 -> { + origin.diffHeight = 1 + right.diffHeight = 1 + } + + 1 -> { + origin.diffHeight = 0 + right.diffHeight = 2 + } + } + } } + if (origin == root) { root = right } return right } - - public override fun remove(key: K): V? { - return TODO() - } } diff --git a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt index 79bcd1b..eae8bf1 100644 --- a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt +++ b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt @@ -4,15 +4,74 @@ import bstrees.templates.BSTreeTemplate class SimpleTree, V> : BSTreeTemplate>() { override fun remove(key: K): V? { - // remove implementation - return null + val vertex = vertByKey(key) ?: return null + val parent = vertex.parent + val oldValue = vertex.value + if (vertex.left == null && vertex.right == null) { + when { + parent == null -> root = null + parent.left == vertex -> parent.left = null + else -> parent.right = null + } + } else if (vertex.right == null) { + vertex.left?.let { + vertex.key = it.key + vertex.value = it.value + vertex.left = null + } + } else { + val successor = minVertex(vertex.right) + val successorParent = successor?.parent + successor?.let { + vertex.key = successor.key + vertex.value = successor.value + } + when { + successorParent?.left == successor -> successorParent?.left = null + else -> vertex.right = null + } + } + --size + return oldValue } override operator fun set( key: K, value: V, ): V? { - // set implemenation - return null + if (root == null) { + val vertex = SimpleVertex(key, value) + root = vertex + size += 1 + return null + } + + var current = root ?: throw IllegalStateException("Can't be null, there was a check above") + while (true) { + val result = current.key.compareTo(key) + if (result < 0) { + if (current.left == null) { + val newVertex = SimpleVertex(key, value) + current.left = newVertex + newVertex.parent = current + size += 1 + return null + } + current = current.left ?: throw IllegalStateException("Case when cur.left is null is processed above") + } else if (result > 0) { + if (current.right == null) { + val newVertex = SimpleVertex(key, value) + current.right = newVertex + newVertex.parent = current + size += 1 + return null + } + current = current.right ?: throw IllegalStateException("Case when cur.right is null is processed above") + } else { + val oldValue = current.value + current.value = value + return null + } + } } } diff --git a/megalinter-reports/updated_sources/lib/src/test/kotlin/trees/AVLTreeTest.kt b/megalinter-reports/updated_sources/lib/src/test/kotlin/trees/AVLTreeTest.kt index d7ac37b..712bf2d 100644 --- a/megalinter-reports/updated_sources/lib/src/test/kotlin/trees/AVLTreeTest.kt +++ b/megalinter-reports/updated_sources/lib/src/test/kotlin/trees/AVLTreeTest.kt @@ -4,13 +4,39 @@ package trees import bstrees.implementations.AVLTree +import bstrees.implementations.AVLVertex +import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test +import kotlin.test.assertContentEquals import kotlin.test.assertEquals class AVLTreeTest { private lateinit var avlTree: AVLTree + /** + * Traverse all vertices of the tree and asserts that their diffHeights are + * equal to real height difference of the subtrees. + * @return height of the subtree with the root at the specified [vertex] + */ + fun checkTreeInvariant(vertex: AVLVertex<*, *>?): Int { + if (vertex == null) return 0 + + val leftSubtreeHeight = checkTreeInvariant(vertex.left) + val rightSubtreeHeight = checkTreeInvariant(vertex.right) + val difference = leftSubtreeHeight - rightSubtreeHeight + assertTrue( + difference in -1..1, + "Height difference of subtrees must be in [-1,1]", + ) + assertEquals( + difference, + vertex.diffHeight, + "Property diffHeights must match real Height difference of subtrees (key = ${vertex.key})", + ) + return maxOf(checkTreeInvariant(vertex.left), checkTreeInvariant(vertex.right)) + 1 + } + @BeforeEach fun setup() { avlTree = AVLTree() @@ -18,25 +44,26 @@ class AVLTreeTest { @Test fun `simple array test`() { - val array = intArrayOf(1, 2, 3, 4, 5) + val array = intArrayOf(0, 1, 2, 3, 4) for (i in array) { - avlTree.set(i, -i) + avlTree[i] = -i } - val expectedGet = -5 - val actualGet = avlTree.get(5) - assertEquals(expectedGet, actualGet, "Get method must return associated with key value") + val expectedGet: Array = Array(5, { i -> -i }) + val actualGet: Array = Array(5, { i -> avlTree.get(i) }) + assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") val expectedSize = 5 val actualSize = avlTree.size - assertEquals(expectedSize, actualSize, "Size of avl tree must correspond to number key-value pairs") + assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") + checkTreeInvariant(avlTree.root) } @Test fun `size of avl tree with duplicate keys`() { for (i in 1..10) { - avlTree.set(i, 30 + i) + avlTree[i] = i + 30 } for (i in 6..10) { - avlTree.set(i, 0) + avlTree[i] = 0 } val expectedSize = 10 @@ -44,17 +71,18 @@ class AVLTreeTest { assertEquals( expectedSize, actualSize, - "Size of avl tree must not change with overwriting an existing key", + "Size of the tree must not change after overwriting an existing key", ) + checkTreeInvariant(avlTree.root) } @Test fun `set keys twice`() { for (i in 1..10) { - avlTree.set(i, 30 + i) + avlTree[i] = 30 + i } for (i in 1..10) { - avlTree.set(i, 0) + avlTree[i] = 0 } val expectedSize = 10 @@ -62,7 +90,234 @@ class AVLTreeTest { assertEquals( expectedSize, actualSize, - "Size of avl tree must not change with overwriting an existing key", + "Size of the tree must not change after overwriting an existing key", + ) + checkTreeInvariant(avlTree.root) + } + + @Test + fun `simple remove`() { + avlTree[0] = 5 + + val expectedResult = 5 + val actualResult = avlTree.remove(0) + val expectedSize = 0 + val actualSize = avlTree.size + + assertEquals( + expectedResult, + actualResult, + "Remove must return removed value", + ) + assertEquals( + expectedSize, + actualSize, + "Size of the tree must decrease after removing the existing key", ) } + + @Test + fun `remove with left vertex`() { + val keys = intArrayOf(0, -1, 1, -2) + for (key in keys) avlTree[key] = key + avlTree.remove(-1) + + val expectedResult = arrayOf(0, null, 1, -2) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Tree must save all other vertices after remove vertex with existing left vertex", + ) + checkTreeInvariant(avlTree.root) + } + + @Test + fun `remove with right subtree of height 1`() { + val keys = intArrayOf(0, -1, 3, 1, 2) + for (key in keys) avlTree[key] = key + avlTree.remove(3) + + val expectedResult = arrayOf(0, -1, null, 1, 2) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Tree must save all other vertices after remove vertex with right subtree of height 1", + ) + checkTreeInvariant(avlTree.root) + } + + @Test + fun `remove with right subtree of height more than 1`() { + val keys = intArrayOf(0, -1, 3, -2, 1, 6, 4, 7) + for (key in keys) avlTree[key] = key + avlTree.remove(3) + + val expectedResult = arrayOf(0, -1, null, -2, 1, 6, 4, 7) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Tree must save all other vertices after remove vertex with right subtree of height >1", + ) + checkTreeInvariant(avlTree.root) + avlTree[5] = 5 + checkTreeInvariant(avlTree.root) + } + + @Test + fun `remove with necessary double rotate`() { + val keys = intArrayOf(5, 0, 7, -1, 2, 6, 9, -2, 1, 3, 8, 4) + for (key in keys) avlTree[key] = key + avlTree.remove(7) + + val expectedResult = arrayOf(5, 0, null, -1, 2, 6, 9, -2, 1, 3, 8, 4) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Tree must save all other vertices after remove that creates unbalance situation", + ) + checkTreeInvariant(avlTree.root) + } + + @Test + fun `remove root with double rotate`() { + val keys = intArrayOf(4, 1, 6, 0, 3, 5, 2) + for (key in keys) avlTree[key] = key + avlTree.remove(4) + + assertTrue(avlTree.root != null) + val expectedResult = arrayOf(null, 1, 6, 0, 3, 5, 2) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Tree must save all other vertices after root remove", + ) + checkTreeInvariant(avlTree.root) + } + + @Test + fun `remove a non-existent key`() { + avlTree[0] = 15 + avlTree.remove(0) + + val expectedResult = null + val actualResult = avlTree.remove(0) + assertEquals( + expectedResult, + actualResult, + "Remove a non-existent key must return null", + ) + } + + @Test + fun `simple iteration`() { + val keys = intArrayOf(1, 7, 4, 9, 2, -44, 3) + val values = intArrayOf(19, 14, 31, 17, 12, -34, 0) + for (i in 0.. = arrayOf(-34, 19, 12, 0, 31, 14, 17) + val iterator = avlTree.iterator() + val actualResult: Array = Array(7, { iterator.next().second }) + assertContentEquals(expectedResult, actualResult, "Iterator must return vertices in keys order") + checkTreeInvariant(avlTree.root) + } + + @Test + fun `rotate left, right diffHeight = -1`() { + val keys = intArrayOf(0, -1, 2, 1, 3, 4) + for (key in keys) avlTree[key] = key + + val expectedResult = Array(keys.size, { i -> keys[i] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Get must return corresponding values after left rotate ( right.diffHeight = -1)", + ) + checkTreeInvariant(avlTree.root) + +// 0 0 2 +// / \ / \ / \ +// -1 2 -1 2 0 3 +// / \ --> / \ --> / \ \ +// 1 3 1 3 -1 1 4 +// \ +// 4 + } + + @Test + fun `rotate left, right diffHeiht = 0`() { + val keys = intArrayOf(0, -1, 4, 2, 6, -2, 1, 3, 5, 7) + for (key in keys) avlTree[key] = key + avlTree.remove(-2) + + val expectedResult = arrayOf(0, -1, 4, 2, 6, null, 1, 3, 5, 7) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Get must return corresponding values after left rotate (right.diffHeight = 0)", + ) + checkTreeInvariant(avlTree.root) +// 0 0 4 +// / \ / \ / \ +// -1 4 -1 4 0 6 +// / / \ --> / \ --> / \ / \ +// -2 2 6 2 6 -1 2 5 7 +// / \ / \ / \ / \ / \ +// 1 3 5 7 1 3 5 7 1 3 + } + + @Test + fun `rotate right, left diffHeight = 1`() { + val keys = intArrayOf(0, 1, -1, -3, -2, -4) + for (key in keys) avlTree[key] = key + + val expectedResult = Array(keys.size, { i -> keys[i] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Get must return corresponding values after right rotate (left.diffHeight = 1)", + ) + checkTreeInvariant(avlTree.root) + +// 0 0 -1 +// / \ / \ / \ +// -1 1 -1 1 -3 0 +// / \ --> / \ --> / / \ +// -3 -2 -3 -2 -4 -2 1 +// / +// -4 + } + + @Test + fun `rotate right, left diffHeight = 0`() { + val keys = intArrayOf(7, 3, 8, 9, 1, 5, 0, 2, 4, 6) + for (key in keys) avlTree[key] = key + avlTree.remove(9) + + val expectedResult = arrayOf(7, 3, 8, null, 1, 5, 0, 2, 4, 6) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Get must return corresponding values after right rotate (left.diffHeight = 0)", + ) + checkTreeInvariant(avlTree.root) + +// 7 7 3 +// / \ / \ / \ +// 3 8 3 8 1 7 +// / \ \ --> / \ --> / \ / \ +// 1 5 9 1 5 0 2 5 8 +// / \ / \ / \ / \ / \ +// 0 2 4 6 0 2 4 6 4 6 + } } diff --git a/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log b/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log new file mode 100644 index 0000000..9913267 --- /dev/null +++ b/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log @@ -0,0 +1,12 @@ +Results of ktlint linter (version 1.2.1) +See documentation on https://megalinter.io/7.10.0/descriptors/kotlin_ktlint/ +----------------------------------------------- + +✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/AVLTree.kt - FIXED +✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/RBTree.kt - FIXED +✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt - FIXED +✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/Vertices.kt +✅ [SUCCESS] lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt +✅ [SUCCESS] lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt - FIXED +✅ [SUCCESS] lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt +✅ [SUCCESS] lib/src/test/kotlin/trees/AVLTreeTest.kt - FIXED diff --git a/megalinter-reports/updated_sources/megalinter-reports/megalinter.log b/megalinter-reports/updated_sources/megalinter-reports/megalinter.log new file mode 100644 index 0000000..f0318f3 --- /dev/null +++ b/megalinter-reports/updated_sources/megalinter-reports/megalinter.log @@ -0,0 +1,57 @@ +---------------------------------------------------------------------------------------------------- +------------------------------------ MegaLinter, by OX Security ------------------------------------ +---------------------------------------------------------------------------------------------------- + - Image Creation Date: 2024-03-10T20:25:08Z + - Image Revision: a7a0163b6c8ff7474a283d99a706e27483ddd80f + - Image Version: v7.10.0 +---------------------------------------------------------------------------------------------------- +The MegaLinter documentation can be found at: + - https://megalinter.io/7.10.0 +---------------------------------------------------------------------------------------------------- +::group::MegaLinter initialization (expand for details) +MegaLinter will analyze workspace [/github/workspace] +GITHUB_REPOSITORY: spbu-coding-2023/trees-8 +GITHUB_REF: refs/pull/10/merge +GITHUB_RUN_ID: 8437735818 + + +CLOJURE_CLJSTYLE has been temporary disabled in MegaLinter, please use a previous MegaLinter version or wait for the next one ! +MARKDOWN_REMARK_LINT has been temporary disabled in MegaLinter, please use a previous MegaLinter version or wait for the next one ! +Skipped linters: ACTION_ACTIONLINT, ANSIBLE_ANSIBLE_LINT, ARM_ARM_TTK, BASH_EXEC, BASH_SHELLCHECK, BASH_SHFMT, BICEP_BICEP_LINTER, CLOJURE_CLJSTYLE, CLOJURE_CLJ_KONDO, CLOUDFORMATION_CFN_LINT, COFFEE_COFFEELINT, COPYPASTE_JSCPD, CPP_CLANG_FORMAT, CPP_CPPLINT, CSHARP_CSHARPIER, CSHARP_DOTNET_FORMAT, CSHARP_ROSLYNATOR, CSS_SCSS_LINT, CSS_STYLELINT, C_CLANG_FORMAT, C_CPPLINT, DART_DARTANALYZER, DOCKERFILE_HADOLINT, EDITORCONFIG_EDITORCONFIG_CHECKER, ENV_DOTENV_LINTER, GHERKIN_GHERKIN_LINT, GO_GOLANGCI_LINT, GO_REVIVE, GRAPHQL_GRAPHQL_SCHEMA_LINTER, GROOVY_NPM_GROOVY_LINT, HTML_DJLINT, HTML_HTMLHINT, JAVASCRIPT_ES, JAVASCRIPT_PRETTIER, JAVASCRIPT_STANDARD, JAVA_CHECKSTYLE, JAVA_PMD, JSON_ESLINT_PLUGIN_JSONC, JSON_JSONLINT, JSON_NPM_PACKAGE_JSON_LINT, JSON_PRETTIER, JSON_V8R, JSX_ESLINT, KUBERNETES_HELM, KUBERNETES_KUBECONFORM, KUBERNETES_KUBESCAPE, LATEX_CHKTEX, LUA_LUACHECK, MAKEFILE_CHECKMAKE, MARKDOWN_MARKDOWNLINT, MARKDOWN_MARKDOWN_LINK_CHECK, MARKDOWN_MARKDOWN_TABLE_FORMATTER, MARKDOWN_REMARK_LINT, OPENAPI_SPECTRAL, PERL_PERLCRITIC, PHP_PHPCS, PHP_PHPLINT, PHP_PHPSTAN, PHP_PSALM, POWERSHELL_POWERSHELL, POWERSHELL_POWERSHELL_FORMATTER, PROTOBUF_PROTOLINT, PUPPET_PUPPET_LINT, PYTHON_BANDIT, PYTHON_BLACK, PYTHON_FLAKE8, PYTHON_ISORT, PYTHON_MYPY, PYTHON_PYLINT, PYTHON_PYRIGHT, PYTHON_RUFF, RAKU_RAKU, REPOSITORY_CHECKOV, REPOSITORY_DEVSKIM, REPOSITORY_DUSTILOCK, REPOSITORY_GITLEAKS, REPOSITORY_GIT_DIFF, REPOSITORY_GRYPE, REPOSITORY_KICS, REPOSITORY_SECRETLINT, REPOSITORY_SEMGREP, REPOSITORY_SYFT, REPOSITORY_TRIVY, REPOSITORY_TRIVY_SBOM, REPOSITORY_TRUFFLEHOG, RST_RSTCHECK, RST_RSTFMT, RST_RST_LINT, RUBY_RUBOCOP, RUST_CLIPPY, R_LINTR, SALESFORCE_LIGHTNING_FLOW_SCANNER, SALESFORCE_SFDX_SCANNER_APEX, SALESFORCE_SFDX_SCANNER_AURA, SALESFORCE_SFDX_SCANNER_LWC, SCALA_SCALAFIX, SNAKEMAKE_LINT, SNAKEMAKE_SNAKEFMT, SPELL_CSPELL, SPELL_LYCHEE, SPELL_PROSELINT, SPELL_VALE, SQL_SQLFLUFF, SQL_SQL_LINT, SQL_TSQLLINT, SWIFT_SWIFTLINT, TEKTON_TEKTON_LINT, TERRAFORM_TERRAFORM_FMT, TERRAFORM_TERRAGRUNT, TERRAFORM_TERRASCAN, TERRAFORM_TFLINT, TSX_ESLINT, TYPESCRIPT_ES, TYPESCRIPT_PRETTIER, TYPESCRIPT_STANDARD, VBDOTNET_DOTNET_FORMAT, XML_XMLLINT, YAML_PRETTIER, YAML_V8R, YAML_YAMLLINT +To receive reports as email, please set variable EMAIL_REPORTER_EMAIL +::endgroup:: +::group::MegaLinter now collects the files to analyse (expand for details) +Listing updated files in [/github/workspace] using git diff. +Modified files: +lib/src/main/kotlin/bstrees/implementations/AVLTree.kt +lib/src/main/kotlin/bstrees/implementations/RBTree.kt +lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt +lib/src/main/kotlin/bstrees/implementations/Vertices.kt +lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt +lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt +lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt +lib/src/test/kotlin/trees/AVLTreeTest.kt +megalinter-reports/megalinter.log +- File extensions: .kt, .kts +- Excluding .gitignored files [0]: +Kept [8] files on [9] found files + ++----MATCHING LINTERS-+----------+----------------+------------+ +| Descriptor | Linter | Criteria | Matching files | Format/Fix | ++------------+--------+----------+----------------+------------+ +| KOTLIN | ktlint | .kt|.kts | 8 | yes | ++------------+--------+----------+----------------+------------+ +::endgroup:: +::group::✅ Linted [KOTLIN] files with [ktlint] successfully - (11.15s) (expand for details) +- Using [ktlint v1.2.1] https://megalinter.io/7.10.0/descriptors/kotlin_ktlint +- MegaLinter key: [KOTLIN_KTLINT] +- Rules config: identified by [ktlint] +- Number of files analyzed: [8] +::endgroup:: + ++----SUMMARY-+--------+------+-------+-------+--------+--------------+ +| Descriptor | Linter | Mode | Files | Fixed | Errors | Elapsed time | ++------------+--------+------+-------+-------+--------+--------------+ +| ✅ KOTLIN | ktlint | file | 8 | 5 | 0 | 11.15s | ++------------+--------+------+-------+-------+--------+--------------+ + From 1cb7bc19bf37f9a731eac2281bda3508f82503df Mon Sep 17 00:00:00 2001 From: Alexei Dmitrievtsev Date: Tue, 26 Mar 2024 11:03:43 -0400 Subject: [PATCH 038/108] add: RBTree right/left rotation --- .../kotlin/bstrees/implementations/RBTree.kt | 48 ++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/bstrees/implementations/RBTree.kt b/lib/src/main/kotlin/bstrees/implementations/RBTree.kt index 128289e..1a948d7 100644 --- a/lib/src/main/kotlin/bstrees/implementations/RBTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/RBTree.kt @@ -8,6 +8,52 @@ class RBTree, V> : BalanceBSTreeTemplate> //balance(currentVert) return returnResult } + private fun rotateRight(vertex: RBVertex) { + val parent = vertex.parent + val leftChild = vertex.left + + vertex.left = leftChild?.right + if (leftChild?.right != null) { + leftChild.right?.parent = vertex + } + leftChild?.right = vertex + vertex.parent = leftChild + if (parent == null) { + root = leftChild + } + else if (parent.left == vertex) { + parent.left = leftChild + } + else if (parent.right == vertex) { + parent.right = leftChild + } + if (leftChild != null) { + leftChild.parent = parent; + } + } + private fun rotateLeft(vertex: RBVertex) { + val parent = vertex.parent + val rightChild = vertex.right + vertex.right = rightChild?.left + if (rightChild?.left != null) { + rightChild.left?.parent = vertex + } + rightChild?.left = vertex + vertex.parent = rightChild + if (parent == null) { + root = rightChild + } + else if (parent.left == vertex) { + parent.left = rightChild + } else if (parent.right == vertex) { + parent.right = rightChild + } + if (rightChild != null) { + rightChild.parent = parent; + } + } + + private fun unbalancedSet(key: K, value: V): Pair, V?> { if (root == null){ val newVertex = RBVertex(key, value) @@ -46,4 +92,4 @@ class RBTree, V> : BalanceBSTreeTemplate> override fun remove(key: K): V?{ return null } -} +} \ No newline at end of file From 3a065376d1ca29d0343e0f64056d81cdf93b81f7 Mon Sep 17 00:00:00 2001 From: Alexei Dmitrievtsev Date: Tue, 26 Mar 2024 15:45:43 -0400 Subject: [PATCH 039/108] add: RBTree set with balance --- .../kotlin/bstrees/implementations/RBTree.kt | 84 +++++++++++++++---- 1 file changed, 68 insertions(+), 16 deletions(-) diff --git a/lib/src/main/kotlin/bstrees/implementations/RBTree.kt b/lib/src/main/kotlin/bstrees/implementations/RBTree.kt index 1a948d7..996f67e 100644 --- a/lib/src/main/kotlin/bstrees/implementations/RBTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/RBTree.kt @@ -5,19 +5,18 @@ import bstrees.templates.BalanceBSTreeTemplate class RBTree, V> : BalanceBSTreeTemplate>() { override fun set(key: K, value: V): V? { val (currentVert, returnResult) = unbalancedSet(key, value) - //balance(currentVert) + balanceTreeAfterInsert(currentVert) return returnResult } - private fun rotateRight(vertex: RBVertex) { - val parent = vertex.parent - val leftChild = vertex.left - - vertex.left = leftChild?.right + private fun rotateRight(vertex: RBVertex?) { + val parent = vertex?.parent + val leftChild = vertex?.left + vertex?.left = leftChild?.right if (leftChild?.right != null) { leftChild.right?.parent = vertex } leftChild?.right = vertex - vertex.parent = leftChild + vertex?.parent = leftChild if (parent == null) { root = leftChild } @@ -28,18 +27,18 @@ class RBTree, V> : BalanceBSTreeTemplate> parent.right = leftChild } if (leftChild != null) { - leftChild.parent = parent; + leftChild.parent = parent } } - private fun rotateLeft(vertex: RBVertex) { - val parent = vertex.parent - val rightChild = vertex.right - vertex.right = rightChild?.left + private fun rotateLeft(vertex: RBVertex?) { + val parent = vertex?.parent + val rightChild = vertex?.right + vertex?.right = rightChild?.left if (rightChild?.left != null) { rightChild.left?.parent = vertex } rightChild?.left = vertex - vertex.parent = rightChild + vertex?.parent = rightChild if (parent == null) { root = rightChild } @@ -49,7 +48,7 @@ class RBTree, V> : BalanceBSTreeTemplate> parent.right = rightChild } if (rightChild != null) { - rightChild.parent = parent; + rightChild.parent = parent } } @@ -64,7 +63,7 @@ class RBTree, V> : BalanceBSTreeTemplate> var currentVertex = root ?: throw IllegalStateException() while (true){ val result = currentVertex.key.compareTo(key) - if (result < 0){ + if (result > 0){ if(currentVertex.left == null){ val newVertex = RBVertex(key, value) currentVertex.left = newVertex @@ -73,7 +72,7 @@ class RBTree, V> : BalanceBSTreeTemplate> return Pair(newVertex, null) } currentVertex = currentVertex.left ?: throw IllegalStateException() - } else if (result > 0){ + } else if (result < 0){ if (currentVertex.right == null){ val newVertex = RBVertex(key, value) currentVertex.right = newVertex @@ -89,6 +88,59 @@ class RBTree, V> : BalanceBSTreeTemplate> } } } + + private fun balanceTreeAfterInsert(vertex: RBVertex){ + var parent = vertex.parent + val black = RBVertex.Color.BLACK + val red = RBVertex.Color.RED + + val grandparent = parent?.parent + if (grandparent == null) { + parent?.color = black + return + } + if (parent == null) { + vertex.color = black + return + } + val uncle = getVertexUncle(parent) + if (uncle != null && uncle.color == red) { + parent.color = black + grandparent.color = red + uncle.color = black + balanceTreeAfterInsert(grandparent) + } + else if (parent == grandparent.left) { + if (vertex == parent.right) { + rotateLeft(parent) + parent = vertex + } + rotateRight(grandparent) + parent.color = black + grandparent.color = red + } + else { + if (vertex == parent.left) { + rotateRight(parent) + parent = vertex + } + rotateLeft(grandparent) + grandparent.color = red + + parent.color = black + } + } + + private fun getVertexUncle(parent: RBVertex?): RBVertex? { + val grandparent = parent?.parent + return if (grandparent?.right == parent) { + grandparent?.right + } else if (grandparent?.left == parent) { + grandparent?.left + } else { + throw IllegalStateException("Grandparent/Parent dependency mistake") + } + } override fun remove(key: K): V?{ return null } From f24f57eb17eaac9c9adc760c31d4e765f42c3559 Mon Sep 17 00:00:00 2001 From: Alexei Dmitrievtsev Date: Wed, 27 Mar 2024 17:31:21 -0400 Subject: [PATCH 040/108] add: RBTree balanced insert --- .../kotlin/bstrees/implementations/RBTree.kt | 181 ++++++++++++++++-- .../bstrees/implementations/Vertices.kt | 2 +- 2 files changed, 164 insertions(+), 19 deletions(-) diff --git a/lib/src/main/kotlin/bstrees/implementations/RBTree.kt b/lib/src/main/kotlin/bstrees/implementations/RBTree.kt index 996f67e..710723b 100644 --- a/lib/src/main/kotlin/bstrees/implementations/RBTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/RBTree.kt @@ -8,6 +8,9 @@ class RBTree, V> : BalanceBSTreeTemplate> balanceTreeAfterInsert(currentVert) return returnResult } + private val red = RBVertex.Color.RED + private val black = RBVertex.Color.BLACK + private fun rotateRight(vertex: RBVertex?) { val parent = vertex?.parent val leftChild = vertex?.left @@ -66,6 +69,7 @@ class RBTree, V> : BalanceBSTreeTemplate> if (result > 0){ if(currentVertex.left == null){ val newVertex = RBVertex(key, value) + newVertex.color = RBVertex.Color.RED currentVertex.left = newVertex newVertex.parent = currentVertex size+= 1 @@ -75,6 +79,7 @@ class RBTree, V> : BalanceBSTreeTemplate> } else if (result < 0){ if (currentVertex.right == null){ val newVertex = RBVertex(key, value) + newVertex.color = RBVertex.Color.RED currentVertex.right = newVertex newVertex.parent = currentVertex size += 1 @@ -91,18 +96,20 @@ class RBTree, V> : BalanceBSTreeTemplate> private fun balanceTreeAfterInsert(vertex: RBVertex){ var parent = vertex.parent - val black = RBVertex.Color.BLACK - val red = RBVertex.Color.RED - - val grandparent = parent?.parent - if (grandparent == null) { - parent?.color = black + if(parent == null){ + vertex.color = black return } - if (parent == null) { - vertex.color = black + if (parent.color == black) { return } + val grandparent = parent.parent + + if (grandparent == null) { + parent.color = black + return + } + val uncle = getVertexUncle(parent) if (uncle != null && uncle.color == red) { parent.color = black @@ -125,23 +132,161 @@ class RBTree, V> : BalanceBSTreeTemplate> parent = vertex } rotateLeft(grandparent) + parent.color = black grandparent.color = red + } + } + override fun remove(key : K) : V?{ + var vertex = root + while (vertex != null && vertex.key != key) { + if (key < vertex.key) { + vertex = vertex.left + } else { + vertex = vertex.right + } + } + if (vertex == null) { + return null + } + val replacedVertex: RBVertex? + val deletedVertexColor: RBVertex.Color + if (vertex.left == null || vertex.right == null) { + replacedVertex = deleteNullChild(vertex) + deletedVertexColor = vertex.color + } + else { + val minVertex = findMin(vertex.right!!) + minVertex.color = vertex.color + minVertex.left = vertex.left + minVertex.right = vertex.right + replaceChild(vertex.parent, vertex, minVertex) + replacedVertex = deleteNullChild(minVertex) + deletedVertexColor = minVertex.color + } - parent.color = black + if (deletedVertexColor == RBVertex.Color.BLACK) { + balanceTreeAfterDelete(replacedVertex) + if (replacedVertex?.nullType == true) { + replaceChild(replacedVertex.parent, replacedVertex, null) + } } + return replacedVertex?.value } + private fun balanceTreeAfterDelete(vertex: RBVertex?) { + if (vertex == root) { + vertex?.color = RBVertex.Color.BLACK + return + } + var brother = getBrother(vertex) - private fun getVertexUncle(parent: RBVertex?): RBVertex? { - val grandparent = parent?.parent - return if (grandparent?.right == parent) { - grandparent?.right - } else if (grandparent?.left == parent) { - grandparent?.left + if (brother?.color === RBVertex.Color.RED) { + manageRedBrother(vertex, brother) + brother = getBrother(vertex) + } + if (brother?.left?.color == RBVertex.Color.BLACK && brother.right?.color == RBVertex.Color.BLACK) { + brother.color = RBVertex.Color.RED + if (vertex?.parent?.color == RBVertex.Color.RED) { + vertex.parent?.color = RBVertex.Color.BLACK + } else { + balanceTreeAfterDelete(vertex?.parent) + } } else { - throw IllegalStateException("Grandparent/Parent dependency mistake") + manageBlackRedOne(vertex, brother) } } - override fun remove(key: K): V?{ - return null + private fun getBrother(vertex : RBVertex?): RBVertex? { + val parent = vertex?.parent + return if (vertex == parent?.left) { + parent?.right + } else if (vertex == parent?.right) { + parent?.left + } else { + throw IllegalStateException() + } + } + private fun manageBlackRedOne(vertex: RBVertex?, argBrother: RBVertex?) { + var brother = argBrother + if (vertex == vertex?.parent?.left && brother?.right?.color == black) { + brother.left?.color = black + brother.color = red + rotateRight(brother) + brother = vertex?.parent?.right + } else if (vertex != vertex?.parent?.left&& brother?.left?.color == black) { + brother.right?.color = black + brother.color = red + rotateLeft(brother) + brother = vertex?.parent?.left + } + brother?.color = vertex?.parent!!.color + vertex.parent?.color = black + if (vertex == vertex.parent?.left) { + brother?.right?.color = black + rotateLeft(vertex.parent) + } else { + brother?.left?.color = black + rotateRight(vertex.parent) + } + } + private fun manageRedBrother(vertex: RBVertex?, brother: RBVertex) { + brother.color = RBVertex.Color.BLACK + vertex?.parent?.color = RBVertex.Color.RED + if (vertex === vertex?.parent?.left) { + rotateLeft(vertex?.parent) + } else { + rotateRight(vertex?.parent) + } + } + + private fun replaceChild(parent: RBVertex?, oldChild: RBVertex, newChild: RBVertex?) { + if (parent == null) { + root = newChild + } else if (parent.left === oldChild) { + parent.left = newChild + } else if (parent.right === oldChild) { + parent.right = newChild + } else { + throw IllegalStateException() + } + if (newChild != null) { + newChild.parent = parent + } + } + private fun deleteNullChild(vertex: RBVertex): RBVertex? { + if (vertex.left != null) { + replaceChild(vertex.parent, vertex, vertex.left) + return vertex.left + } else if (vertex.right != null) { + replaceChild(vertex.parent, vertex, vertex.right) + return vertex.right + } else { + var newChild : RBVertex? = RBVertex(vertex.key, vertex.value) + if(vertex.color == RBVertex.Color.BLACK) { + newChild?.nullType = true + } + else{ + newChild = null + } + replaceChild(vertex.parent, vertex, newChild) + return newChild + } + } + private fun findMin(argVertex: RBVertex): RBVertex { + var vertex = argVertex + while (vertex.left != null) { + vertex = vertex.left!! + } + return vertex + } + + + private fun getVertexUncle(parent: RBVertex): RBVertex? { + val grandparent = parent.parent + return if (grandparent?.left == parent) { + grandparent.right + } else if (grandparent?.right == parent) { + grandparent.left + } else { + throw IllegalStateException("Grandparent/Parent dependency mistake") + } } } \ No newline at end of file diff --git a/lib/src/main/kotlin/bstrees/implementations/Vertices.kt b/lib/src/main/kotlin/bstrees/implementations/Vertices.kt index c13eaac..32877c3 100644 --- a/lib/src/main/kotlin/bstrees/implementations/Vertices.kt +++ b/lib/src/main/kotlin/bstrees/implementations/Vertices.kt @@ -10,7 +10,7 @@ class AVLVertex, V>(key: K, value: V) : VertexTemplate, V>(key: K, value: V) : VertexTemplate>(key, value) { var color: Color = Color.BLACK - + var nullType = true enum class Color { BLACK, RED, From 3f69120f97fbba62b8b5357916daaabe4ee9fc88 Mon Sep 17 00:00:00 2001 From: admitrievtsev Date: Wed, 27 Mar 2024 21:38:18 +0000 Subject: [PATCH 041/108] [MegaLinter] Apply linters fixes --- .../kotlin/bstrees/implementations/RBTree.kt | 146 ++++---- .../bstrees/implementations/Vertices.kt | 1 + .../linters_logs/SUCCESS-KOTLIN_KTLINT.log | 8 +- megalinter-reports/megalinter.log | 24 +- .../kotlin/bstrees/implementations/RBTree.kt | 313 +++++++++++++++++- .../bstrees/implementations/Vertices.kt | 7 + .../linters_logs/SUCCESS-KOTLIN_KTLINT.log | 8 +- .../megalinter-reports/megalinter.log | 20 +- 8 files changed, 422 insertions(+), 105 deletions(-) diff --git a/lib/src/main/kotlin/bstrees/implementations/RBTree.kt b/lib/src/main/kotlin/bstrees/implementations/RBTree.kt index 710723b..dad5435 100644 --- a/lib/src/main/kotlin/bstrees/implementations/RBTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/RBTree.kt @@ -3,11 +3,15 @@ package bstrees.implementations import bstrees.templates.BalanceBSTreeTemplate class RBTree, V> : BalanceBSTreeTemplate>() { - override fun set(key: K, value: V): V? { + override fun set( + key: K, + value: V, + ): V? { val (currentVert, returnResult) = unbalancedSet(key, value) balanceTreeAfterInsert(currentVert) return returnResult } + private val red = RBVertex.Color.RED private val black = RBVertex.Color.BLACK @@ -22,19 +26,18 @@ class RBTree, V> : BalanceBSTreeTemplate> vertex?.parent = leftChild if (parent == null) { root = leftChild - } - else if (parent.left == vertex) { + } else if (parent.left == vertex) { parent.left = leftChild - } - else if (parent.right == vertex) { + } else if (parent.right == vertex) { parent.right = leftChild } if (leftChild != null) { leftChild.parent = parent } } + private fun rotateLeft(vertex: RBVertex?) { - val parent = vertex?.parent + val parent = vertex?.parent val rightChild = vertex?.right vertex?.right = rightChild?.left if (rightChild?.left != null) { @@ -44,8 +47,7 @@ class RBTree, V> : BalanceBSTreeTemplate> vertex?.parent = rightChild if (parent == null) { root = rightChild - } - else if (parent.left == vertex) { + } else if (parent.left == vertex) { parent.left = rightChild } else if (parent.right == vertex) { parent.right = rightChild @@ -55,38 +57,45 @@ class RBTree, V> : BalanceBSTreeTemplate> } } - - private fun unbalancedSet(key: K, value: V): Pair, V?> { - if (root == null){ - val newVertex = RBVertex(key, value) - root = newVertex - size += 1 - return Pair(newVertex, null) - } + private fun unbalancedSet( + key: K, + value: V, + ): Pair, V?> { + if (root == null) + { + val newVertex = RBVertex(key, value) + root = newVertex + size += 1 + return Pair(newVertex, null) + } var currentVertex = root ?: throw IllegalStateException() - while (true){ + while (true) { val result = currentVertex.key.compareTo(key) - if (result > 0){ - if(currentVertex.left == null){ - val newVertex = RBVertex(key, value) - newVertex.color = RBVertex.Color.RED - currentVertex.left = newVertex - newVertex.parent = currentVertex - size+= 1 - return Pair(newVertex, null) - } - currentVertex = currentVertex.left ?: throw IllegalStateException() - } else if (result < 0){ - if (currentVertex.right == null){ - val newVertex = RBVertex(key, value) - newVertex.color = RBVertex.Color.RED - currentVertex.right = newVertex - newVertex.parent = currentVertex - size += 1 - return Pair(newVertex, null) - } - currentVertex = currentVertex.right ?: throw IllegalStateException() - } else{ + if (result > 0) + { + if (currentVertex.left == null) + { + val newVertex = RBVertex(key, value) + newVertex.color = RBVertex.Color.RED + currentVertex.left = newVertex + newVertex.parent = currentVertex + size += 1 + return Pair(newVertex, null) + } + currentVertex = currentVertex.left ?: throw IllegalStateException() + } else if (result < 0) + { + if (currentVertex.right == null) + { + val newVertex = RBVertex(key, value) + newVertex.color = RBVertex.Color.RED + currentVertex.right = newVertex + newVertex.parent = currentVertex + size += 1 + return Pair(newVertex, null) + } + currentVertex = currentVertex.right ?: throw IllegalStateException() + } else { val oldValue = currentVertex.value currentVertex.value = value return Pair(currentVertex, oldValue) @@ -94,12 +103,13 @@ class RBTree, V> : BalanceBSTreeTemplate> } } - private fun balanceTreeAfterInsert(vertex: RBVertex){ + private fun balanceTreeAfterInsert(vertex: RBVertex) { var parent = vertex.parent - if(parent == null){ - vertex.color = black - return - } + if (parent == null) + { + vertex.color = black + return + } if (parent.color == black) { return } @@ -116,8 +126,7 @@ class RBTree, V> : BalanceBSTreeTemplate> grandparent.color = red uncle.color = black balanceTreeAfterInsert(grandparent) - } - else if (parent == grandparent.left) { + } else if (parent == grandparent.left) { if (vertex == parent.right) { rotateLeft(parent) parent = vertex @@ -125,8 +134,7 @@ class RBTree, V> : BalanceBSTreeTemplate> rotateRight(grandparent) parent.color = black grandparent.color = red - } - else { + } else { if (vertex == parent.left) { rotateRight(parent) parent = vertex @@ -136,7 +144,8 @@ class RBTree, V> : BalanceBSTreeTemplate> grandparent.color = red } } - override fun remove(key : K) : V?{ + + override fun remove(key: K): V? { var vertex = root while (vertex != null && vertex.key != key) { if (key < vertex.key) { @@ -153,8 +162,7 @@ class RBTree, V> : BalanceBSTreeTemplate> if (vertex.left == null || vertex.right == null) { replacedVertex = deleteNullChild(vertex) deletedVertexColor = vertex.color - } - else { + } else { val minVertex = findMin(vertex.right!!) minVertex.color = vertex.color minVertex.left = vertex.left @@ -172,6 +180,7 @@ class RBTree, V> : BalanceBSTreeTemplate> } return replacedVertex?.value } + private fun balanceTreeAfterDelete(vertex: RBVertex?) { if (vertex == root) { vertex?.color = RBVertex.Color.BLACK @@ -181,7 +190,7 @@ class RBTree, V> : BalanceBSTreeTemplate> if (brother?.color === RBVertex.Color.RED) { manageRedBrother(vertex, brother) - brother = getBrother(vertex) + brother = getBrother(vertex) } if (brother?.left?.color == RBVertex.Color.BLACK && brother.right?.color == RBVertex.Color.BLACK) { brother.color = RBVertex.Color.RED @@ -194,7 +203,8 @@ class RBTree, V> : BalanceBSTreeTemplate> manageBlackRedOne(vertex, brother) } } - private fun getBrother(vertex : RBVertex?): RBVertex? { + + private fun getBrother(vertex: RBVertex?): RBVertex? { val parent = vertex?.parent return if (vertex == parent?.left) { parent?.right @@ -204,14 +214,18 @@ class RBTree, V> : BalanceBSTreeTemplate> throw IllegalStateException() } } - private fun manageBlackRedOne(vertex: RBVertex?, argBrother: RBVertex?) { + + private fun manageBlackRedOne( + vertex: RBVertex?, + argBrother: RBVertex?, + ) { var brother = argBrother if (vertex == vertex?.parent?.left && brother?.right?.color == black) { brother.left?.color = black brother.color = red rotateRight(brother) brother = vertex?.parent?.right - } else if (vertex != vertex?.parent?.left&& brother?.left?.color == black) { + } else if (vertex != vertex?.parent?.left && brother?.left?.color == black) { brother.right?.color = black brother.color = red rotateLeft(brother) @@ -227,7 +241,11 @@ class RBTree, V> : BalanceBSTreeTemplate> rotateRight(vertex.parent) } } - private fun manageRedBrother(vertex: RBVertex?, brother: RBVertex) { + + private fun manageRedBrother( + vertex: RBVertex?, + brother: RBVertex, + ) { brother.color = RBVertex.Color.BLACK vertex?.parent?.color = RBVertex.Color.RED if (vertex === vertex?.parent?.left) { @@ -237,7 +255,11 @@ class RBTree, V> : BalanceBSTreeTemplate> } } - private fun replaceChild(parent: RBVertex?, oldChild: RBVertex, newChild: RBVertex?) { + private fun replaceChild( + parent: RBVertex?, + oldChild: RBVertex, + newChild: RBVertex?, + ) { if (parent == null) { root = newChild } else if (parent.left === oldChild) { @@ -251,6 +273,7 @@ class RBTree, V> : BalanceBSTreeTemplate> newChild.parent = parent } } + private fun deleteNullChild(vertex: RBVertex): RBVertex? { if (vertex.left != null) { replaceChild(vertex.parent, vertex, vertex.left) @@ -259,17 +282,17 @@ class RBTree, V> : BalanceBSTreeTemplate> replaceChild(vertex.parent, vertex, vertex.right) return vertex.right } else { - var newChild : RBVertex? = RBVertex(vertex.key, vertex.value) - if(vertex.color == RBVertex.Color.BLACK) { + var newChild: RBVertex? = RBVertex(vertex.key, vertex.value) + if (vertex.color == RBVertex.Color.BLACK) { newChild?.nullType = true - } - else{ + } else { newChild = null } replaceChild(vertex.parent, vertex, newChild) return newChild } } + private fun findMin(argVertex: RBVertex): RBVertex { var vertex = argVertex while (vertex.left != null) { @@ -278,7 +301,6 @@ class RBTree, V> : BalanceBSTreeTemplate> return vertex } - private fun getVertexUncle(parent: RBVertex): RBVertex? { val grandparent = parent.parent return if (grandparent?.left == parent) { @@ -289,4 +311,4 @@ class RBTree, V> : BalanceBSTreeTemplate> throw IllegalStateException("Grandparent/Parent dependency mistake") } } -} \ No newline at end of file +} diff --git a/lib/src/main/kotlin/bstrees/implementations/Vertices.kt b/lib/src/main/kotlin/bstrees/implementations/Vertices.kt index 83ca52a..542ef83 100644 --- a/lib/src/main/kotlin/bstrees/implementations/Vertices.kt +++ b/lib/src/main/kotlin/bstrees/implementations/Vertices.kt @@ -17,6 +17,7 @@ class AVLVertex, V>(key: K, value: V) : VertexTemplate, V>(key: K, value: V) : VertexTemplate>(key, value) { var color: Color = Color.BLACK var nullType = true + enum class Color { BLACK, RED, diff --git a/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log b/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log index 9913267..5575c56 100644 --- a/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log +++ b/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log @@ -2,11 +2,5 @@ Results of ktlint linter (version 1.2.1) See documentation on https://megalinter.io/7.10.0/descriptors/kotlin_ktlint/ ----------------------------------------------- -✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/AVLTree.kt - FIXED ✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/RBTree.kt - FIXED -✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt - FIXED -✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/Vertices.kt -✅ [SUCCESS] lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt -✅ [SUCCESS] lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt - FIXED -✅ [SUCCESS] lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt -✅ [SUCCESS] lib/src/test/kotlin/trees/AVLTreeTest.kt - FIXED +✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/Vertices.kt - FIXED diff --git a/megalinter-reports/megalinter.log b/megalinter-reports/megalinter.log index a2359ee..ea80566 100644 --- a/megalinter-reports/megalinter.log +++ b/megalinter-reports/megalinter.log @@ -11,8 +11,8 @@ The MegaLinter documentation can be found at: ::group::MegaLinter initialization (expand for details) MegaLinter will analyze workspace [/github/workspace] GITHUB_REPOSITORY: spbu-coding-2023/trees-8 -GITHUB_REF: refs/pull/10/merge -GITHUB_RUN_ID: 8437735818 +GITHUB_REF: refs/pull/11/merge +GITHUB_RUN_ID: 8458962685 CLOJURE_CLJSTYLE has been temporary disabled in MegaLinter, please use a previous MegaLinter version or wait for the next one ! @@ -23,39 +23,33 @@ To receive reports as email, please set variable EMAIL_REPORTER_EMAIL ::group::MegaLinter now collects the files to analyse (expand for details) Listing updated files in [/github/workspace] using git diff. Modified files: -lib/src/main/kotlin/bstrees/implementations/AVLTree.kt lib/src/main/kotlin/bstrees/implementations/RBTree.kt -lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt lib/src/main/kotlin/bstrees/implementations/Vertices.kt -lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt -lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt -lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt -lib/src/test/kotlin/trees/AVLTreeTest.kt megalinter-reports/megalinter.log - File extensions: .kt, .kts - Excluding .gitignored files [0]: -Kept [8] files on [9] found files +Kept [2] files on [3] found files +----MATCHING LINTERS-+----------+----------------+------------+ | Descriptor | Linter | Criteria | Matching files | Format/Fix | +------------+--------+----------+----------------+------------+ -| KOTLIN | ktlint | .kt|.kts | 8 | yes | +| KOTLIN | ktlint | .kt|.kts | 2 | yes | +------------+--------+----------+----------------+------------+ ::endgroup:: -::group::✅ Linted [KOTLIN] files with [ktlint] successfully - (11.15s) (expand for details) +::group::✅ Linted [KOTLIN] files with [ktlint] successfully - (3.29s) (expand for details) - Using [ktlint v1.2.1] https://megalinter.io/7.10.0/descriptors/kotlin_ktlint - MegaLinter key: [KOTLIN_KTLINT] - Rules config: identified by [ktlint] -- Number of files analyzed: [8] +- Number of files analyzed: [2] ::endgroup:: +----SUMMARY-+--------+------+-------+-------+--------+--------------+ | Descriptor | Linter | Mode | Files | Fixed | Errors | Elapsed time | +------------+--------+------+-------+-------+--------+--------------+ -| ✅ KOTLIN | ktlint | file | 8 | 5 | 0 | 11.15s | +| ✅ KOTLIN | ktlint | file | 2 | 2 | 0 | 3.29s | +------------+--------+------+-------+-------+--------+--------------+ -[Updated Sources Reporter] copied 7 fixed source files in folder /github/workspace/megalinter-reports/updated_sources. +[Updated Sources Reporter] copied 4 fixed source files in folder /github/workspace/megalinter-reports/updated_sources. Download it from artifacts then copy-paste it in your local repo to apply linters updates -[GitHub Comment Reporter] Posted summary as comment on spbu-coding-2023/trees-8 #PR10 +[GitHub Comment Reporter] Posted summary as comment on spbu-coding-2023/trees-8 #PR11 ✅ Successfully linted all files without errors diff --git a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/RBTree.kt b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/RBTree.kt index c1c9ef5..dad5435 100644 --- a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/RBTree.kt +++ b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/RBTree.kt @@ -1,3 +1,314 @@ package bstrees.implementations -class RBTree +import bstrees.templates.BalanceBSTreeTemplate + +class RBTree, V> : BalanceBSTreeTemplate>() { + override fun set( + key: K, + value: V, + ): V? { + val (currentVert, returnResult) = unbalancedSet(key, value) + balanceTreeAfterInsert(currentVert) + return returnResult + } + + private val red = RBVertex.Color.RED + private val black = RBVertex.Color.BLACK + + private fun rotateRight(vertex: RBVertex?) { + val parent = vertex?.parent + val leftChild = vertex?.left + vertex?.left = leftChild?.right + if (leftChild?.right != null) { + leftChild.right?.parent = vertex + } + leftChild?.right = vertex + vertex?.parent = leftChild + if (parent == null) { + root = leftChild + } else if (parent.left == vertex) { + parent.left = leftChild + } else if (parent.right == vertex) { + parent.right = leftChild + } + if (leftChild != null) { + leftChild.parent = parent + } + } + + private fun rotateLeft(vertex: RBVertex?) { + val parent = vertex?.parent + val rightChild = vertex?.right + vertex?.right = rightChild?.left + if (rightChild?.left != null) { + rightChild.left?.parent = vertex + } + rightChild?.left = vertex + vertex?.parent = rightChild + if (parent == null) { + root = rightChild + } else if (parent.left == vertex) { + parent.left = rightChild + } else if (parent.right == vertex) { + parent.right = rightChild + } + if (rightChild != null) { + rightChild.parent = parent + } + } + + private fun unbalancedSet( + key: K, + value: V, + ): Pair, V?> { + if (root == null) + { + val newVertex = RBVertex(key, value) + root = newVertex + size += 1 + return Pair(newVertex, null) + } + var currentVertex = root ?: throw IllegalStateException() + while (true) { + val result = currentVertex.key.compareTo(key) + if (result > 0) + { + if (currentVertex.left == null) + { + val newVertex = RBVertex(key, value) + newVertex.color = RBVertex.Color.RED + currentVertex.left = newVertex + newVertex.parent = currentVertex + size += 1 + return Pair(newVertex, null) + } + currentVertex = currentVertex.left ?: throw IllegalStateException() + } else if (result < 0) + { + if (currentVertex.right == null) + { + val newVertex = RBVertex(key, value) + newVertex.color = RBVertex.Color.RED + currentVertex.right = newVertex + newVertex.parent = currentVertex + size += 1 + return Pair(newVertex, null) + } + currentVertex = currentVertex.right ?: throw IllegalStateException() + } else { + val oldValue = currentVertex.value + currentVertex.value = value + return Pair(currentVertex, oldValue) + } + } + } + + private fun balanceTreeAfterInsert(vertex: RBVertex) { + var parent = vertex.parent + if (parent == null) + { + vertex.color = black + return + } + if (parent.color == black) { + return + } + val grandparent = parent.parent + + if (grandparent == null) { + parent.color = black + return + } + + val uncle = getVertexUncle(parent) + if (uncle != null && uncle.color == red) { + parent.color = black + grandparent.color = red + uncle.color = black + balanceTreeAfterInsert(grandparent) + } else if (parent == grandparent.left) { + if (vertex == parent.right) { + rotateLeft(parent) + parent = vertex + } + rotateRight(grandparent) + parent.color = black + grandparent.color = red + } else { + if (vertex == parent.left) { + rotateRight(parent) + parent = vertex + } + rotateLeft(grandparent) + parent.color = black + grandparent.color = red + } + } + + override fun remove(key: K): V? { + var vertex = root + while (vertex != null && vertex.key != key) { + if (key < vertex.key) { + vertex = vertex.left + } else { + vertex = vertex.right + } + } + if (vertex == null) { + return null + } + val replacedVertex: RBVertex? + val deletedVertexColor: RBVertex.Color + if (vertex.left == null || vertex.right == null) { + replacedVertex = deleteNullChild(vertex) + deletedVertexColor = vertex.color + } else { + val minVertex = findMin(vertex.right!!) + minVertex.color = vertex.color + minVertex.left = vertex.left + minVertex.right = vertex.right + replaceChild(vertex.parent, vertex, minVertex) + replacedVertex = deleteNullChild(minVertex) + deletedVertexColor = minVertex.color + } + + if (deletedVertexColor == RBVertex.Color.BLACK) { + balanceTreeAfterDelete(replacedVertex) + if (replacedVertex?.nullType == true) { + replaceChild(replacedVertex.parent, replacedVertex, null) + } + } + return replacedVertex?.value + } + + private fun balanceTreeAfterDelete(vertex: RBVertex?) { + if (vertex == root) { + vertex?.color = RBVertex.Color.BLACK + return + } + var brother = getBrother(vertex) + + if (brother?.color === RBVertex.Color.RED) { + manageRedBrother(vertex, brother) + brother = getBrother(vertex) + } + if (brother?.left?.color == RBVertex.Color.BLACK && brother.right?.color == RBVertex.Color.BLACK) { + brother.color = RBVertex.Color.RED + if (vertex?.parent?.color == RBVertex.Color.RED) { + vertex.parent?.color = RBVertex.Color.BLACK + } else { + balanceTreeAfterDelete(vertex?.parent) + } + } else { + manageBlackRedOne(vertex, brother) + } + } + + private fun getBrother(vertex: RBVertex?): RBVertex? { + val parent = vertex?.parent + return if (vertex == parent?.left) { + parent?.right + } else if (vertex == parent?.right) { + parent?.left + } else { + throw IllegalStateException() + } + } + + private fun manageBlackRedOne( + vertex: RBVertex?, + argBrother: RBVertex?, + ) { + var brother = argBrother + if (vertex == vertex?.parent?.left && brother?.right?.color == black) { + brother.left?.color = black + brother.color = red + rotateRight(brother) + brother = vertex?.parent?.right + } else if (vertex != vertex?.parent?.left && brother?.left?.color == black) { + brother.right?.color = black + brother.color = red + rotateLeft(brother) + brother = vertex?.parent?.left + } + brother?.color = vertex?.parent!!.color + vertex.parent?.color = black + if (vertex == vertex.parent?.left) { + brother?.right?.color = black + rotateLeft(vertex.parent) + } else { + brother?.left?.color = black + rotateRight(vertex.parent) + } + } + + private fun manageRedBrother( + vertex: RBVertex?, + brother: RBVertex, + ) { + brother.color = RBVertex.Color.BLACK + vertex?.parent?.color = RBVertex.Color.RED + if (vertex === vertex?.parent?.left) { + rotateLeft(vertex?.parent) + } else { + rotateRight(vertex?.parent) + } + } + + private fun replaceChild( + parent: RBVertex?, + oldChild: RBVertex, + newChild: RBVertex?, + ) { + if (parent == null) { + root = newChild + } else if (parent.left === oldChild) { + parent.left = newChild + } else if (parent.right === oldChild) { + parent.right = newChild + } else { + throw IllegalStateException() + } + if (newChild != null) { + newChild.parent = parent + } + } + + private fun deleteNullChild(vertex: RBVertex): RBVertex? { + if (vertex.left != null) { + replaceChild(vertex.parent, vertex, vertex.left) + return vertex.left + } else if (vertex.right != null) { + replaceChild(vertex.parent, vertex, vertex.right) + return vertex.right + } else { + var newChild: RBVertex? = RBVertex(vertex.key, vertex.value) + if (vertex.color == RBVertex.Color.BLACK) { + newChild?.nullType = true + } else { + newChild = null + } + replaceChild(vertex.parent, vertex, newChild) + return newChild + } + } + + private fun findMin(argVertex: RBVertex): RBVertex { + var vertex = argVertex + while (vertex.left != null) { + vertex = vertex.left!! + } + return vertex + } + + private fun getVertexUncle(parent: RBVertex): RBVertex? { + val grandparent = parent.parent + return if (grandparent?.left == parent) { + grandparent.right + } else if (grandparent?.right == parent) { + grandparent.left + } else { + throw IllegalStateException("Grandparent/Parent dependency mistake") + } + } +} diff --git a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/Vertices.kt b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/Vertices.kt index c13eaac..542ef83 100644 --- a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/Vertices.kt +++ b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/Vertices.kt @@ -6,10 +6,17 @@ class SimpleVertex, V>(key: K, value: V) : VertexTemplate, V>(key: K, value: V) : VertexTemplate>(key, value) { var diffHeight: Int = 0 + internal set(value) { + if (value !in -2..2) { + throw IllegalArgumentException("difference of heights can't be out of [-2,2]") + } + field = value + } } class RBVertex, V>(key: K, value: V) : VertexTemplate>(key, value) { var color: Color = Color.BLACK + var nullType = true enum class Color { BLACK, diff --git a/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log b/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log index 9913267..5575c56 100644 --- a/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log +++ b/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log @@ -2,11 +2,5 @@ Results of ktlint linter (version 1.2.1) See documentation on https://megalinter.io/7.10.0/descriptors/kotlin_ktlint/ ----------------------------------------------- -✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/AVLTree.kt - FIXED ✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/RBTree.kt - FIXED -✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt - FIXED -✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/Vertices.kt -✅ [SUCCESS] lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt -✅ [SUCCESS] lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt - FIXED -✅ [SUCCESS] lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt -✅ [SUCCESS] lib/src/test/kotlin/trees/AVLTreeTest.kt - FIXED +✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/Vertices.kt - FIXED diff --git a/megalinter-reports/updated_sources/megalinter-reports/megalinter.log b/megalinter-reports/updated_sources/megalinter-reports/megalinter.log index f0318f3..6d16308 100644 --- a/megalinter-reports/updated_sources/megalinter-reports/megalinter.log +++ b/megalinter-reports/updated_sources/megalinter-reports/megalinter.log @@ -11,8 +11,8 @@ The MegaLinter documentation can be found at: ::group::MegaLinter initialization (expand for details) MegaLinter will analyze workspace [/github/workspace] GITHUB_REPOSITORY: spbu-coding-2023/trees-8 -GITHUB_REF: refs/pull/10/merge -GITHUB_RUN_ID: 8437735818 +GITHUB_REF: refs/pull/11/merge +GITHUB_RUN_ID: 8458962685 CLOJURE_CLJSTYLE has been temporary disabled in MegaLinter, please use a previous MegaLinter version or wait for the next one ! @@ -23,35 +23,29 @@ To receive reports as email, please set variable EMAIL_REPORTER_EMAIL ::group::MegaLinter now collects the files to analyse (expand for details) Listing updated files in [/github/workspace] using git diff. Modified files: -lib/src/main/kotlin/bstrees/implementations/AVLTree.kt lib/src/main/kotlin/bstrees/implementations/RBTree.kt -lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt lib/src/main/kotlin/bstrees/implementations/Vertices.kt -lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt -lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt -lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt -lib/src/test/kotlin/trees/AVLTreeTest.kt megalinter-reports/megalinter.log - File extensions: .kt, .kts - Excluding .gitignored files [0]: -Kept [8] files on [9] found files +Kept [2] files on [3] found files +----MATCHING LINTERS-+----------+----------------+------------+ | Descriptor | Linter | Criteria | Matching files | Format/Fix | +------------+--------+----------+----------------+------------+ -| KOTLIN | ktlint | .kt|.kts | 8 | yes | +| KOTLIN | ktlint | .kt|.kts | 2 | yes | +------------+--------+----------+----------------+------------+ ::endgroup:: -::group::✅ Linted [KOTLIN] files with [ktlint] successfully - (11.15s) (expand for details) +::group::✅ Linted [KOTLIN] files with [ktlint] successfully - (3.29s) (expand for details) - Using [ktlint v1.2.1] https://megalinter.io/7.10.0/descriptors/kotlin_ktlint - MegaLinter key: [KOTLIN_KTLINT] - Rules config: identified by [ktlint] -- Number of files analyzed: [8] +- Number of files analyzed: [2] ::endgroup:: +----SUMMARY-+--------+------+-------+-------+--------+--------------+ | Descriptor | Linter | Mode | Files | Fixed | Errors | Elapsed time | +------------+--------+------+-------+-------+--------+--------------+ -| ✅ KOTLIN | ktlint | file | 8 | 5 | 0 | 11.15s | +| ✅ KOTLIN | ktlint | file | 2 | 2 | 0 | 3.29s | +------------+--------+------+-------+-------+--------+--------------+ From 23f0f9ccd4feb22bb17ff9fa31ccb4ed61fc2eaa Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Thu, 28 Mar 2024 19:41:40 +0300 Subject: [PATCH 042/108] Add coverage test --- .github/workflows/coverage.yml | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 .github/workflows/coverage.yml diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 0000000..2fd26bb --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,33 @@ +name: Coverage Test + +on: + push: + pull_request: + branches: + - main + +jobs: + Coverage: + runs-on: ubuntu-latest + + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'oracle' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 + + - name: Run Test Coverage + run: ./gradlew jacocoTestReport + + - name: Jacoco Test Coverage Report + uses: cicirello/jacoco-badge-generator@v2.8.0 + with: + generate-branches-badge: true + jacoco-csv-file: lib/build/jacoco/report.csv \ No newline at end of file From 511a6f8fa036ca22d14d35eb592d686d67a52407 Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Thu, 28 Mar 2024 19:49:21 +0300 Subject: [PATCH 043/108] Add coverage --- .github/workflows/coverage.yml | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 .github/workflows/coverage.yml diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 0000000..08f0546 --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,33 @@ +name: Coverage Test + +on: + push: + pull_request: + branches: + - main + +jobs: + Coverage: + runs-on: ubuntu-latest + + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 + + - name: Run Test Coverage + run: ./gradlew jacocoTestReport + + - name: Jacoco Test Coverage Report + uses: cicirello/jacoco-badge-generator@v2.8.0 + with: + generate-branches-badge: true + jacoco-csv-file: lib/build/jacoco/report.csv \ No newline at end of file From b3adb52881850ab79eba05592100a34cdb286efb Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Thu, 28 Mar 2024 20:20:37 +0300 Subject: [PATCH 044/108] Add plugin in `build.gradle.kts` --- .github/workflows/coverage.yml | 12 +++++++++++- lib/build.gradle.kts | 23 +++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 08f0546..f174c58 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -30,4 +30,14 @@ jobs: uses: cicirello/jacoco-badge-generator@v2.8.0 with: generate-branches-badge: true - jacoco-csv-file: lib/build/jacoco/report.csv \ No newline at end of file + jacoco-csv-file: lib/build/jacoco/report.csv + + - name: Add coverage to PR + id: jacoco + uses: madrapps/jacoco-report@v1.6.1 + with: + paths: | + ${{ github.workspace }}/**/build/reports/jacoco/prodNormalDebugCoverage/prodNormalDebugCoverage.xml, + ${{ github.workspace }}/**/build/reports/jacoco/**/debugCoverage.xml + token: ${{ secrets.GITHUB_TOKEN }} + min-coverage-overall: 40 diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index f6cad6d..8b95e8b 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -11,6 +11,8 @@ plugins { // Apply the java-library plugin for API and implementation separation. `java-library` + jacoco + `jacoco-report-aggregation` } repositories { @@ -45,3 +47,24 @@ tasks.named("test") { // Use JUnit Platform for unit tests. useJUnitPlatform() } + +tasks.test { + finalizedBy(tasks.jacocoTestReport) +} +tasks.jacocoTestReport { + dependsOn(tasks.test) +} + +jacoco { + toolVersion = "0.8.11" + reportsDirectory = layout.buildDirectory.dir("lib/build/jacoco").get().asFile +} + +tasks.jacocoTestReport { + reports { + xml.required = true + csv.required = true + html.outputLocation = layout.buildDirectory.dir("jacocoHtml").get().asFile + csv.outputLocation = layout.buildDirectory.file("jacoco/report.csv") + } +} From 92a50c7162693e37b612fdbe52146a7045123c34 Mon Sep 17 00:00:00 2001 From: Azamat Ishbaev <143432879+odiumuniverse@users.noreply.github.com> Date: Thu, 28 Mar 2024 20:25:43 +0300 Subject: [PATCH 045/108] Add coverage action --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 59b89d4..94eff44 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ ![CI_Test](https://github.com/spbu-coding-2023/trees-8/actions/workflows/CI_Test.yml/badge.svg) [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) [![CodeFactor](https://www.codefactor.io/repository/github/spbu-coding-2023/trees-8/badge)](https://www.codefactor.io/repository/github/spbu-coding-2023/trees-8) +[![Coverage Test](https://github.com/spbu-coding-2023/trees-8/actions/workflows/coverage.yml/badge.svg)](https://github.com/spbu-coding-2023/trees-8/actions/workflows/coverage.yml) # Binary Trees Project From fc4857b1a314756f06b1ff9b43de22a7d3e8e2f0 Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Thu, 28 Mar 2024 20:34:55 +0300 Subject: [PATCH 046/108] small change in coverage.yml --- .github/workflows/coverage.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index f174c58..d8cb6c9 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -41,3 +41,4 @@ jobs: ${{ github.workspace }}/**/build/reports/jacoco/**/debugCoverage.xml token: ${{ secrets.GITHUB_TOKEN }} min-coverage-overall: 40 + update-comment: true From 41d9976ee1feb86c6e91c140667ae68361b51eae Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Sat, 30 Mar 2024 22:32:03 +0300 Subject: [PATCH 047/108] Added .editorconfig --- .editorconfig | 4 ++++ lib/src/main/kotlin/bstrees/implementations/AVLTree.kt | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..367d04d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +root = true + +{*.{kt,kts}} +ktlint_code_style = intellij_idea \ No newline at end of file diff --git a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt index 77f2377..ad5092b 100644 --- a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt @@ -1,7 +1,7 @@ package bstrees.implementations import bstrees.templates.BalanceBSTreeTemplate - + class AVLTree, V> : BalanceBSTreeTemplate>() { public override operator fun set( key: K, From 56f1396aa7da1d05b3a7667e766110f99227ffeb Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Sat, 30 Mar 2024 22:45:59 +0300 Subject: [PATCH 048/108] Fix .editorconfig --- .editorconfig | 5 +++-- lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.editorconfig b/.editorconfig index 367d04d..3391ef2 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,4 +1,5 @@ root = true -{*.{kt,kts}} -ktlint_code_style = intellij_idea \ No newline at end of file +[*.{kt,kts}] +ktlint_code_style = intellij_idea +max_line_length = 120 \ No newline at end of file diff --git a/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt b/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt index 2fe714c..a6a8cd6 100644 --- a/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt +++ b/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt @@ -2,6 +2,7 @@ package bstrees.templates import java.util.Stack + abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate> { var root: Vertex_t? = null protected set From 68bd28f38349d39818d6e3ae3b0482c4b071e137 Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Sat, 30 Mar 2024 22:56:07 +0300 Subject: [PATCH 049/108] Code style fixes --- .../kotlin/bstrees/implementations/AVLTree.kt | 12 +-- .../kotlin/bstrees/implementations/RBTree.kt | 93 ++++++++----------- 2 files changed, 40 insertions(+), 65 deletions(-) diff --git a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt index ad5092b..57a2bf1 100644 --- a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt @@ -1,12 +1,9 @@ package bstrees.implementations import bstrees.templates.BalanceBSTreeTemplate - + class AVLTree, V> : BalanceBSTreeTemplate>() { - public override operator fun set( - key: K, - value: V, - ): V? { + public override operator fun set(key: K, value: V): V? { val (currentVert, oldValue) = setWithoutBalance(key, value) if (oldValue == null) { size += 1 @@ -21,10 +18,7 @@ class AVLTree, V> : BalanceBSTreeTemplate, V?> { + private fun setWithoutBalance(key: K, value: V): Pair, V?> { if (root == null) { val newVertex = AVLVertex(key, value) root = newVertex diff --git a/lib/src/main/kotlin/bstrees/implementations/RBTree.kt b/lib/src/main/kotlin/bstrees/implementations/RBTree.kt index dad5435..449b4f6 100644 --- a/lib/src/main/kotlin/bstrees/implementations/RBTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/RBTree.kt @@ -3,10 +3,7 @@ package bstrees.implementations import bstrees.templates.BalanceBSTreeTemplate class RBTree, V> : BalanceBSTreeTemplate>() { - override fun set( - key: K, - value: V, - ): V? { + override fun set(key: K, value: V): V? { val (currentVert, returnResult) = unbalancedSet(key, value) balanceTreeAfterInsert(currentVert) return returnResult @@ -57,45 +54,37 @@ class RBTree, V> : BalanceBSTreeTemplate> } } - private fun unbalancedSet( - key: K, - value: V, - ): Pair, V?> { - if (root == null) - { - val newVertex = RBVertex(key, value) - root = newVertex - size += 1 - return Pair(newVertex, null) - } + private fun unbalancedSet(key: K, value: V): Pair, V?> { + if (root == null) { + val newVertex = RBVertex(key, value) + root = newVertex + size += 1 + return Pair(newVertex, null) + } var currentVertex = root ?: throw IllegalStateException() while (true) { val result = currentVertex.key.compareTo(key) - if (result > 0) - { - if (currentVertex.left == null) - { - val newVertex = RBVertex(key, value) - newVertex.color = RBVertex.Color.RED - currentVertex.left = newVertex - newVertex.parent = currentVertex - size += 1 - return Pair(newVertex, null) - } - currentVertex = currentVertex.left ?: throw IllegalStateException() - } else if (result < 0) - { - if (currentVertex.right == null) - { - val newVertex = RBVertex(key, value) - newVertex.color = RBVertex.Color.RED - currentVertex.right = newVertex - newVertex.parent = currentVertex - size += 1 - return Pair(newVertex, null) - } - currentVertex = currentVertex.right ?: throw IllegalStateException() - } else { + if (result > 0) { + if (currentVertex.left == null) { + val newVertex = RBVertex(key, value) + newVertex.color = RBVertex.Color.RED + currentVertex.left = newVertex + newVertex.parent = currentVertex + size += 1 + return Pair(newVertex, null) + } + currentVertex = currentVertex.left ?: throw IllegalStateException() + } else if (result < 0) { + if (currentVertex.right == null) { + val newVertex = RBVertex(key, value) + newVertex.color = RBVertex.Color.RED + currentVertex.right = newVertex + newVertex.parent = currentVertex + size += 1 + return Pair(newVertex, null) + } + currentVertex = currentVertex.right ?: throw IllegalStateException() + } else { val oldValue = currentVertex.value currentVertex.value = value return Pair(currentVertex, oldValue) @@ -103,13 +92,12 @@ class RBTree, V> : BalanceBSTreeTemplate> } } - private fun balanceTreeAfterInsert(vertex: RBVertex) { + private fun balanceTreeAfterInsert(vertex: RBVertex) { var parent = vertex.parent - if (parent == null) - { - vertex.color = black - return - } + if (parent == null) { + vertex.color = black + return + } if (parent.color == black) { return } @@ -145,7 +133,7 @@ class RBTree, V> : BalanceBSTreeTemplate> } } - override fun remove(key: K): V? { + override fun remove(key: K): V? { var vertex = root while (vertex != null && vertex.key != key) { if (key < vertex.key) { @@ -242,10 +230,7 @@ class RBTree, V> : BalanceBSTreeTemplate> } } - private fun manageRedBrother( - vertex: RBVertex?, - brother: RBVertex, - ) { + private fun manageRedBrother(vertex: RBVertex?, brother: RBVertex) { brother.color = RBVertex.Color.BLACK vertex?.parent?.color = RBVertex.Color.RED if (vertex === vertex?.parent?.left) { @@ -255,11 +240,7 @@ class RBTree, V> : BalanceBSTreeTemplate> } } - private fun replaceChild( - parent: RBVertex?, - oldChild: RBVertex, - newChild: RBVertex?, - ) { + private fun replaceChild(parent: RBVertex?, oldChild: RBVertex, newChild: RBVertex?) { if (parent == null) { root = newChild } else if (parent.left === oldChild) { From 9f9bbd75d1ea75e9a0b31451e7b60ff0cb9fd84e Mon Sep 17 00:00:00 2001 From: Ycyken Date: Sat, 30 Mar 2024 20:03:12 +0000 Subject: [PATCH 050/108] [MegaLinter] Apply linters fixes --- .../kotlin/bstrees/implementations/RBTree.kt | 5 +- .../bstrees/templates/BSTreeTemplate.kt | 21 +--- .../linters_logs/SUCCESS-KOTLIN_KTLINT.log | 3 +- megalinter-reports/megalinter.log | 20 ++-- .../kotlin/bstrees/implementations/RBTree.kt | 98 +++++++------------ .../bstrees/templates/BSTreeTemplate.kt | 48 ++++----- .../linters_logs/SUCCESS-KOTLIN_KTLINT.log | 3 +- .../megalinter-reports/megalinter.log | 18 ++-- 8 files changed, 89 insertions(+), 127 deletions(-) diff --git a/lib/src/main/kotlin/bstrees/implementations/RBTree.kt b/lib/src/main/kotlin/bstrees/implementations/RBTree.kt index 449b4f6..2580c31 100644 --- a/lib/src/main/kotlin/bstrees/implementations/RBTree.kt +++ b/lib/src/main/kotlin/bstrees/implementations/RBTree.kt @@ -203,10 +203,7 @@ class RBTree, V> : BalanceBSTreeTemplate> } } - private fun manageBlackRedOne( - vertex: RBVertex?, - argBrother: RBVertex?, - ) { + private fun manageBlackRedOne(vertex: RBVertex?, argBrother: RBVertex?) { var brother = argBrother if (vertex == vertex?.parent?.left && brother?.right?.color == black) { brother.left?.color = black diff --git a/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt b/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt index a6a8cd6..9361017 100644 --- a/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt +++ b/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt @@ -2,7 +2,6 @@ package bstrees.templates import java.util.Stack - abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate> { var root: Vertex_t? = null protected set @@ -20,19 +19,13 @@ abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate, V> : BalanceBSTreeTemplate>() { - override fun set( - key: K, - value: V, - ): V? { + override fun set(key: K, value: V): V? { val (currentVert, returnResult) = unbalancedSet(key, value) balanceTreeAfterInsert(currentVert) return returnResult @@ -57,45 +54,37 @@ class RBTree, V> : BalanceBSTreeTemplate> } } - private fun unbalancedSet( - key: K, - value: V, - ): Pair, V?> { - if (root == null) - { - val newVertex = RBVertex(key, value) - root = newVertex - size += 1 - return Pair(newVertex, null) - } + private fun unbalancedSet(key: K, value: V): Pair, V?> { + if (root == null) { + val newVertex = RBVertex(key, value) + root = newVertex + size += 1 + return Pair(newVertex, null) + } var currentVertex = root ?: throw IllegalStateException() while (true) { val result = currentVertex.key.compareTo(key) - if (result > 0) - { - if (currentVertex.left == null) - { - val newVertex = RBVertex(key, value) - newVertex.color = RBVertex.Color.RED - currentVertex.left = newVertex - newVertex.parent = currentVertex - size += 1 - return Pair(newVertex, null) - } - currentVertex = currentVertex.left ?: throw IllegalStateException() - } else if (result < 0) - { - if (currentVertex.right == null) - { - val newVertex = RBVertex(key, value) - newVertex.color = RBVertex.Color.RED - currentVertex.right = newVertex - newVertex.parent = currentVertex - size += 1 - return Pair(newVertex, null) - } - currentVertex = currentVertex.right ?: throw IllegalStateException() - } else { + if (result > 0) { + if (currentVertex.left == null) { + val newVertex = RBVertex(key, value) + newVertex.color = RBVertex.Color.RED + currentVertex.left = newVertex + newVertex.parent = currentVertex + size += 1 + return Pair(newVertex, null) + } + currentVertex = currentVertex.left ?: throw IllegalStateException() + } else if (result < 0) { + if (currentVertex.right == null) { + val newVertex = RBVertex(key, value) + newVertex.color = RBVertex.Color.RED + currentVertex.right = newVertex + newVertex.parent = currentVertex + size += 1 + return Pair(newVertex, null) + } + currentVertex = currentVertex.right ?: throw IllegalStateException() + } else { val oldValue = currentVertex.value currentVertex.value = value return Pair(currentVertex, oldValue) @@ -103,13 +92,12 @@ class RBTree, V> : BalanceBSTreeTemplate> } } - private fun balanceTreeAfterInsert(vertex: RBVertex) { + private fun balanceTreeAfterInsert(vertex: RBVertex) { var parent = vertex.parent - if (parent == null) - { - vertex.color = black - return - } + if (parent == null) { + vertex.color = black + return + } if (parent.color == black) { return } @@ -145,7 +133,7 @@ class RBTree, V> : BalanceBSTreeTemplate> } } - override fun remove(key: K): V? { + override fun remove(key: K): V? { var vertex = root while (vertex != null && vertex.key != key) { if (key < vertex.key) { @@ -215,10 +203,7 @@ class RBTree, V> : BalanceBSTreeTemplate> } } - private fun manageBlackRedOne( - vertex: RBVertex?, - argBrother: RBVertex?, - ) { + private fun manageBlackRedOne(vertex: RBVertex?, argBrother: RBVertex?) { var brother = argBrother if (vertex == vertex?.parent?.left && brother?.right?.color == black) { brother.left?.color = black @@ -242,10 +227,7 @@ class RBTree, V> : BalanceBSTreeTemplate> } } - private fun manageRedBrother( - vertex: RBVertex?, - brother: RBVertex, - ) { + private fun manageRedBrother(vertex: RBVertex?, brother: RBVertex) { brother.color = RBVertex.Color.BLACK vertex?.parent?.color = RBVertex.Color.RED if (vertex === vertex?.parent?.left) { @@ -255,11 +237,7 @@ class RBTree, V> : BalanceBSTreeTemplate> } } - private fun replaceChild( - parent: RBVertex?, - oldChild: RBVertex, - newChild: RBVertex?, - ) { + private fun replaceChild(parent: RBVertex?, oldChild: RBVertex, newChild: RBVertex?) { if (parent == null) { root = newChild } else if (parent.left === oldChild) { diff --git a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt index 5e9c759..9361017 100644 --- a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt +++ b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt @@ -4,6 +4,7 @@ import java.util.Stack abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate> { var root: Vertex_t? = null + protected set var size: Int = 0 protected set(value) { if (value >= 0) { @@ -18,19 +19,13 @@ abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate cur = cur.left - result > 0 -> cur = cur.right - result == 0 -> return cur.value - } - } - return null + return vertByKey(key)?.value } /** * Returns the value corresponding to the given [key], or [defaultValue] if such a key is not present in the map. */ - public fun getOrDefault( - key: K, - defaultValue: Any, - ): Any { + public fun getOrDefault(key: K, defaultValue: Any): Any { return get(key) ?: defaultValue } @@ -69,10 +52,7 @@ abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate cur.key) { + cur = cur.right + } else if (key == cur.key) { + break + } + } + return cur + } + public fun isEmpty(): Boolean { return size == 0 } diff --git a/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log b/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log index 5575c56..8642d87 100644 --- a/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log +++ b/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log @@ -2,5 +2,6 @@ Results of ktlint linter (version 1.2.1) See documentation on https://megalinter.io/7.10.0/descriptors/kotlin_ktlint/ ----------------------------------------------- +✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/AVLTree.kt ✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/RBTree.kt - FIXED -✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/Vertices.kt - FIXED +✅ [SUCCESS] lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt - FIXED diff --git a/megalinter-reports/updated_sources/megalinter-reports/megalinter.log b/megalinter-reports/updated_sources/megalinter-reports/megalinter.log index 6d16308..72408b8 100644 --- a/megalinter-reports/updated_sources/megalinter-reports/megalinter.log +++ b/megalinter-reports/updated_sources/megalinter-reports/megalinter.log @@ -11,8 +11,8 @@ The MegaLinter documentation can be found at: ::group::MegaLinter initialization (expand for details) MegaLinter will analyze workspace [/github/workspace] GITHUB_REPOSITORY: spbu-coding-2023/trees-8 -GITHUB_REF: refs/pull/11/merge -GITHUB_RUN_ID: 8458962685 +GITHUB_REF: refs/pull/13/merge +GITHUB_RUN_ID: 8493051201 CLOJURE_CLJSTYLE has been temporary disabled in MegaLinter, please use a previous MegaLinter version or wait for the next one ! @@ -23,29 +23,31 @@ To receive reports as email, please set variable EMAIL_REPORTER_EMAIL ::group::MegaLinter now collects the files to analyse (expand for details) Listing updated files in [/github/workspace] using git diff. Modified files: +.editorconfig +lib/src/main/kotlin/bstrees/implementations/AVLTree.kt lib/src/main/kotlin/bstrees/implementations/RBTree.kt -lib/src/main/kotlin/bstrees/implementations/Vertices.kt +lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt megalinter-reports/megalinter.log - File extensions: .kt, .kts - Excluding .gitignored files [0]: -Kept [2] files on [3] found files +Kept [3] files on [5] found files +----MATCHING LINTERS-+----------+----------------+------------+ | Descriptor | Linter | Criteria | Matching files | Format/Fix | +------------+--------+----------+----------------+------------+ -| KOTLIN | ktlint | .kt|.kts | 2 | yes | +| KOTLIN | ktlint | .kt|.kts | 3 | yes | +------------+--------+----------+----------------+------------+ ::endgroup:: -::group::✅ Linted [KOTLIN] files with [ktlint] successfully - (3.29s) (expand for details) +::group::✅ Linted [KOTLIN] files with [ktlint] successfully - (4.57s) (expand for details) - Using [ktlint v1.2.1] https://megalinter.io/7.10.0/descriptors/kotlin_ktlint - MegaLinter key: [KOTLIN_KTLINT] - Rules config: identified by [ktlint] -- Number of files analyzed: [2] +- Number of files analyzed: [3] ::endgroup:: +----SUMMARY-+--------+------+-------+-------+--------+--------------+ | Descriptor | Linter | Mode | Files | Fixed | Errors | Elapsed time | +------------+--------+------+-------+-------+--------+--------------+ -| ✅ KOTLIN | ktlint | file | 2 | 2 | 0 | 3.29s | +| ✅ KOTLIN | ktlint | file | 3 | 2 | 0 | 4.57s | +------------+--------+------+-------+-------+--------+--------------+ From 1384a6d8aafef2e977dcb88d9782d4e354d0cd72 Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Sun, 31 Mar 2024 01:24:06 +0300 Subject: [PATCH 051/108] Add tests for avl tree -add 6 double rotate tests with all cases -add 1 remove test --- lib/src/test/kotlin/trees/AVLTreeTest.kt | 105 ++++++++++++++++++++++- 1 file changed, 103 insertions(+), 2 deletions(-) diff --git a/lib/src/test/kotlin/trees/AVLTreeTest.kt b/lib/src/test/kotlin/trees/AVLTreeTest.kt index 712bf2d..868e179 100644 --- a/lib/src/test/kotlin/trees/AVLTreeTest.kt +++ b/lib/src/test/kotlin/trees/AVLTreeTest.kt @@ -117,7 +117,7 @@ class AVLTreeTest { } @Test - fun `remove with left vertex`() { + fun `remove root of left subtree with existing left vertex`() { val keys = intArrayOf(0, -1, 1, -2) for (key in keys) avlTree[key] = key avlTree.remove(-1) @@ -132,6 +132,21 @@ class AVLTreeTest { checkTreeInvariant(avlTree.root) } + @Test + fun `remove root of right subtree with existing left vertex`() { + val keys = intArrayOf(0, -1, 2, 1) + for (key in keys) avlTree[key] = key + avlTree.remove(2) + + val expectedResult = arrayOf(0, -1, null, 1) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, actualResult, + "Tree must save all other vertices after remove root of right subtree with existing left vertex" + ) + checkTreeInvariant(avlTree.root) + } + @Test fun `remove with right subtree of height 1`() { val keys = intArrayOf(0, -1, 3, 1, 2) @@ -167,7 +182,7 @@ class AVLTreeTest { } @Test - fun `remove with necessary double rotate`() { + fun `remove with double rotate`() { val keys = intArrayOf(5, 0, 7, -1, 2, 6, 9, -2, 1, 3, 8, 4) for (key in keys) avlTree[key] = key avlTree.remove(7) @@ -320,4 +335,90 @@ class AVLTreeTest { // / \ / \ / \ / \ / \ // 0 2 4 6 0 2 4 6 4 6 } + + @Test + fun `rotate right-left, right diffHeight is 1, right-left diffHeight is 1`() { + val keys = intArrayOf(1, 0, 4, 3, 5, 2) + for (key in keys) avlTree[key] = key + + val expectedResult = Array(keys.size, { i -> keys[i] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, actualResult, + "Get must return corresponding values after right-left rotate with right.left.diffHeight = 1" + ) + checkTreeInvariant(avlTree.root) + } + + @Test + fun `rotate right-left, right diffHeight is 1, right-left diffHeight is 0`() { + val keys = intArrayOf(2, 1, 6, 0, 4, 7, 3, 5) + for (key in keys) avlTree[key] = key + avlTree.remove(0) + + val expectedResult: Array = arrayOf(2, 1, 6, null, 4, 7, 3, 5) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, actualResult, + "Get must return corresponding values after right-left rotate with right.left.diffHeight = 0" + ) + checkTreeInvariant(avlTree.root) + } + + @Test + fun `rotate right-left, right diffHeight is 1, right-left diffHeight is -1`() { + val keys = intArrayOf(1, 0, 4, 2, 5, 3) + for (key in keys) avlTree[key] = key + + val expectedResult = Array(keys.size, { i -> keys[i] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, actualResult, + "Get must return corresponding values after right-left rotate with right.left.diffHeight = -1" + ) + checkTreeInvariant(avlTree.root) + } + + @Test + fun `rotate left-right, left diffHeight is -1, left-right diffHeight is -1`() { + val keys = intArrayOf(4, 1, 5, 0, 2, 3) + for (key in keys) avlTree[key] = key + + val expectedResult = Array(keys.size, { i -> keys[i] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, actualResult, + "Get must return corresponding values after left-right rotate with left.right.diffHeight = -1" + ) + checkTreeInvariant(avlTree.root) + } + + @Test + fun `rotate left-right, left diffHeight is -1, left-right diffHeight is 0`() { + val keys = intArrayOf(5, 1, 6, 0, 3, 7, 2, 4) + for (key in keys) avlTree[key] = key + avlTree.remove(7) + + val expectedResult = arrayOf(5, 1, 6, 0, 3, null, 2, 4) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, actualResult, + "Get must return corresponding values after left-right rotate with left.right.diffHeight = 0" + ) + checkTreeInvariant(avlTree.root) + } + + @Test + fun `rotate left-right, left diffHeight is -1, left-right diffHeight is 1`() { + val keys = intArrayOf(4, 1, 5, 0, 3, 2) + for (key in keys) avlTree[key] = key + + val expectedResult = Array(keys.size, { i -> keys[i] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, actualResult, + "Get must return corresponding values after left-right rotate with left.right.diffHeight = 1" + ) + checkTreeInvariant(avlTree.root) + } } From 8fa50e96f0b763113349a0e48c483ddc0abeffaf Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Sun, 31 Mar 2024 13:47:18 +0300 Subject: [PATCH 052/108] Add visualisation for 1 avl tree test --- lib/src/test/kotlin/trees/AVLTreeTest.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/src/test/kotlin/trees/AVLTreeTest.kt b/lib/src/test/kotlin/trees/AVLTreeTest.kt index 868e179..f74f2c7 100644 --- a/lib/src/test/kotlin/trees/AVLTreeTest.kt +++ b/lib/src/test/kotlin/trees/AVLTreeTest.kt @@ -348,6 +348,14 @@ class AVLTreeTest { "Get must return corresponding values after right-left rotate with right.left.diffHeight = 1" ) checkTreeInvariant(avlTree.root) + +// 1 1 3 +// / \ / \ / \ +// 0 4 0 3 1 4 +// / \ --> / \ --> / \ \ +// 3 5 2 4 0 2 5 +// / \ +// 2 5 } @Test From f87eda7f03ae007f2ef47e88380b871e7c7c2daf Mon Sep 17 00:00:00 2001 From: Ycyken Date: Sun, 31 Mar 2024 10:53:39 +0000 Subject: [PATCH 053/108] [MegaLinter] Apply linters fixes --- lib/src/test/kotlin/trees/AVLTreeTest.kt | 35 +++-- .../linters_logs/SUCCESS-KOTLIN_KTLINT.log | 4 +- megalinter-reports/megalinter.log | 23 ++-- .../lib/src/test/kotlin/trees/AVLTreeTest.kt | 120 +++++++++++++++++- .../linters_logs/SUCCESS-KOTLIN_KTLINT.log | 4 +- .../megalinter-reports/megalinter.log | 19 ++- 6 files changed, 159 insertions(+), 46 deletions(-) diff --git a/lib/src/test/kotlin/trees/AVLTreeTest.kt b/lib/src/test/kotlin/trees/AVLTreeTest.kt index f74f2c7..9f2ec3a 100644 --- a/lib/src/test/kotlin/trees/AVLTreeTest.kt +++ b/lib/src/test/kotlin/trees/AVLTreeTest.kt @@ -141,8 +141,9 @@ class AVLTreeTest { val expectedResult = arrayOf(0, -1, null, 1) val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( - expectedResult, actualResult, - "Tree must save all other vertices after remove root of right subtree with existing left vertex" + expectedResult, + actualResult, + "Tree must save all other vertices after remove root of right subtree with existing left vertex", ) checkTreeInvariant(avlTree.root) } @@ -344,8 +345,9 @@ class AVLTreeTest { val expectedResult = Array(keys.size, { i -> keys[i] }) val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( - expectedResult, actualResult, - "Get must return corresponding values after right-left rotate with right.left.diffHeight = 1" + expectedResult, + actualResult, + "Get must return corresponding values after right-left rotate with right.left.diffHeight = 1", ) checkTreeInvariant(avlTree.root) @@ -367,8 +369,9 @@ class AVLTreeTest { val expectedResult: Array = arrayOf(2, 1, 6, null, 4, 7, 3, 5) val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( - expectedResult, actualResult, - "Get must return corresponding values after right-left rotate with right.left.diffHeight = 0" + expectedResult, + actualResult, + "Get must return corresponding values after right-left rotate with right.left.diffHeight = 0", ) checkTreeInvariant(avlTree.root) } @@ -381,8 +384,9 @@ class AVLTreeTest { val expectedResult = Array(keys.size, { i -> keys[i] }) val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( - expectedResult, actualResult, - "Get must return corresponding values after right-left rotate with right.left.diffHeight = -1" + expectedResult, + actualResult, + "Get must return corresponding values after right-left rotate with right.left.diffHeight = -1", ) checkTreeInvariant(avlTree.root) } @@ -395,8 +399,9 @@ class AVLTreeTest { val expectedResult = Array(keys.size, { i -> keys[i] }) val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( - expectedResult, actualResult, - "Get must return corresponding values after left-right rotate with left.right.diffHeight = -1" + expectedResult, + actualResult, + "Get must return corresponding values after left-right rotate with left.right.diffHeight = -1", ) checkTreeInvariant(avlTree.root) } @@ -410,8 +415,9 @@ class AVLTreeTest { val expectedResult = arrayOf(5, 1, 6, 0, 3, null, 2, 4) val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( - expectedResult, actualResult, - "Get must return corresponding values after left-right rotate with left.right.diffHeight = 0" + expectedResult, + actualResult, + "Get must return corresponding values after left-right rotate with left.right.diffHeight = 0", ) checkTreeInvariant(avlTree.root) } @@ -424,8 +430,9 @@ class AVLTreeTest { val expectedResult = Array(keys.size, { i -> keys[i] }) val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( - expectedResult, actualResult, - "Get must return corresponding values after left-right rotate with left.right.diffHeight = 1" + expectedResult, + actualResult, + "Get must return corresponding values after left-right rotate with left.right.diffHeight = 1", ) checkTreeInvariant(avlTree.root) } diff --git a/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log b/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log index 8642d87..f7ae4cd 100644 --- a/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log +++ b/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log @@ -2,6 +2,4 @@ Results of ktlint linter (version 1.2.1) See documentation on https://megalinter.io/7.10.0/descriptors/kotlin_ktlint/ ----------------------------------------------- -✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/AVLTree.kt -✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/RBTree.kt - FIXED -✅ [SUCCESS] lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt - FIXED +✅ [SUCCESS] lib/src/test/kotlin/trees/AVLTreeTest.kt - FIXED diff --git a/megalinter-reports/megalinter.log b/megalinter-reports/megalinter.log index fe68c3a..443c99e 100644 --- a/megalinter-reports/megalinter.log +++ b/megalinter-reports/megalinter.log @@ -11,8 +11,8 @@ The MegaLinter documentation can be found at: ::group::MegaLinter initialization (expand for details) MegaLinter will analyze workspace [/github/workspace] GITHUB_REPOSITORY: spbu-coding-2023/trees-8 -GITHUB_REF: refs/pull/13/merge -GITHUB_RUN_ID: 8493051201 +GITHUB_REF: refs/pull/14/merge +GITHUB_RUN_ID: 8497650337 CLOJURE_CLJSTYLE has been temporary disabled in MegaLinter, please use a previous MegaLinter version or wait for the next one ! @@ -23,35 +23,32 @@ To receive reports as email, please set variable EMAIL_REPORTER_EMAIL ::group::MegaLinter now collects the files to analyse (expand for details) Listing updated files in [/github/workspace] using git diff. Modified files: -.editorconfig -lib/src/main/kotlin/bstrees/implementations/AVLTree.kt -lib/src/main/kotlin/bstrees/implementations/RBTree.kt -lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt +lib/src/test/kotlin/trees/AVLTreeTest.kt megalinter-reports/megalinter.log - File extensions: .kt, .kts - Excluding .gitignored files [0]: -Kept [3] files on [5] found files +Kept [1] files on [2] found files +----MATCHING LINTERS-+----------+----------------+------------+ | Descriptor | Linter | Criteria | Matching files | Format/Fix | +------------+--------+----------+----------------+------------+ -| KOTLIN | ktlint | .kt|.kts | 3 | yes | +| KOTLIN | ktlint | .kt|.kts | 1 | yes | +------------+--------+----------+----------------+------------+ ::endgroup:: -::group::✅ Linted [KOTLIN] files with [ktlint] successfully - (4.57s) (expand for details) +::group::✅ Linted [KOTLIN] files with [ktlint] successfully - (1.88s) (expand for details) - Using [ktlint v1.2.1] https://megalinter.io/7.10.0/descriptors/kotlin_ktlint - MegaLinter key: [KOTLIN_KTLINT] - Rules config: identified by [ktlint] -- Number of files analyzed: [3] +- Number of files analyzed: [1] ::endgroup:: +----SUMMARY-+--------+------+-------+-------+--------+--------------+ | Descriptor | Linter | Mode | Files | Fixed | Errors | Elapsed time | +------------+--------+------+-------+-------+--------+--------------+ -| ✅ KOTLIN | ktlint | file | 3 | 2 | 0 | 4.57s | +| ✅ KOTLIN | ktlint | file | 1 | 1 | 0 | 1.88s | +------------+--------+------+-------+-------+--------+--------------+ -[Updated Sources Reporter] copied 4 fixed source files in folder /github/workspace/megalinter-reports/updated_sources. +[Updated Sources Reporter] copied 3 fixed source files in folder /github/workspace/megalinter-reports/updated_sources. Download it from artifacts then copy-paste it in your local repo to apply linters updates -[GitHub Comment Reporter] Posted summary as comment on spbu-coding-2023/trees-8 #PR13 +[GitHub Comment Reporter] Posted summary as comment on spbu-coding-2023/trees-8 #PR14 ✅ Successfully linted all files without errors diff --git a/megalinter-reports/updated_sources/lib/src/test/kotlin/trees/AVLTreeTest.kt b/megalinter-reports/updated_sources/lib/src/test/kotlin/trees/AVLTreeTest.kt index 712bf2d..9f2ec3a 100644 --- a/megalinter-reports/updated_sources/lib/src/test/kotlin/trees/AVLTreeTest.kt +++ b/megalinter-reports/updated_sources/lib/src/test/kotlin/trees/AVLTreeTest.kt @@ -117,7 +117,7 @@ class AVLTreeTest { } @Test - fun `remove with left vertex`() { + fun `remove root of left subtree with existing left vertex`() { val keys = intArrayOf(0, -1, 1, -2) for (key in keys) avlTree[key] = key avlTree.remove(-1) @@ -132,6 +132,22 @@ class AVLTreeTest { checkTreeInvariant(avlTree.root) } + @Test + fun `remove root of right subtree with existing left vertex`() { + val keys = intArrayOf(0, -1, 2, 1) + for (key in keys) avlTree[key] = key + avlTree.remove(2) + + val expectedResult = arrayOf(0, -1, null, 1) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Tree must save all other vertices after remove root of right subtree with existing left vertex", + ) + checkTreeInvariant(avlTree.root) + } + @Test fun `remove with right subtree of height 1`() { val keys = intArrayOf(0, -1, 3, 1, 2) @@ -167,7 +183,7 @@ class AVLTreeTest { } @Test - fun `remove with necessary double rotate`() { + fun `remove with double rotate`() { val keys = intArrayOf(5, 0, 7, -1, 2, 6, 9, -2, 1, 3, 8, 4) for (key in keys) avlTree[key] = key avlTree.remove(7) @@ -320,4 +336,104 @@ class AVLTreeTest { // / \ / \ / \ / \ / \ // 0 2 4 6 0 2 4 6 4 6 } + + @Test + fun `rotate right-left, right diffHeight is 1, right-left diffHeight is 1`() { + val keys = intArrayOf(1, 0, 4, 3, 5, 2) + for (key in keys) avlTree[key] = key + + val expectedResult = Array(keys.size, { i -> keys[i] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Get must return corresponding values after right-left rotate with right.left.diffHeight = 1", + ) + checkTreeInvariant(avlTree.root) + +// 1 1 3 +// / \ / \ / \ +// 0 4 0 3 1 4 +// / \ --> / \ --> / \ \ +// 3 5 2 4 0 2 5 +// / \ +// 2 5 + } + + @Test + fun `rotate right-left, right diffHeight is 1, right-left diffHeight is 0`() { + val keys = intArrayOf(2, 1, 6, 0, 4, 7, 3, 5) + for (key in keys) avlTree[key] = key + avlTree.remove(0) + + val expectedResult: Array = arrayOf(2, 1, 6, null, 4, 7, 3, 5) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Get must return corresponding values after right-left rotate with right.left.diffHeight = 0", + ) + checkTreeInvariant(avlTree.root) + } + + @Test + fun `rotate right-left, right diffHeight is 1, right-left diffHeight is -1`() { + val keys = intArrayOf(1, 0, 4, 2, 5, 3) + for (key in keys) avlTree[key] = key + + val expectedResult = Array(keys.size, { i -> keys[i] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Get must return corresponding values after right-left rotate with right.left.diffHeight = -1", + ) + checkTreeInvariant(avlTree.root) + } + + @Test + fun `rotate left-right, left diffHeight is -1, left-right diffHeight is -1`() { + val keys = intArrayOf(4, 1, 5, 0, 2, 3) + for (key in keys) avlTree[key] = key + + val expectedResult = Array(keys.size, { i -> keys[i] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Get must return corresponding values after left-right rotate with left.right.diffHeight = -1", + ) + checkTreeInvariant(avlTree.root) + } + + @Test + fun `rotate left-right, left diffHeight is -1, left-right diffHeight is 0`() { + val keys = intArrayOf(5, 1, 6, 0, 3, 7, 2, 4) + for (key in keys) avlTree[key] = key + avlTree.remove(7) + + val expectedResult = arrayOf(5, 1, 6, 0, 3, null, 2, 4) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Get must return corresponding values after left-right rotate with left.right.diffHeight = 0", + ) + checkTreeInvariant(avlTree.root) + } + + @Test + fun `rotate left-right, left diffHeight is -1, left-right diffHeight is 1`() { + val keys = intArrayOf(4, 1, 5, 0, 3, 2) + for (key in keys) avlTree[key] = key + + val expectedResult = Array(keys.size, { i -> keys[i] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Get must return corresponding values after left-right rotate with left.right.diffHeight = 1", + ) + checkTreeInvariant(avlTree.root) + } } diff --git a/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log b/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log index 8642d87..f7ae4cd 100644 --- a/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log +++ b/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log @@ -2,6 +2,4 @@ Results of ktlint linter (version 1.2.1) See documentation on https://megalinter.io/7.10.0/descriptors/kotlin_ktlint/ ----------------------------------------------- -✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/AVLTree.kt -✅ [SUCCESS] lib/src/main/kotlin/bstrees/implementations/RBTree.kt - FIXED -✅ [SUCCESS] lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt - FIXED +✅ [SUCCESS] lib/src/test/kotlin/trees/AVLTreeTest.kt - FIXED diff --git a/megalinter-reports/updated_sources/megalinter-reports/megalinter.log b/megalinter-reports/updated_sources/megalinter-reports/megalinter.log index 72408b8..9a87511 100644 --- a/megalinter-reports/updated_sources/megalinter-reports/megalinter.log +++ b/megalinter-reports/updated_sources/megalinter-reports/megalinter.log @@ -11,8 +11,8 @@ The MegaLinter documentation can be found at: ::group::MegaLinter initialization (expand for details) MegaLinter will analyze workspace [/github/workspace] GITHUB_REPOSITORY: spbu-coding-2023/trees-8 -GITHUB_REF: refs/pull/13/merge -GITHUB_RUN_ID: 8493051201 +GITHUB_REF: refs/pull/14/merge +GITHUB_RUN_ID: 8497650337 CLOJURE_CLJSTYLE has been temporary disabled in MegaLinter, please use a previous MegaLinter version or wait for the next one ! @@ -23,31 +23,28 @@ To receive reports as email, please set variable EMAIL_REPORTER_EMAIL ::group::MegaLinter now collects the files to analyse (expand for details) Listing updated files in [/github/workspace] using git diff. Modified files: -.editorconfig -lib/src/main/kotlin/bstrees/implementations/AVLTree.kt -lib/src/main/kotlin/bstrees/implementations/RBTree.kt -lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt +lib/src/test/kotlin/trees/AVLTreeTest.kt megalinter-reports/megalinter.log - File extensions: .kt, .kts - Excluding .gitignored files [0]: -Kept [3] files on [5] found files +Kept [1] files on [2] found files +----MATCHING LINTERS-+----------+----------------+------------+ | Descriptor | Linter | Criteria | Matching files | Format/Fix | +------------+--------+----------+----------------+------------+ -| KOTLIN | ktlint | .kt|.kts | 3 | yes | +| KOTLIN | ktlint | .kt|.kts | 1 | yes | +------------+--------+----------+----------------+------------+ ::endgroup:: -::group::✅ Linted [KOTLIN] files with [ktlint] successfully - (4.57s) (expand for details) +::group::✅ Linted [KOTLIN] files with [ktlint] successfully - (1.88s) (expand for details) - Using [ktlint v1.2.1] https://megalinter.io/7.10.0/descriptors/kotlin_ktlint - MegaLinter key: [KOTLIN_KTLINT] - Rules config: identified by [ktlint] -- Number of files analyzed: [3] +- Number of files analyzed: [1] ::endgroup:: +----SUMMARY-+--------+------+-------+-------+--------+--------------+ | Descriptor | Linter | Mode | Files | Fixed | Errors | Elapsed time | +------------+--------+------+-------+-------+--------+--------------+ -| ✅ KOTLIN | ktlint | file | 3 | 2 | 0 | 4.57s | +| ✅ KOTLIN | ktlint | file | 1 | 1 | 0 | 1.88s | +------------+--------+------+-------+-------+--------+--------------+ From 994ce9d98bd8ea8189409396621e1cfc4c99a407 Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Sun, 31 Mar 2024 16:34:40 +0300 Subject: [PATCH 054/108] Add tests for public methods in avl tree --- lib/src/test/kotlin/trees/AVLTreeTest.kt | 174 +++++++++++++++++++++-- 1 file changed, 159 insertions(+), 15 deletions(-) diff --git a/lib/src/test/kotlin/trees/AVLTreeTest.kt b/lib/src/test/kotlin/trees/AVLTreeTest.kt index 9f2ec3a..3e1ab7a 100644 --- a/lib/src/test/kotlin/trees/AVLTreeTest.kt +++ b/lib/src/test/kotlin/trees/AVLTreeTest.kt @@ -8,8 +8,10 @@ import bstrees.implementations.AVLVertex import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows import kotlin.test.assertContentEquals import kotlin.test.assertEquals +import kotlin.test.assertIs class AVLTreeTest { private lateinit var avlTree: AVLTree @@ -95,6 +97,19 @@ class AVLTreeTest { checkTreeInvariant(avlTree.root) } + @Test + fun `set return`() { + assertEquals( + avlTree.set(44, -37), null, + "Set must return null if set key was not present in the tree" + ) + + assertEquals( + avlTree.set(44, 152), -37, + "Set must return previous value associated with the key" + ) + } + @Test fun `simple remove`() { avlTree[0] = 5 @@ -229,21 +244,6 @@ class AVLTreeTest { ) } - @Test - fun `simple iteration`() { - val keys = intArrayOf(1, 7, 4, 9, 2, -44, 3) - val values = intArrayOf(19, 14, 31, 17, 12, -34, 0) - for (i in 0.. = arrayOf(-34, 19, 12, 0, 31, 14, 17) - val iterator = avlTree.iterator() - val actualResult: Array = Array(7, { iterator.next().second }) - assertContentEquals(expectedResult, actualResult, "Iterator must return vertices in keys order") - checkTreeInvariant(avlTree.root) - } - @Test fun `rotate left, right diffHeight = -1`() { val keys = intArrayOf(0, -1, 2, 1, 3, 4) @@ -436,4 +436,148 @@ class AVLTreeTest { ) checkTreeInvariant(avlTree.root) } + + @Test + fun `simple iteration`() { + val keys = intArrayOf(1, 7, 4, 9, 2, -44, 3) + val values = intArrayOf(19, 14, 31, 17, 12, -34, 0) + for (i in 0.. = arrayOf(-34, 19, 12, 0, 31, 14, 17) + val iterator = avlTree.iterator() + val actualResult: Array = Array(7, { iterator.next().second }) + assertContentEquals(expectedResult, actualResult, "Iterator must return vertices in keys order") + checkTreeInvariant(avlTree.root) + } + + @Test + fun `iteration outOfBonds exception`() { + val keys = intArrayOf(1, 3, 5, 7, 9, 12, 342, -488) + for (key in keys) avlTree[key] = key + val iterator = avlTree.iterator() + for (key in keys) { + assertIs>( + iterator.next(), "iterator.next() must return Pair while all keys is not bypassed" + ) + } + assertThrows( + "Iterator must throw IndexOutOfBondsException after next() if all keys is bypassed" + ) { + iterator.next() + } + } + + @Test + fun clear() { + val keys = intArrayOf(1, 2, 7, 2, 4, 9) + for (key in keys) avlTree[key] = -key + avlTree.clear() + + assertEquals(avlTree.size, 0, "Size of the tree must be 0 after clear") + assertEquals(avlTree.root, null, "Root of the tree must be null after clear") + } + + @Test + fun `contains key`() { + val keys = intArrayOf(1, 7, 3, -34, 45) + for (key in keys) avlTree[key] = key + + for (key in keys) { + assertEquals( + avlTree.containsKey(key), true, + "containsKey must return true for keys existing in the tree" + ) + } + avlTree.remove(-34) + val keysNotInTheTree = intArrayOf(102, 57, -22, -34) + for (key in keysNotInTheTree) { + assertEquals( + avlTree.containsKey(key), false, + "containsKey must return false for keys not existing in the tree" + ) + } + } + + @Test + fun isNotEmpty() { + assertEquals(avlTree.isNotEmpty(), false, "isNotEmpty must return false if tree is empty") + + val keys = intArrayOf(1, 45, -10045, 0, -10000, 3000004) + for (key in keys) avlTree[key] = key + + assertEquals(avlTree.isNotEmpty(), true, "isNotEmpty must return true if tree is not empty") + + avlTree.clear() + + assertEquals(avlTree.isNotEmpty(), false, "isNotEmpty must return false if tree is empty") + + } + + @Test + fun isEmpty() { + assertEquals(avlTree.isEmpty(), true, "isEmpty must return true if tree is empty") + + avlTree[14] = 902 + + assertEquals(avlTree.isEmpty(), false, "isEmpty must return false if tree is not empty") + + avlTree.remove(14) + + assertEquals(avlTree.isEmpty(), true, "isEmpty must return true if tree is empty") + } + + @Test + fun max() { + val keys = intArrayOf(0, -1, 1, -45, 5, 4, 2, 3) + for (key in keys) avlTree[key] = key + + val expectedResult = Pair(5, 5) + val actualResult = avlTree.max() + + assertEquals(expectedResult, actualResult, "Max must return Pairs by max key in the tree") + checkTreeInvariant(avlTree.root) + + } + + @Test + fun `max after remove max key with double rotate`() { + val keys = intArrayOf(5, 1, 6, 0, 3, 7, 2, 4) + for (key in keys) avlTree[key] = key + avlTree.remove(7) + + val expectedResult = Pair(6, 6) + val actualResult = avlTree.max() + + assertEquals(expectedResult, actualResult, "Max must return Pair by max key in the tree") + checkTreeInvariant(avlTree.root) + } + + @Test + fun min() { + val keys = intArrayOf(54, 88, 4332, -46, -2) + for (key in keys) avlTree[key] = key + + + val expectedResult = Pair(-46, -46) + val actualResult = avlTree.min() + assertEquals(expectedResult, actualResult, "Min must return Pair by min key in the tree") + checkTreeInvariant(avlTree.root) + + + } + + @Test + fun `min after remove min key with double rotate`() { + val keys = intArrayOf(2, 1, 6, 0, 4, 7, 3, 5) + for (key in keys) avlTree[key] = key + avlTree.remove(0) + + val expectedResult = Pair(1, 1) + val actualResult = avlTree.min() + + assertEquals(expectedResult, actualResult, "Min must return Pair by min key in the tree") + checkTreeInvariant(avlTree.root) + } } From b33b8d7c1651ac3cb20a8d8d7b0621989ddd24ad Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Sun, 31 Mar 2024 20:12:29 +0300 Subject: [PATCH 055/108] Add avl tests, change module names -add tests for all public methods in avl tree -renamed packages -separated general and specific avl tests (created 2 classes) --- .../implementations/AVLTree.kt | 4 +- .../implementations/RBTree.kt | 4 +- .../implementations/SimpleTree.kt | 4 +- .../implementations/Vertices.kt | 4 +- .../templates/BSTreeTemplate.kt | 4 +- .../templates/BalanceBSTreeTemplate.kt | 2 +- .../templates/VertexTemplate.kt | 2 +- .../AVLGeneralTest.kt} | 365 +++++------------- .../kotlin/trees/AVLTest/AVLSpecificTest.kt | 274 +++++++++++++ 9 files changed, 378 insertions(+), 285 deletions(-) rename lib/src/main/kotlin/{bstrees => trees}/implementations/AVLTree.kt (99%) rename lib/src/main/kotlin/{bstrees => trees}/implementations/RBTree.kt (99%) rename lib/src/main/kotlin/{bstrees => trees}/implementations/SimpleTree.kt (97%) rename lib/src/main/kotlin/{bstrees => trees}/implementations/Vertices.kt (90%) rename lib/src/main/kotlin/{bstrees => trees}/templates/BSTreeTemplate.kt (98%) rename lib/src/main/kotlin/{bstrees => trees}/templates/BalanceBSTreeTemplate.kt (84%) rename lib/src/main/kotlin/{bstrees => trees}/templates/VertexTemplate.kt (95%) rename lib/src/test/kotlin/trees/{AVLTreeTest.kt => AVLTest/AVLGeneralTest.kt} (50%) create mode 100644 lib/src/test/kotlin/trees/AVLTest/AVLSpecificTest.kt diff --git a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt b/lib/src/main/kotlin/trees/implementations/AVLTree.kt similarity index 99% rename from lib/src/main/kotlin/bstrees/implementations/AVLTree.kt rename to lib/src/main/kotlin/trees/implementations/AVLTree.kt index 57a2bf1..b28e31d 100644 --- a/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt +++ b/lib/src/main/kotlin/trees/implementations/AVLTree.kt @@ -1,6 +1,6 @@ -package bstrees.implementations +package trees.implementations -import bstrees.templates.BalanceBSTreeTemplate +import trees.templates.BalanceBSTreeTemplate class AVLTree, V> : BalanceBSTreeTemplate>() { public override operator fun set(key: K, value: V): V? { diff --git a/lib/src/main/kotlin/bstrees/implementations/RBTree.kt b/lib/src/main/kotlin/trees/implementations/RBTree.kt similarity index 99% rename from lib/src/main/kotlin/bstrees/implementations/RBTree.kt rename to lib/src/main/kotlin/trees/implementations/RBTree.kt index 2580c31..e5731e6 100644 --- a/lib/src/main/kotlin/bstrees/implementations/RBTree.kt +++ b/lib/src/main/kotlin/trees/implementations/RBTree.kt @@ -1,6 +1,6 @@ -package bstrees.implementations +package trees.implementations -import bstrees.templates.BalanceBSTreeTemplate +import trees.templates.BalanceBSTreeTemplate class RBTree, V> : BalanceBSTreeTemplate>() { override fun set(key: K, value: V): V? { diff --git a/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt similarity index 97% rename from lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt rename to lib/src/main/kotlin/trees/implementations/SimpleTree.kt index eae8bf1..c493101 100644 --- a/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt +++ b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt @@ -1,6 +1,6 @@ -package bstrees.implementations +package trees.implementations -import bstrees.templates.BSTreeTemplate +import trees.templates.BSTreeTemplate class SimpleTree, V> : BSTreeTemplate>() { override fun remove(key: K): V? { diff --git a/lib/src/main/kotlin/bstrees/implementations/Vertices.kt b/lib/src/main/kotlin/trees/implementations/Vertices.kt similarity index 90% rename from lib/src/main/kotlin/bstrees/implementations/Vertices.kt rename to lib/src/main/kotlin/trees/implementations/Vertices.kt index 542ef83..be19b63 100644 --- a/lib/src/main/kotlin/bstrees/implementations/Vertices.kt +++ b/lib/src/main/kotlin/trees/implementations/Vertices.kt @@ -1,6 +1,6 @@ -package bstrees.implementations +package trees.implementations -import bstrees.templates.VertexTemplate +import trees.templates.VertexTemplate class SimpleVertex, V>(key: K, value: V) : VertexTemplate>(key, value) diff --git a/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt b/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt similarity index 98% rename from lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt rename to lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt index 9361017..5ccc4b5 100644 --- a/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt +++ b/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt @@ -1,4 +1,4 @@ -package bstrees.templates +package trees.templates import java.util.Stack @@ -50,7 +50,7 @@ abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate> : BSTreeTemplate() diff --git a/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt b/lib/src/main/kotlin/trees/templates/VertexTemplate.kt similarity index 95% rename from lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt rename to lib/src/main/kotlin/trees/templates/VertexTemplate.kt index 31a2ff9..cbf7c0d 100644 --- a/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt +++ b/lib/src/main/kotlin/trees/templates/VertexTemplate.kt @@ -1,4 +1,4 @@ -package bstrees.templates +package trees.templates abstract class VertexTemplate, V, Vertex_t : VertexTemplate>(key: K, value: V) { var key = key diff --git a/lib/src/test/kotlin/trees/AVLTreeTest.kt b/lib/src/test/kotlin/trees/AVLTest/AVLGeneralTest.kt similarity index 50% rename from lib/src/test/kotlin/trees/AVLTreeTest.kt rename to lib/src/test/kotlin/trees/AVLTest/AVLGeneralTest.kt index 3e1ab7a..941ea70 100644 --- a/lib/src/test/kotlin/trees/AVLTreeTest.kt +++ b/lib/src/test/kotlin/trees/AVLTest/AVLGeneralTest.kt @@ -1,44 +1,18 @@ -/* - * This Kotlin source file was generated by the Gradle 'init' task. - */ -package trees - -import bstrees.implementations.AVLTree -import bstrees.implementations.AVLVertex -import org.junit.jupiter.api.Assertions.assertTrue +package trees.AVLTest + import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows +import trees.implementations.AVLTree import kotlin.test.assertContentEquals import kotlin.test.assertEquals +import trees.AVLTest.AVLSpecificTests.Companion.checkTreeInvariant +import kotlin.math.exp import kotlin.test.assertIs -class AVLTreeTest { +class AVLGeneralTest { private lateinit var avlTree: AVLTree - /** - * Traverse all vertices of the tree and asserts that their diffHeights are - * equal to real height difference of the subtrees. - * @return height of the subtree with the root at the specified [vertex] - */ - fun checkTreeInvariant(vertex: AVLVertex<*, *>?): Int { - if (vertex == null) return 0 - - val leftSubtreeHeight = checkTreeInvariant(vertex.left) - val rightSubtreeHeight = checkTreeInvariant(vertex.right) - val difference = leftSubtreeHeight - rightSubtreeHeight - assertTrue( - difference in -1..1, - "Height difference of subtrees must be in [-1,1]", - ) - assertEquals( - difference, - vertex.diffHeight, - "Property diffHeights must match real Height difference of subtrees (key = ${vertex.key})", - ) - return maxOf(checkTreeInvariant(vertex.left), checkTreeInvariant(vertex.right)) + 1 - } - @BeforeEach fun setup() { avlTree = AVLTree() @@ -131,6 +105,20 @@ class AVLTreeTest { ) } + @Test + fun `remove a non-existent key`() { + avlTree[0] = 15 + avlTree.remove(0) + + val expectedResult = null + val actualResult = avlTree.remove(0) + assertEquals( + expectedResult, + actualResult, + "Remove a non-existent key must return null", + ) + } + @Test fun `remove root of left subtree with existing left vertex`() { val keys = intArrayOf(0, -1, 1, -2) @@ -197,246 +185,6 @@ class AVLTreeTest { checkTreeInvariant(avlTree.root) } - @Test - fun `remove with double rotate`() { - val keys = intArrayOf(5, 0, 7, -1, 2, 6, 9, -2, 1, 3, 8, 4) - for (key in keys) avlTree[key] = key - avlTree.remove(7) - - val expectedResult = arrayOf(5, 0, null, -1, 2, 6, 9, -2, 1, 3, 8, 4) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Tree must save all other vertices after remove that creates unbalance situation", - ) - checkTreeInvariant(avlTree.root) - } - - @Test - fun `remove root with double rotate`() { - val keys = intArrayOf(4, 1, 6, 0, 3, 5, 2) - for (key in keys) avlTree[key] = key - avlTree.remove(4) - - assertTrue(avlTree.root != null) - val expectedResult = arrayOf(null, 1, 6, 0, 3, 5, 2) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Tree must save all other vertices after root remove", - ) - checkTreeInvariant(avlTree.root) - } - - @Test - fun `remove a non-existent key`() { - avlTree[0] = 15 - avlTree.remove(0) - - val expectedResult = null - val actualResult = avlTree.remove(0) - assertEquals( - expectedResult, - actualResult, - "Remove a non-existent key must return null", - ) - } - - @Test - fun `rotate left, right diffHeight = -1`() { - val keys = intArrayOf(0, -1, 2, 1, 3, 4) - for (key in keys) avlTree[key] = key - - val expectedResult = Array(keys.size, { i -> keys[i] }) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Get must return corresponding values after left rotate ( right.diffHeight = -1)", - ) - checkTreeInvariant(avlTree.root) - -// 0 0 2 -// / \ / \ / \ -// -1 2 -1 2 0 3 -// / \ --> / \ --> / \ \ -// 1 3 1 3 -1 1 4 -// \ -// 4 - } - - @Test - fun `rotate left, right diffHeiht = 0`() { - val keys = intArrayOf(0, -1, 4, 2, 6, -2, 1, 3, 5, 7) - for (key in keys) avlTree[key] = key - avlTree.remove(-2) - - val expectedResult = arrayOf(0, -1, 4, 2, 6, null, 1, 3, 5, 7) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Get must return corresponding values after left rotate (right.diffHeight = 0)", - ) - checkTreeInvariant(avlTree.root) -// 0 0 4 -// / \ / \ / \ -// -1 4 -1 4 0 6 -// / / \ --> / \ --> / \ / \ -// -2 2 6 2 6 -1 2 5 7 -// / \ / \ / \ / \ / \ -// 1 3 5 7 1 3 5 7 1 3 - } - - @Test - fun `rotate right, left diffHeight = 1`() { - val keys = intArrayOf(0, 1, -1, -3, -2, -4) - for (key in keys) avlTree[key] = key - - val expectedResult = Array(keys.size, { i -> keys[i] }) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Get must return corresponding values after right rotate (left.diffHeight = 1)", - ) - checkTreeInvariant(avlTree.root) - -// 0 0 -1 -// / \ / \ / \ -// -1 1 -1 1 -3 0 -// / \ --> / \ --> / / \ -// -3 -2 -3 -2 -4 -2 1 -// / -// -4 - } - - @Test - fun `rotate right, left diffHeight = 0`() { - val keys = intArrayOf(7, 3, 8, 9, 1, 5, 0, 2, 4, 6) - for (key in keys) avlTree[key] = key - avlTree.remove(9) - - val expectedResult = arrayOf(7, 3, 8, null, 1, 5, 0, 2, 4, 6) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Get must return corresponding values after right rotate (left.diffHeight = 0)", - ) - checkTreeInvariant(avlTree.root) - -// 7 7 3 -// / \ / \ / \ -// 3 8 3 8 1 7 -// / \ \ --> / \ --> / \ / \ -// 1 5 9 1 5 0 2 5 8 -// / \ / \ / \ / \ / \ -// 0 2 4 6 0 2 4 6 4 6 - } - - @Test - fun `rotate right-left, right diffHeight is 1, right-left diffHeight is 1`() { - val keys = intArrayOf(1, 0, 4, 3, 5, 2) - for (key in keys) avlTree[key] = key - - val expectedResult = Array(keys.size, { i -> keys[i] }) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Get must return corresponding values after right-left rotate with right.left.diffHeight = 1", - ) - checkTreeInvariant(avlTree.root) - -// 1 1 3 -// / \ / \ / \ -// 0 4 0 3 1 4 -// / \ --> / \ --> / \ \ -// 3 5 2 4 0 2 5 -// / \ -// 2 5 - } - - @Test - fun `rotate right-left, right diffHeight is 1, right-left diffHeight is 0`() { - val keys = intArrayOf(2, 1, 6, 0, 4, 7, 3, 5) - for (key in keys) avlTree[key] = key - avlTree.remove(0) - - val expectedResult: Array = arrayOf(2, 1, 6, null, 4, 7, 3, 5) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Get must return corresponding values after right-left rotate with right.left.diffHeight = 0", - ) - checkTreeInvariant(avlTree.root) - } - - @Test - fun `rotate right-left, right diffHeight is 1, right-left diffHeight is -1`() { - val keys = intArrayOf(1, 0, 4, 2, 5, 3) - for (key in keys) avlTree[key] = key - - val expectedResult = Array(keys.size, { i -> keys[i] }) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Get must return corresponding values after right-left rotate with right.left.diffHeight = -1", - ) - checkTreeInvariant(avlTree.root) - } - - @Test - fun `rotate left-right, left diffHeight is -1, left-right diffHeight is -1`() { - val keys = intArrayOf(4, 1, 5, 0, 2, 3) - for (key in keys) avlTree[key] = key - - val expectedResult = Array(keys.size, { i -> keys[i] }) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Get must return corresponding values after left-right rotate with left.right.diffHeight = -1", - ) - checkTreeInvariant(avlTree.root) - } - - @Test - fun `rotate left-right, left diffHeight is -1, left-right diffHeight is 0`() { - val keys = intArrayOf(5, 1, 6, 0, 3, 7, 2, 4) - for (key in keys) avlTree[key] = key - avlTree.remove(7) - - val expectedResult = arrayOf(5, 1, 6, 0, 3, null, 2, 4) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Get must return corresponding values after left-right rotate with left.right.diffHeight = 0", - ) - checkTreeInvariant(avlTree.root) - } - - @Test - fun `rotate left-right, left diffHeight is -1, left-right diffHeight is 1`() { - val keys = intArrayOf(4, 1, 5, 0, 3, 2) - for (key in keys) avlTree[key] = key - - val expectedResult = Array(keys.size, { i -> keys[i] }) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Get must return corresponding values after left-right rotate with left.right.diffHeight = 1", - ) - checkTreeInvariant(avlTree.root) - } - @Test fun `simple iteration`() { val keys = intArrayOf(1, 7, 4, 9, 2, -44, 3) @@ -580,4 +328,75 @@ class AVLTreeTest { assertEquals(expectedResult, actualResult, "Min must return Pair by min key in the tree") checkTreeInvariant(avlTree.root) } -} + + @Test + fun `getOrSet with existing key`() { + avlTree[25] = -48 + + val expectedResult = -48 + val actualResult = avlTree.getOrSet(25, 90) + assertEquals( + expectedResult, actualResult, + "getOrSet must return value corresponding to the specified key if it's presented in the tree" + ) + } + + @Test + fun `getOrSet with non existing key`() { + assertEquals( + avlTree.getOrSet(0, -10500), null, + "getOrSet must return null if key is not presented in the tree" + ) + assertEquals( + avlTree[0], -10500, + "getOrSet must set specified key-value if key was not presented in the tree" + ) + } + + @Test + fun `getOrDefault with existing key`() { + avlTree[45] = 45 + + val expectedResult = 45 + val actualResult = avlTree.getOrDefault(45, "Default") + assertEquals( + expectedResult, actualResult, + "getOrDefault must return value corresponding to the specified key if it's presented in the tree" + ) + } + + @Test + fun `getOrDefault with non existing key`() { + val expectedResult = "Default" + val actualResult = avlTree.getOrDefault(100, "Default") + assertEquals( + expectedResult, actualResult, + "getOrDefault must return defaultValue if key is not presented in the tree" + ) + } + + @Test + fun `setIfAbsent when not absent`() { + avlTree[520] = 520 + avlTree.setIfAbsent(520, -200) + + val expectedResult = 520 + val actualResult = avlTree[520] + assertEquals( + expectedResult, actualResult, + "setIfAbsent must not change value if key is presented in the tree" + ) + } + + @Test + fun `setIfAbsent when absent`() { + avlTree.setIfAbsent(-100, 250) + + val expectedResult = 250 + val actualResult = avlTree[-100] + assertEquals( + expectedResult, actualResult, + "setIfAbsent must set specified value under specified key if key was not presented in the tree" + ) + } +} \ No newline at end of file diff --git a/lib/src/test/kotlin/trees/AVLTest/AVLSpecificTest.kt b/lib/src/test/kotlin/trees/AVLTest/AVLSpecificTest.kt new file mode 100644 index 0000000..1216751 --- /dev/null +++ b/lib/src/test/kotlin/trees/AVLTest/AVLSpecificTest.kt @@ -0,0 +1,274 @@ +/* + * This Kotlin source file was generated by the Gradle 'init' task. + */ +package trees.AVLTest + +import trees.implementations.AVLTree +import trees.implementations.AVLVertex +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import kotlin.test.assertContentEquals +import kotlin.test.assertEquals +import kotlin.test.assertIs + +class AVLSpecificTests { + private lateinit var avlTree: AVLTree + + /** + * Traverse all vertices of the tree and asserts that their diffHeights are + * equal to real height difference of the subtrees. + * @return height of the subtree with the root at the specified [vertex] + */ + companion object { + fun checkTreeInvariant(vertex: AVLVertex<*, *>?): Int { + if (vertex == null) return 0 + + val leftSubtreeHeight = checkTreeInvariant(vertex.left) + val rightSubtreeHeight = checkTreeInvariant(vertex.right) + val difference = leftSubtreeHeight - rightSubtreeHeight + assertTrue( + difference in -1..1, + "Height difference of subtrees must be in [-1,1]", + ) + assertEquals( + difference, + vertex.diffHeight, + "Property diffHeights must match real Height difference of subtrees (key = ${vertex.key})", + ) + return maxOf(checkTreeInvariant(vertex.left), checkTreeInvariant(vertex.right)) + 1 + } + } + + @BeforeEach + fun setup() { + avlTree = AVLTree() + } + + @Test + fun `remove with double rotate`() { + val keys = intArrayOf(5, 0, 7, -1, 2, 6, 9, -2, 1, 3, 8, 4) + for (key in keys) avlTree[key] = key + avlTree.remove(7) + + val expectedResult = arrayOf(5, 0, null, -1, 2, 6, 9, -2, 1, 3, 8, 4) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Tree must save all other vertices after remove that creates unbalance situation", + ) + checkTreeInvariant(avlTree.root) + } + + @Test + fun `remove root with double rotate`() { + val keys = intArrayOf(4, 1, 6, 0, 3, 5, 2) + for (key in keys) avlTree[key] = key + avlTree.remove(4) + + assertTrue(avlTree.root != null) + val expectedResult = arrayOf(null, 1, 6, 0, 3, 5, 2) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Tree must save all other vertices after root remove", + ) + checkTreeInvariant(avlTree.root) + } + + @Test + fun `rotate left, right diffHeight = -1`() { + val keys = intArrayOf(0, -1, 2, 1, 3, 4) + for (key in keys) avlTree[key] = key + + val expectedResult = Array(keys.size, { i -> keys[i] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Get must return corresponding values after left rotate ( right.diffHeight = -1)", + ) + checkTreeInvariant(avlTree.root) + +// 0 0 2 +// / \ / \ / \ +// -1 2 -1 2 0 3 +// / \ --> / \ --> / \ \ +// 1 3 1 3 -1 1 4 +// \ +// 4 + } + + @Test + fun `rotate left, right diffHeiht = 0`() { + val keys = intArrayOf(0, -1, 4, 2, 6, -2, 1, 3, 5, 7) + for (key in keys) avlTree[key] = key + avlTree.remove(-2) + + val expectedResult = arrayOf(0, -1, 4, 2, 6, null, 1, 3, 5, 7) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Get must return corresponding values after left rotate (right.diffHeight = 0)", + ) + checkTreeInvariant(avlTree.root) +// 0 0 4 +// / \ / \ / \ +// -1 4 -1 4 0 6 +// / / \ --> / \ --> / \ / \ +// -2 2 6 2 6 -1 2 5 7 +// / \ / \ / \ / \ / \ +// 1 3 5 7 1 3 5 7 1 3 + } + + @Test + fun `rotate right, left diffHeight = 1`() { + val keys = intArrayOf(0, 1, -1, -3, -2, -4) + for (key in keys) avlTree[key] = key + + val expectedResult = Array(keys.size, { i -> keys[i] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Get must return corresponding values after right rotate (left.diffHeight = 1)", + ) + checkTreeInvariant(avlTree.root) + +// 0 0 -1 +// / \ / \ / \ +// -1 1 -1 1 -3 0 +// / \ --> / \ --> / / \ +// -3 -2 -3 -2 -4 -2 1 +// / +// -4 + } + + @Test + fun `rotate right, left diffHeight = 0`() { + val keys = intArrayOf(7, 3, 8, 9, 1, 5, 0, 2, 4, 6) + for (key in keys) avlTree[key] = key + avlTree.remove(9) + + val expectedResult = arrayOf(7, 3, 8, null, 1, 5, 0, 2, 4, 6) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Get must return corresponding values after right rotate (left.diffHeight = 0)", + ) + checkTreeInvariant(avlTree.root) + +// 7 7 3 +// / \ / \ / \ +// 3 8 3 8 1 7 +// / \ \ --> / \ --> / \ / \ +// 1 5 9 1 5 0 2 5 8 +// / \ / \ / \ / \ / \ +// 0 2 4 6 0 2 4 6 4 6 + } + + @Test + fun `rotate right-left, right diffHeight is 1, right-left diffHeight is 1`() { + val keys = intArrayOf(1, 0, 4, 3, 5, 2) + for (key in keys) avlTree[key] = key + + val expectedResult = Array(keys.size, { i -> keys[i] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Get must return corresponding values after right-left rotate with right.left.diffHeight = 1", + ) + checkTreeInvariant(avlTree.root) + +// 1 1 3 +// / \ / \ / \ +// 0 4 0 3 1 4 +// / \ --> / \ --> / \ \ +// 3 5 2 4 0 2 5 +// / \ +// 2 5 + } + + @Test + fun `rotate right-left, right diffHeight is 1, right-left diffHeight is 0`() { + val keys = intArrayOf(2, 1, 6, 0, 4, 7, 3, 5) + for (key in keys) avlTree[key] = key + avlTree.remove(0) + + val expectedResult: Array = arrayOf(2, 1, 6, null, 4, 7, 3, 5) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Get must return corresponding values after right-left rotate with right.left.diffHeight = 0", + ) + checkTreeInvariant(avlTree.root) + } + + @Test + fun `rotate right-left, right diffHeight is 1, right-left diffHeight is -1`() { + val keys = intArrayOf(1, 0, 4, 2, 5, 3) + for (key in keys) avlTree[key] = key + + val expectedResult = Array(keys.size, { i -> keys[i] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Get must return corresponding values after right-left rotate with right.left.diffHeight = -1", + ) + checkTreeInvariant(avlTree.root) + } + + @Test + fun `rotate left-right, left diffHeight is -1, left-right diffHeight is -1`() { + val keys = intArrayOf(4, 1, 5, 0, 2, 3) + for (key in keys) avlTree[key] = key + + val expectedResult = Array(keys.size, { i -> keys[i] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Get must return corresponding values after left-right rotate with left.right.diffHeight = -1", + ) + checkTreeInvariant(avlTree.root) + } + + @Test + fun `rotate left-right, left diffHeight is -1, left-right diffHeight is 0`() { + val keys = intArrayOf(5, 1, 6, 0, 3, 7, 2, 4) + for (key in keys) avlTree[key] = key + avlTree.remove(7) + + val expectedResult = arrayOf(5, 1, 6, 0, 3, null, 2, 4) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Get must return corresponding values after left-right rotate with left.right.diffHeight = 0", + ) + checkTreeInvariant(avlTree.root) + } + + @Test + fun `rotate left-right, left diffHeight is -1, left-right diffHeight is 1`() { + val keys = intArrayOf(4, 1, 5, 0, 3, 2) + for (key in keys) avlTree[key] = key + + val expectedResult = Array(keys.size, { i -> keys[i] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + assertContentEquals( + expectedResult, + actualResult, + "Get must return corresponding values after left-right rotate with left.right.diffHeight = 1", + ) + checkTreeInvariant(avlTree.root) + } +} From 09aca2bbe2e5a00a28d7be4842d17b20a3ba4eed Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Sun, 31 Mar 2024 20:35:59 +0300 Subject: [PATCH 056/108] Renamed all occurrences of AVLTree to AvlTree --- .../implementations/{AVLTree.kt => AvlTree.kt} | 2 +- .../test/kotlin/trees/AVLTest/AVLGeneralTest.kt | 13 ++++++------- .../test/kotlin/trees/AVLTest/AVLSpecificTest.kt | 15 +++++---------- 3 files changed, 12 insertions(+), 18 deletions(-) rename lib/src/main/kotlin/trees/implementations/{AVLTree.kt => AvlTree.kt} (99%) diff --git a/lib/src/main/kotlin/trees/implementations/AVLTree.kt b/lib/src/main/kotlin/trees/implementations/AvlTree.kt similarity index 99% rename from lib/src/main/kotlin/trees/implementations/AVLTree.kt rename to lib/src/main/kotlin/trees/implementations/AvlTree.kt index b28e31d..5a06b33 100644 --- a/lib/src/main/kotlin/trees/implementations/AVLTree.kt +++ b/lib/src/main/kotlin/trees/implementations/AvlTree.kt @@ -2,7 +2,7 @@ package trees.implementations import trees.templates.BalanceBSTreeTemplate -class AVLTree, V> : BalanceBSTreeTemplate>() { +class AvlTree, V> : BalanceBSTreeTemplate>() { public override operator fun set(key: K, value: V): V? { val (currentVert, oldValue) = setWithoutBalance(key, value) if (oldValue == null) { diff --git a/lib/src/test/kotlin/trees/AVLTest/AVLGeneralTest.kt b/lib/src/test/kotlin/trees/AVLTest/AVLGeneralTest.kt index 941ea70..ce88699 100644 --- a/lib/src/test/kotlin/trees/AVLTest/AVLGeneralTest.kt +++ b/lib/src/test/kotlin/trees/AVLTest/AVLGeneralTest.kt @@ -1,21 +1,20 @@ -package trees.AVLTest +package trees.AvlTest import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows -import trees.implementations.AVLTree +import trees.implementations.AvlTree import kotlin.test.assertContentEquals import kotlin.test.assertEquals -import trees.AVLTest.AVLSpecificTests.Companion.checkTreeInvariant -import kotlin.math.exp +import trees.AvlTest.AvlSpecificTests.Companion.checkTreeInvariant import kotlin.test.assertIs -class AVLGeneralTest { - private lateinit var avlTree: AVLTree +class AvlGeneralTest { + private lateinit var avlTree: AvlTree @BeforeEach fun setup() { - avlTree = AVLTree() + avlTree = AvlTree() } @Test diff --git a/lib/src/test/kotlin/trees/AVLTest/AVLSpecificTest.kt b/lib/src/test/kotlin/trees/AVLTest/AVLSpecificTest.kt index 1216751..599323a 100644 --- a/lib/src/test/kotlin/trees/AVLTest/AVLSpecificTest.kt +++ b/lib/src/test/kotlin/trees/AVLTest/AVLSpecificTest.kt @@ -1,20 +1,15 @@ -/* - * This Kotlin source file was generated by the Gradle 'init' task. - */ -package trees.AVLTest +package trees.AvlTest -import trees.implementations.AVLTree +import trees.implementations.AvlTree import trees.implementations.AVLVertex import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertThrows import kotlin.test.assertContentEquals import kotlin.test.assertEquals -import kotlin.test.assertIs -class AVLSpecificTests { - private lateinit var avlTree: AVLTree +class AvlSpecificTests { + private lateinit var avlTree: AvlTree /** * Traverse all vertices of the tree and asserts that their diffHeights are @@ -43,7 +38,7 @@ class AVLSpecificTests { @BeforeEach fun setup() { - avlTree = AVLTree() + avlTree = AvlTree() } @Test From 1812704e0d5dd7a3fd57fb91fa0b8ecfbf8016f3 Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Sun, 31 Mar 2024 20:39:32 +0300 Subject: [PATCH 057/108] Change package names to camelCase --- .../test/kotlin/trees/{AVLTest => avltest}/AVLGeneralTest.kt | 4 ++-- .../test/kotlin/trees/{AVLTest => avltest}/AVLSpecificTest.kt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename lib/src/test/kotlin/trees/{AVLTest => avltest}/AVLGeneralTest.kt (99%) rename lib/src/test/kotlin/trees/{AVLTest => avltest}/AVLSpecificTest.kt (99%) diff --git a/lib/src/test/kotlin/trees/AVLTest/AVLGeneralTest.kt b/lib/src/test/kotlin/trees/avltest/AVLGeneralTest.kt similarity index 99% rename from lib/src/test/kotlin/trees/AVLTest/AVLGeneralTest.kt rename to lib/src/test/kotlin/trees/avltest/AVLGeneralTest.kt index ce88699..4431b51 100644 --- a/lib/src/test/kotlin/trees/AVLTest/AVLGeneralTest.kt +++ b/lib/src/test/kotlin/trees/avltest/AVLGeneralTest.kt @@ -1,4 +1,4 @@ -package trees.AvlTest +package trees.avlTest import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test @@ -6,7 +6,7 @@ import org.junit.jupiter.api.assertThrows import trees.implementations.AvlTree import kotlin.test.assertContentEquals import kotlin.test.assertEquals -import trees.AvlTest.AvlSpecificTests.Companion.checkTreeInvariant +import trees.avlTest.AvlSpecificTests.Companion.checkTreeInvariant import kotlin.test.assertIs class AvlGeneralTest { diff --git a/lib/src/test/kotlin/trees/AVLTest/AVLSpecificTest.kt b/lib/src/test/kotlin/trees/avltest/AVLSpecificTest.kt similarity index 99% rename from lib/src/test/kotlin/trees/AVLTest/AVLSpecificTest.kt rename to lib/src/test/kotlin/trees/avltest/AVLSpecificTest.kt index 599323a..aa1ac1d 100644 --- a/lib/src/test/kotlin/trees/AVLTest/AVLSpecificTest.kt +++ b/lib/src/test/kotlin/trees/avltest/AVLSpecificTest.kt @@ -1,4 +1,4 @@ -package trees.AvlTest +package trees.avlTest import trees.implementations.AvlTree import trees.implementations.AVLVertex From bb8c6c92348e19606f9398011db4f5f80b518a74 Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Sun, 31 Mar 2024 20:41:27 +0300 Subject: [PATCH 058/108] Change file names to camelCase --- .../kotlin/trees/avltest/{AVLGeneralTest.kt => AvlGeneralTest.kt} | 0 .../trees/avltest/{AVLSpecificTest.kt => AvlSpecificTest.kt} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename lib/src/test/kotlin/trees/avltest/{AVLGeneralTest.kt => AvlGeneralTest.kt} (100%) rename lib/src/test/kotlin/trees/avltest/{AVLSpecificTest.kt => AvlSpecificTest.kt} (100%) diff --git a/lib/src/test/kotlin/trees/avltest/AVLGeneralTest.kt b/lib/src/test/kotlin/trees/avltest/AvlGeneralTest.kt similarity index 100% rename from lib/src/test/kotlin/trees/avltest/AVLGeneralTest.kt rename to lib/src/test/kotlin/trees/avltest/AvlGeneralTest.kt diff --git a/lib/src/test/kotlin/trees/avltest/AVLSpecificTest.kt b/lib/src/test/kotlin/trees/avltest/AvlSpecificTest.kt similarity index 100% rename from lib/src/test/kotlin/trees/avltest/AVLSpecificTest.kt rename to lib/src/test/kotlin/trees/avltest/AvlSpecificTest.kt From aef29de43427df76dca33ec57bd6d2a0e6c170bd Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Sun, 31 Mar 2024 20:46:01 +0300 Subject: [PATCH 059/108] Rename AvlSpecificTest class --- lib/src/test/kotlin/trees/avltest/AvlGeneralTest.kt | 2 +- lib/src/test/kotlin/trees/avltest/AvlSpecificTest.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/test/kotlin/trees/avltest/AvlGeneralTest.kt b/lib/src/test/kotlin/trees/avltest/AvlGeneralTest.kt index 4431b51..ecc2594 100644 --- a/lib/src/test/kotlin/trees/avltest/AvlGeneralTest.kt +++ b/lib/src/test/kotlin/trees/avltest/AvlGeneralTest.kt @@ -6,7 +6,7 @@ import org.junit.jupiter.api.assertThrows import trees.implementations.AvlTree import kotlin.test.assertContentEquals import kotlin.test.assertEquals -import trees.avlTest.AvlSpecificTests.Companion.checkTreeInvariant +import trees.avlTest.AvlSpecificTest.Companion.checkTreeInvariant import kotlin.test.assertIs class AvlGeneralTest { diff --git a/lib/src/test/kotlin/trees/avltest/AvlSpecificTest.kt b/lib/src/test/kotlin/trees/avltest/AvlSpecificTest.kt index aa1ac1d..492cd1b 100644 --- a/lib/src/test/kotlin/trees/avltest/AvlSpecificTest.kt +++ b/lib/src/test/kotlin/trees/avltest/AvlSpecificTest.kt @@ -8,7 +8,7 @@ import org.junit.jupiter.api.Test import kotlin.test.assertContentEquals import kotlin.test.assertEquals -class AvlSpecificTests { +class AvlSpecificTest { private lateinit var avlTree: AvlTree /** From ab18f3c95965491320ba7a60e28bcb2b9ac060cd Mon Sep 17 00:00:00 2001 From: Alexei Dmitrievtsev Date: Sun, 31 Mar 2024 14:46:55 -0400 Subject: [PATCH 060/108] fix: RBTree size counter bug fix --- lib/src/main/kotlin/trees/implementations/RBTree.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/src/main/kotlin/trees/implementations/RBTree.kt b/lib/src/main/kotlin/trees/implementations/RBTree.kt index e5731e6..287f9b7 100644 --- a/lib/src/main/kotlin/trees/implementations/RBTree.kt +++ b/lib/src/main/kotlin/trees/implementations/RBTree.kt @@ -142,6 +142,7 @@ class RBTree, V> : BalanceBSTreeTemplate> vertex = vertex.right } } + size -= 1 if (vertex == null) { return null } From 31f1f9d3bdf5f8eaae5b97f348131af055060894 Mon Sep 17 00:00:00 2001 From: Alexei Dmitrievtsev Date: Sun, 31 Mar 2024 14:49:32 -0400 Subject: [PATCH 061/108] add: simple RBTree tests --- lib/src/test/kotlin/trees/rbtest/RBTest.kt | 116 +++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 lib/src/test/kotlin/trees/rbtest/RBTest.kt diff --git a/lib/src/test/kotlin/trees/rbtest/RBTest.kt b/lib/src/test/kotlin/trees/rbtest/RBTest.kt new file mode 100644 index 0000000..921a4c0 --- /dev/null +++ b/lib/src/test/kotlin/trees/rbtest/RBTest.kt @@ -0,0 +1,116 @@ +package trees.avlTest + +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import trees.implementations.RBTree +import kotlin.test.assertContentEquals +import kotlin.test.assertEquals +import trees.implementations.RBVertex +import kotlin.test.assertIs + +class RBTest { + private lateinit var rbTree: RBTree + + @BeforeEach + fun setup() { + rbTree = RBTree() + } + + @Test + fun `simple array test`() { + val array = intArrayOf(0, 1, 2, 3, 4) + for (i in array) { + rbTree[i] = i + } + val expectedGet: Array = Array(5, { i -> i }) + val actualGet: Array = Array(5, { i -> rbTree.get(i) }) + assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") + val expectedSize = 5 + val actualSize = rbTree.size + assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") + } + + @Test + fun `size of red black tree with duplicate keys`() { + for (i in 1..10) { + rbTree[i] = i + 30 + } + for (i in 6..10) { + rbTree[i] = 0 + } + + val expectedSize = 10 + val actualSize = rbTree.size + assertEquals( + expectedSize, + actualSize, + "Size of the tree must not change after overwriting an existing key", + ) + } + + @Test + fun `simple array set test`() { + for (i in 0 .. 19) { + rbTree.set(i, i) + } + + for (i in 0 .. 19) { + val expectedContains = rbTree.get(i) + assertEquals(expectedContains, i, "Added and not removed element does not contain in the tree") + } + + val expectedGet: Array = Array(20, { i -> i }) + val actualGet: Array = Array(20, { i -> rbTree.get(i) }) + assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") + val expectedSize = 20 + val actualSize = rbTree.size + assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") + } + @Test + fun `simple array set remove test`() { + for (i in 0 .. 19) { + rbTree.set(i, i) + } + for (i in 10 .. 19) { + rbTree.remove(i) + } + for (i in 10 .. 19) { + val expectedNotContains = rbTree.get(i) + assertEquals(expectedNotContains, null, "Removed element contains in the tree") + } + for (i in 0 .. 9) { + val expectedContains = rbTree.get(i) + assertEquals(expectedContains, i, "Added and not removed element does not contain in the tree") + } + + val expectedGet: Array = Array(10, { i -> i }) + val actualGet: Array = Array(10, { i -> rbTree.get(i) }) + assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") + val expectedSize = 10 + val actualSize = rbTree.size + assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") + } + + @Test + fun `adding and removing all elements test`() { + for (i in 0 .. 19) { + rbTree.set(i, i) + } + for (i in 0 .. 19) { + rbTree.remove(i) + } + for (i in 0 .. 19) { + val expectedNotContains = rbTree.get(i) + assertEquals(expectedNotContains, null, "Removed element contains in the tree") + } + + val expectedGet: Array = emptyArray() + val actualGet: Array = Array(rbTree.size, { i -> rbTree.get(i) }) + assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") + val expectedSize = 0 + val actualSize = rbTree.size + assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") + } +} \ No newline at end of file From 2b90d6525150bdeb61f44305013ba0e3a30437fd Mon Sep 17 00:00:00 2001 From: admitrievtsev Date: Sun, 31 Mar 2024 18:57:07 +0000 Subject: [PATCH 062/108] [MegaLinter] Apply linters fixes --- lib/src/test/kotlin/trees/rbtest/RBTest.kt | 27 ++--- .../linters_logs/SUCCESS-KOTLIN_KTLINT.log | 3 +- megalinter-reports/megalinter.log | 19 +-- .../src/test/kotlin/trees/rbtest/RBTest.kt | 113 ++++++++++++++++++ .../linters_logs/SUCCESS-KOTLIN_KTLINT.log | 3 +- .../megalinter-reports/megalinter.log | 17 +-- 6 files changed, 148 insertions(+), 34 deletions(-) create mode 100644 megalinter-reports/updated_sources/lib/src/test/kotlin/trees/rbtest/RBTest.kt diff --git a/lib/src/test/kotlin/trees/rbtest/RBTest.kt b/lib/src/test/kotlin/trees/rbtest/RBTest.kt index 921a4c0..064a221 100644 --- a/lib/src/test/kotlin/trees/rbtest/RBTest.kt +++ b/lib/src/test/kotlin/trees/rbtest/RBTest.kt @@ -1,14 +1,10 @@ package trees.avlTest -import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertThrows import trees.implementations.RBTree import kotlin.test.assertContentEquals import kotlin.test.assertEquals -import trees.implementations.RBVertex -import kotlin.test.assertIs class RBTest { private lateinit var rbTree: RBTree @@ -52,11 +48,11 @@ class RBTest { @Test fun `simple array set test`() { - for (i in 0 .. 19) { + for (i in 0..19) { rbTree.set(i, i) } - for (i in 0 .. 19) { + for (i in 0..19) { val expectedContains = rbTree.get(i) assertEquals(expectedContains, i, "Added and not removed element does not contain in the tree") } @@ -68,21 +64,22 @@ class RBTest { val actualSize = rbTree.size assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") } + @Test fun `simple array set remove test`() { - for (i in 0 .. 19) { + for (i in 0..19) { rbTree.set(i, i) } - for (i in 10 .. 19) { + for (i in 10..19) { rbTree.remove(i) } - for (i in 10 .. 19) { + for (i in 10..19) { val expectedNotContains = rbTree.get(i) assertEquals(expectedNotContains, null, "Removed element contains in the tree") } - for (i in 0 .. 9) { + for (i in 0..9) { val expectedContains = rbTree.get(i) - assertEquals(expectedContains, i, "Added and not removed element does not contain in the tree") + assertEquals(expectedContains, i, "Added and not removed element does not contain in the tree") } val expectedGet: Array = Array(10, { i -> i }) @@ -95,13 +92,13 @@ class RBTest { @Test fun `adding and removing all elements test`() { - for (i in 0 .. 19) { + for (i in 0..19) { rbTree.set(i, i) } - for (i in 0 .. 19) { + for (i in 0..19) { rbTree.remove(i) } - for (i in 0 .. 19) { + for (i in 0..19) { val expectedNotContains = rbTree.get(i) assertEquals(expectedNotContains, null, "Removed element contains in the tree") } @@ -113,4 +110,4 @@ class RBTest { val actualSize = rbTree.size assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") } -} \ No newline at end of file +} diff --git a/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log b/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log index f7ae4cd..d229ece 100644 --- a/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log +++ b/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log @@ -2,4 +2,5 @@ Results of ktlint linter (version 1.2.1) See documentation on https://megalinter.io/7.10.0/descriptors/kotlin_ktlint/ ----------------------------------------------- -✅ [SUCCESS] lib/src/test/kotlin/trees/AVLTreeTest.kt - FIXED +✅ [SUCCESS] lib/src/main/kotlin/trees/implementations/RBTree.kt +✅ [SUCCESS] lib/src/test/kotlin/trees/rbtest/RBTest.kt - FIXED diff --git a/megalinter-reports/megalinter.log b/megalinter-reports/megalinter.log index 443c99e..e720373 100644 --- a/megalinter-reports/megalinter.log +++ b/megalinter-reports/megalinter.log @@ -11,8 +11,8 @@ The MegaLinter documentation can be found at: ::group::MegaLinter initialization (expand for details) MegaLinter will analyze workspace [/github/workspace] GITHUB_REPOSITORY: spbu-coding-2023/trees-8 -GITHUB_REF: refs/pull/14/merge -GITHUB_RUN_ID: 8497650337 +GITHUB_REF: refs/pull/18/merge +GITHUB_RUN_ID: 8500266858 CLOJURE_CLJSTYLE has been temporary disabled in MegaLinter, please use a previous MegaLinter version or wait for the next one ! @@ -23,32 +23,33 @@ To receive reports as email, please set variable EMAIL_REPORTER_EMAIL ::group::MegaLinter now collects the files to analyse (expand for details) Listing updated files in [/github/workspace] using git diff. Modified files: -lib/src/test/kotlin/trees/AVLTreeTest.kt +lib/src/main/kotlin/trees/implementations/RBTree.kt +lib/src/test/kotlin/trees/rbtest/RBTest.kt megalinter-reports/megalinter.log - File extensions: .kt, .kts - Excluding .gitignored files [0]: -Kept [1] files on [2] found files +Kept [2] files on [3] found files +----MATCHING LINTERS-+----------+----------------+------------+ | Descriptor | Linter | Criteria | Matching files | Format/Fix | +------------+--------+----------+----------------+------------+ -| KOTLIN | ktlint | .kt|.kts | 1 | yes | +| KOTLIN | ktlint | .kt|.kts | 2 | yes | +------------+--------+----------+----------------+------------+ ::endgroup:: -::group::✅ Linted [KOTLIN] files with [ktlint] successfully - (1.88s) (expand for details) +::group::✅ Linted [KOTLIN] files with [ktlint] successfully - (2.95s) (expand for details) - Using [ktlint v1.2.1] https://megalinter.io/7.10.0/descriptors/kotlin_ktlint - MegaLinter key: [KOTLIN_KTLINT] - Rules config: identified by [ktlint] -- Number of files analyzed: [1] +- Number of files analyzed: [2] ::endgroup:: +----SUMMARY-+--------+------+-------+-------+--------+--------------+ | Descriptor | Linter | Mode | Files | Fixed | Errors | Elapsed time | +------------+--------+------+-------+-------+--------+--------------+ -| ✅ KOTLIN | ktlint | file | 1 | 1 | 0 | 1.88s | +| ✅ KOTLIN | ktlint | file | 2 | 1 | 0 | 2.95s | +------------+--------+------+-------+-------+--------+--------------+ [Updated Sources Reporter] copied 3 fixed source files in folder /github/workspace/megalinter-reports/updated_sources. Download it from artifacts then copy-paste it in your local repo to apply linters updates -[GitHub Comment Reporter] Posted summary as comment on spbu-coding-2023/trees-8 #PR14 +[GitHub Comment Reporter] Posted summary as comment on spbu-coding-2023/trees-8 #PR18 ✅ Successfully linted all files without errors diff --git a/megalinter-reports/updated_sources/lib/src/test/kotlin/trees/rbtest/RBTest.kt b/megalinter-reports/updated_sources/lib/src/test/kotlin/trees/rbtest/RBTest.kt new file mode 100644 index 0000000..064a221 --- /dev/null +++ b/megalinter-reports/updated_sources/lib/src/test/kotlin/trees/rbtest/RBTest.kt @@ -0,0 +1,113 @@ +package trees.avlTest + +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import trees.implementations.RBTree +import kotlin.test.assertContentEquals +import kotlin.test.assertEquals + +class RBTest { + private lateinit var rbTree: RBTree + + @BeforeEach + fun setup() { + rbTree = RBTree() + } + + @Test + fun `simple array test`() { + val array = intArrayOf(0, 1, 2, 3, 4) + for (i in array) { + rbTree[i] = i + } + val expectedGet: Array = Array(5, { i -> i }) + val actualGet: Array = Array(5, { i -> rbTree.get(i) }) + assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") + val expectedSize = 5 + val actualSize = rbTree.size + assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") + } + + @Test + fun `size of red black tree with duplicate keys`() { + for (i in 1..10) { + rbTree[i] = i + 30 + } + for (i in 6..10) { + rbTree[i] = 0 + } + + val expectedSize = 10 + val actualSize = rbTree.size + assertEquals( + expectedSize, + actualSize, + "Size of the tree must not change after overwriting an existing key", + ) + } + + @Test + fun `simple array set test`() { + for (i in 0..19) { + rbTree.set(i, i) + } + + for (i in 0..19) { + val expectedContains = rbTree.get(i) + assertEquals(expectedContains, i, "Added and not removed element does not contain in the tree") + } + + val expectedGet: Array = Array(20, { i -> i }) + val actualGet: Array = Array(20, { i -> rbTree.get(i) }) + assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") + val expectedSize = 20 + val actualSize = rbTree.size + assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") + } + + @Test + fun `simple array set remove test`() { + for (i in 0..19) { + rbTree.set(i, i) + } + for (i in 10..19) { + rbTree.remove(i) + } + for (i in 10..19) { + val expectedNotContains = rbTree.get(i) + assertEquals(expectedNotContains, null, "Removed element contains in the tree") + } + for (i in 0..9) { + val expectedContains = rbTree.get(i) + assertEquals(expectedContains, i, "Added and not removed element does not contain in the tree") + } + + val expectedGet: Array = Array(10, { i -> i }) + val actualGet: Array = Array(10, { i -> rbTree.get(i) }) + assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") + val expectedSize = 10 + val actualSize = rbTree.size + assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") + } + + @Test + fun `adding and removing all elements test`() { + for (i in 0..19) { + rbTree.set(i, i) + } + for (i in 0..19) { + rbTree.remove(i) + } + for (i in 0..19) { + val expectedNotContains = rbTree.get(i) + assertEquals(expectedNotContains, null, "Removed element contains in the tree") + } + + val expectedGet: Array = emptyArray() + val actualGet: Array = Array(rbTree.size, { i -> rbTree.get(i) }) + assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") + val expectedSize = 0 + val actualSize = rbTree.size + assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") + } +} diff --git a/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log b/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log index f7ae4cd..d229ece 100644 --- a/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log +++ b/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log @@ -2,4 +2,5 @@ Results of ktlint linter (version 1.2.1) See documentation on https://megalinter.io/7.10.0/descriptors/kotlin_ktlint/ ----------------------------------------------- -✅ [SUCCESS] lib/src/test/kotlin/trees/AVLTreeTest.kt - FIXED +✅ [SUCCESS] lib/src/main/kotlin/trees/implementations/RBTree.kt +✅ [SUCCESS] lib/src/test/kotlin/trees/rbtest/RBTest.kt - FIXED diff --git a/megalinter-reports/updated_sources/megalinter-reports/megalinter.log b/megalinter-reports/updated_sources/megalinter-reports/megalinter.log index 9a87511..06fa11f 100644 --- a/megalinter-reports/updated_sources/megalinter-reports/megalinter.log +++ b/megalinter-reports/updated_sources/megalinter-reports/megalinter.log @@ -11,8 +11,8 @@ The MegaLinter documentation can be found at: ::group::MegaLinter initialization (expand for details) MegaLinter will analyze workspace [/github/workspace] GITHUB_REPOSITORY: spbu-coding-2023/trees-8 -GITHUB_REF: refs/pull/14/merge -GITHUB_RUN_ID: 8497650337 +GITHUB_REF: refs/pull/18/merge +GITHUB_RUN_ID: 8500266858 CLOJURE_CLJSTYLE has been temporary disabled in MegaLinter, please use a previous MegaLinter version or wait for the next one ! @@ -23,28 +23,29 @@ To receive reports as email, please set variable EMAIL_REPORTER_EMAIL ::group::MegaLinter now collects the files to analyse (expand for details) Listing updated files in [/github/workspace] using git diff. Modified files: -lib/src/test/kotlin/trees/AVLTreeTest.kt +lib/src/main/kotlin/trees/implementations/RBTree.kt +lib/src/test/kotlin/trees/rbtest/RBTest.kt megalinter-reports/megalinter.log - File extensions: .kt, .kts - Excluding .gitignored files [0]: -Kept [1] files on [2] found files +Kept [2] files on [3] found files +----MATCHING LINTERS-+----------+----------------+------------+ | Descriptor | Linter | Criteria | Matching files | Format/Fix | +------------+--------+----------+----------------+------------+ -| KOTLIN | ktlint | .kt|.kts | 1 | yes | +| KOTLIN | ktlint | .kt|.kts | 2 | yes | +------------+--------+----------+----------------+------------+ ::endgroup:: -::group::✅ Linted [KOTLIN] files with [ktlint] successfully - (1.88s) (expand for details) +::group::✅ Linted [KOTLIN] files with [ktlint] successfully - (2.95s) (expand for details) - Using [ktlint v1.2.1] https://megalinter.io/7.10.0/descriptors/kotlin_ktlint - MegaLinter key: [KOTLIN_KTLINT] - Rules config: identified by [ktlint] -- Number of files analyzed: [1] +- Number of files analyzed: [2] ::endgroup:: +----SUMMARY-+--------+------+-------+-------+--------+--------------+ | Descriptor | Linter | Mode | Files | Fixed | Errors | Elapsed time | +------------+--------+------+-------+-------+--------+--------------+ -| ✅ KOTLIN | ktlint | file | 1 | 1 | 0 | 1.88s | +| ✅ KOTLIN | ktlint | file | 2 | 1 | 0 | 2.95s | +------------+--------+------+-------+-------+--------+--------------+ From 14146d183952d47882c2d155f889b50cb0fb0b46 Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Sun, 31 Mar 2024 23:53:19 +0300 Subject: [PATCH 063/108] Fix warnings -remove redundant public mofidifiers -remove explicit type arguments -etc --- .../kotlin/trees/implementations/AvlTree.kt | 6 +-- .../kotlin/trees/templates/BSTreeTemplate.kt | 32 ++++++++-------- .../kotlin/trees/avltest/AvlGeneralTest.kt | 18 ++++----- .../kotlin/trees/avltest/AvlSpecificTest.kt | 38 +++++++++---------- 4 files changed, 47 insertions(+), 47 deletions(-) diff --git a/lib/src/main/kotlin/trees/implementations/AvlTree.kt b/lib/src/main/kotlin/trees/implementations/AvlTree.kt index 5a06b33..9b913eb 100644 --- a/lib/src/main/kotlin/trees/implementations/AvlTree.kt +++ b/lib/src/main/kotlin/trees/implementations/AvlTree.kt @@ -3,7 +3,7 @@ package trees.implementations import trees.templates.BalanceBSTreeTemplate class AvlTree, V> : BalanceBSTreeTemplate>() { - public override operator fun set(key: K, value: V): V? { + override operator fun set(key: K, value: V): V? { val (currentVert, oldValue) = setWithoutBalance(key, value) if (oldValue == null) { size += 1 @@ -43,7 +43,7 @@ class AvlTree, V> : BalanceBSTreeTemplate, V> : BalanceBSTreeTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate> { - var cur = root - val stack = Stack() + private var cur = root + private val stack = Stack() override fun next(): Pair { while (hasNext()) { @@ -95,7 +95,7 @@ abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate by minimum key in the tree. If tree is empty then returns null */ - public fun min(): Pair? { + fun min(): Pair? { return minVertex(root)?.toPair() } @@ -110,7 +110,7 @@ abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate by maximum key in the tree. If tree is empty then returns null */ - public fun max(): Pair? { + fun max(): Pair? { return maxVert(root)?.toPair() } @@ -136,19 +136,19 @@ abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate() + avlTree = AvlTree() } @Test @@ -24,7 +24,7 @@ class AvlGeneralTest { avlTree[i] = -i } val expectedGet: Array = Array(5, { i -> -i }) - val actualGet: Array = Array(5, { i -> avlTree.get(i) }) + val actualGet: Array = Array(5, { i -> avlTree[i] }) assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") val expectedSize = 5 val actualSize = avlTree.size @@ -125,7 +125,7 @@ class AvlGeneralTest { avlTree.remove(-1) val expectedResult = arrayOf(0, null, 1, -2) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( expectedResult, actualResult, @@ -141,7 +141,7 @@ class AvlGeneralTest { avlTree.remove(2) val expectedResult = arrayOf(0, -1, null, 1) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( expectedResult, actualResult, @@ -157,7 +157,7 @@ class AvlGeneralTest { avlTree.remove(3) val expectedResult = arrayOf(0, -1, null, 1, 2) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( expectedResult, actualResult, @@ -173,7 +173,7 @@ class AvlGeneralTest { avlTree.remove(3) val expectedResult = arrayOf(0, -1, null, -2, 1, 6, 4, 7) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( expectedResult, actualResult, @@ -188,7 +188,7 @@ class AvlGeneralTest { fun `simple iteration`() { val keys = intArrayOf(1, 7, 4, 9, 2, -44, 3) val values = intArrayOf(19, 14, 31, 17, 12, -34, 0) - for (i in 0.. - /** - * Traverse all vertices of the tree and asserts that their diffHeights are - * equal to real height difference of the subtrees. - * @return height of the subtree with the root at the specified [vertex] - */ companion object { + /** + * Traverse all vertices of the tree and asserts that their diffHeights are + * equal to real height difference of the subtrees. + * @return height of the subtree with the root at the specified [vertex] + */ fun checkTreeInvariant(vertex: AVLVertex<*, *>?): Int { if (vertex == null) return 0 @@ -38,7 +38,7 @@ class AvlSpecificTest { @BeforeEach fun setup() { - avlTree = AvlTree() + avlTree = AvlTree() } @Test @@ -48,7 +48,7 @@ class AvlSpecificTest { avlTree.remove(7) val expectedResult = arrayOf(5, 0, null, -1, 2, 6, 9, -2, 1, 3, 8, 4) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( expectedResult, actualResult, @@ -65,7 +65,7 @@ class AvlSpecificTest { assertTrue(avlTree.root != null) val expectedResult = arrayOf(null, 1, 6, 0, 3, 5, 2) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( expectedResult, actualResult, @@ -80,7 +80,7 @@ class AvlSpecificTest { for (key in keys) avlTree[key] = key val expectedResult = Array(keys.size, { i -> keys[i] }) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( expectedResult, actualResult, @@ -98,13 +98,13 @@ class AvlSpecificTest { } @Test - fun `rotate left, right diffHeiht = 0`() { + fun `rotate left, right diffHeight = 0`() { val keys = intArrayOf(0, -1, 4, 2, 6, -2, 1, 3, 5, 7) for (key in keys) avlTree[key] = key avlTree.remove(-2) val expectedResult = arrayOf(0, -1, 4, 2, 6, null, 1, 3, 5, 7) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( expectedResult, actualResult, @@ -126,7 +126,7 @@ class AvlSpecificTest { for (key in keys) avlTree[key] = key val expectedResult = Array(keys.size, { i -> keys[i] }) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( expectedResult, actualResult, @@ -173,7 +173,7 @@ class AvlSpecificTest { for (key in keys) avlTree[key] = key val expectedResult = Array(keys.size, { i -> keys[i] }) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( expectedResult, actualResult, @@ -197,7 +197,7 @@ class AvlSpecificTest { avlTree.remove(0) val expectedResult: Array = arrayOf(2, 1, 6, null, 4, 7, 3, 5) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( expectedResult, actualResult, @@ -212,7 +212,7 @@ class AvlSpecificTest { for (key in keys) avlTree[key] = key val expectedResult = Array(keys.size, { i -> keys[i] }) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( expectedResult, actualResult, @@ -227,7 +227,7 @@ class AvlSpecificTest { for (key in keys) avlTree[key] = key val expectedResult = Array(keys.size, { i -> keys[i] }) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( expectedResult, actualResult, @@ -243,7 +243,7 @@ class AvlSpecificTest { avlTree.remove(7) val expectedResult = arrayOf(5, 1, 6, 0, 3, null, 2, 4) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( expectedResult, actualResult, @@ -258,7 +258,7 @@ class AvlSpecificTest { for (key in keys) avlTree[key] = key val expectedResult = Array(keys.size, { i -> keys[i] }) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( expectedResult, actualResult, From 4f427264eca376dda4218a0ecda4504a93f454e5 Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Mon, 1 Apr 2024 00:01:18 +0300 Subject: [PATCH 064/108] Fix `set` method in SimpleTree --- lib/src/main/kotlin/trees/implementations/SimpleTree.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/trees/implementations/SimpleTree.kt b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt index c493101..dabe244 100644 --- a/lib/src/main/kotlin/trees/implementations/SimpleTree.kt +++ b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt @@ -48,7 +48,7 @@ class SimpleTree, V> : BSTreeTemplate var current = root ?: throw IllegalStateException("Can't be null, there was a check above") while (true) { - val result = current.key.compareTo(key) + val result = key.compareTo(current.key) if (result < 0) { if (current.left == null) { val newVertex = SimpleVertex(key, value) From d748486dfad01dcc8f039235446d61fddede886a Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Mon, 1 Apr 2024 00:01:35 +0300 Subject: [PATCH 065/108] Add SimpleTree tests --- lib/src/test/kotlin/trees/BSTreeTest.kt | 147 ++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 lib/src/test/kotlin/trees/BSTreeTest.kt diff --git a/lib/src/test/kotlin/trees/BSTreeTest.kt b/lib/src/test/kotlin/trees/BSTreeTest.kt new file mode 100644 index 0000000..f842d91 --- /dev/null +++ b/lib/src/test/kotlin/trees/BSTreeTest.kt @@ -0,0 +1,147 @@ +package trees + +import bstrees.implementations.SimpleTree +import org.junit.jupiter.api.Assertions.assertNull +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import kotlin.test.assertContentEquals +import kotlin.test.assertEquals + +class BSTreeTest { + private lateinit var simpleTree: SimpleTree + + @BeforeEach + fun setup() { + simpleTree = SimpleTree() + } + + @Test + fun testCheckEmptyTree() { + assertNull(simpleTree.root) + assertEquals(0, simpleTree.size) + } + + @Test + fun testInsertAndFind() { + val array = intArrayOf(0, 1, 2, 3, 4, 5, 6, 7) + for (i in array) { + simpleTree[i] = -i + } + val expectedGet: Array = Array(7) { i -> -i } + val actualGet: Array = Array(7) { i -> simpleTree[i] } + assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") + val expectedSize = array.size + val actualSize = simpleTree.size + assertEquals(expectedSize, actualSize) + } + + @Test + fun testSimpleDelete() { + val array = intArrayOf(0, 1, 2, 3, 4, 5, 6) + for (i in array) { + simpleTree[i] = i + } + + val expectedResult = 3 + val actualResult = simpleTree.remove(3) + assertEquals(expectedResult, actualResult) + + val expectedSize = array.size - 1 + val actualSize = simpleTree.size + assertEquals(expectedSize, actualSize) + } + + @Test + fun testSizeWithDuplicateKeys() { + for (i in 1..10) { + simpleTree[i] = i + 30 + } + for (i in 6..10) { + simpleTree[i] = 0 + } + + val expectedSize = 10 + val actualSize = simpleTree.size + assertEquals(expectedSize, actualSize) + } + + @Test + fun testTwiceKeys() { + for (i in 1..10) { + simpleTree[i] = 30 + i + } + for (i in 1..10) { + simpleTree[i] = 0 + } + + val expectedSize = 10 + val actualSize = simpleTree.size + assertEquals(expectedSize, actualSize) + } + + @Test + fun testRemoveNonExistentKey(){ + simpleTree[0] = 15 + val actualResult = simpleTree.remove(3) + val expectedResult = null + assertEquals(expectedResult, actualResult) + } + + @Test + fun testRemoveRootOfLeftSubtree() { + val keys = intArrayOf(0, -1, 1, -2) + for (i in keys) { + simpleTree[i] = i + } + simpleTree.remove(-1) + + val expectedResult: Array = arrayOf(0, null, 1, -2) + val actualResult = Array(keys.size) { j -> simpleTree[keys[j]] } + assertContentEquals(expectedResult, actualResult) + } + + @Test + fun testRemoveRootOfRightSubtree() { + val keys = intArrayOf(0, -1, 2, 1) + for (i in keys) { + simpleTree[i] = i + } + simpleTree.remove(-1) + + val expectedResult: Array = arrayOf(0, null, 2, 1) + val actualResult = Array(keys.size) { j -> simpleTree[keys[j]] } + assertContentEquals(expectedResult, actualResult) + } + + @Test + fun testRemoveRootWith2Childs() { + val keys = intArrayOf(0, -1, 2, 1, 3) + for (key in keys) { + simpleTree[key] = key + } + simpleTree.remove(2) + + val expectedResult: Array = arrayOf(0, -1, null, 1, 3) + val actualResult = Array(keys.size) { i -> simpleTree[keys[i]] } + assertContentEquals(expectedResult, actualResult) + } +} + + + + + + + + + + + + + + + + + + + From ab3ca95aa89e542960d3d7934784adf128f0a9a8 Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Mon, 1 Apr 2024 00:17:55 +0300 Subject: [PATCH 066/108] Fix after change the file structure Add `bstest` folder --- lib/src/test/kotlin/trees/{ => bstest}/BSTreeTest.kt | 4 ++-- lib/src/test/kotlin/trees/rbtest/RBTest.kt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename lib/src/test/kotlin/trees/{ => bstest}/BSTreeTest.kt (98%) diff --git a/lib/src/test/kotlin/trees/BSTreeTest.kt b/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt similarity index 98% rename from lib/src/test/kotlin/trees/BSTreeTest.kt rename to lib/src/test/kotlin/trees/bstest/BSTreeTest.kt index f842d91..9ea75e1 100644 --- a/lib/src/test/kotlin/trees/BSTreeTest.kt +++ b/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt @@ -1,6 +1,6 @@ -package trees +package trees.bstest -import bstrees.implementations.SimpleTree +import trees.implementations.SimpleTree import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test diff --git a/lib/src/test/kotlin/trees/rbtest/RBTest.kt b/lib/src/test/kotlin/trees/rbtest/RBTest.kt index 064a221..5d606dc 100644 --- a/lib/src/test/kotlin/trees/rbtest/RBTest.kt +++ b/lib/src/test/kotlin/trees/rbtest/RBTest.kt @@ -1,4 +1,4 @@ -package trees.avlTest +package trees.rbtest import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test From f94402c63e1a9fdadd0dc1a948159b6b2152fb16 Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Mon, 1 Apr 2024 00:39:06 +0300 Subject: [PATCH 067/108] Add test on SimpleTree for 100% coverage --- lib/src/test/kotlin/trees/bstest/BSTreeTest.kt | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt b/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt index 9ea75e1..3751a41 100644 --- a/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt +++ b/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt @@ -80,7 +80,7 @@ class BSTreeTest { } @Test - fun testRemoveNonExistentKey(){ + fun testRemoveNonExistentKey() { simpleTree[0] = 15 val actualResult = simpleTree.remove(3) val expectedResult = null @@ -125,6 +125,19 @@ class BSTreeTest { val actualResult = Array(keys.size) { i -> simpleTree[keys[i]] } assertContentEquals(expectedResult, actualResult) } + + @Test + fun testRemoveRigthRootWithoutChilds() { + val keys = intArrayOf(0, -1, 2) + for (key in keys) { + simpleTree[key] = key + } + simpleTree.remove(2) + + val expectedResult: Array = arrayOf(0, -1, null) + val actualResult = Array(keys.size) { i -> simpleTree[keys[i]] } + assertContentEquals(expectedResult, actualResult) + } } From 4757da0d00d9ed216d6add9346299d1ba4d323ae Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Mon, 1 Apr 2024 02:25:39 +0300 Subject: [PATCH 068/108] Add tests on RB | Increased coverage to 86% Fix warnings --- lib/src/test/kotlin/trees/rbtest/RBTest.kt | 71 +++++++++++++++++----- 1 file changed, 56 insertions(+), 15 deletions(-) diff --git a/lib/src/test/kotlin/trees/rbtest/RBTest.kt b/lib/src/test/kotlin/trees/rbtest/RBTest.kt index 5d606dc..ec3f461 100644 --- a/lib/src/test/kotlin/trees/rbtest/RBTest.kt +++ b/lib/src/test/kotlin/trees/rbtest/RBTest.kt @@ -11,7 +11,7 @@ class RBTest { @BeforeEach fun setup() { - rbTree = RBTree() + rbTree = RBTree() } @Test @@ -20,8 +20,22 @@ class RBTest { for (i in array) { rbTree[i] = i } - val expectedGet: Array = Array(5, { i -> i }) - val actualGet: Array = Array(5, { i -> rbTree.get(i) }) + val expectedGet: Array = Array(5) { i -> i } + val actualGet: Array = Array(5) { i -> rbTree[i] } + assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") + val expectedSize = 5 + val actualSize = rbTree.size + assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") + } + + @Test + fun `array test`() { + val array = intArrayOf(2, 1, 3, 0, 4) + for (i in array) { + rbTree[i] = i + } + val expectedGet: Array = Array(5) { i -> i } + val actualGet: Array = Array(5) { i -> rbTree[i] } assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") val expectedSize = 5 val actualSize = rbTree.size @@ -49,16 +63,16 @@ class RBTest { @Test fun `simple array set test`() { for (i in 0..19) { - rbTree.set(i, i) + rbTree[i] = i } for (i in 0..19) { - val expectedContains = rbTree.get(i) + val expectedContains = rbTree[i] assertEquals(expectedContains, i, "Added and not removed element does not contain in the tree") } - val expectedGet: Array = Array(20, { i -> i }) - val actualGet: Array = Array(20, { i -> rbTree.get(i) }) + val expectedGet: Array = Array(20) { i -> i } + val actualGet: Array = Array(20) { i -> rbTree[i] } assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") val expectedSize = 20 val actualSize = rbTree.size @@ -68,22 +82,22 @@ class RBTest { @Test fun `simple array set remove test`() { for (i in 0..19) { - rbTree.set(i, i) + rbTree[i] = i } for (i in 10..19) { rbTree.remove(i) } for (i in 10..19) { - val expectedNotContains = rbTree.get(i) + val expectedNotContains = rbTree[i] assertEquals(expectedNotContains, null, "Removed element contains in the tree") } for (i in 0..9) { - val expectedContains = rbTree.get(i) + val expectedContains = rbTree[i] assertEquals(expectedContains, i, "Added and not removed element does not contain in the tree") } - val expectedGet: Array = Array(10, { i -> i }) - val actualGet: Array = Array(10, { i -> rbTree.get(i) }) + val expectedGet: Array = Array(10) { i -> i } + val actualGet: Array = Array(10) { i -> rbTree[i] } assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") val expectedSize = 10 val actualSize = rbTree.size @@ -93,21 +107,48 @@ class RBTest { @Test fun `adding and removing all elements test`() { for (i in 0..19) { - rbTree.set(i, i) + rbTree[i] = i } for (i in 0..19) { rbTree.remove(i) } for (i in 0..19) { - val expectedNotContains = rbTree.get(i) + val expectedNotContains = rbTree[i] assertEquals(expectedNotContains, null, "Removed element contains in the tree") } val expectedGet: Array = emptyArray() - val actualGet: Array = Array(rbTree.size, { i -> rbTree.get(i) }) + val actualGet: Array = Array(rbTree.size) { i -> rbTree[i] } assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") val expectedSize = 0 val actualSize = rbTree.size assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") } + + @Test + fun `rotate left`() { + val keys = intArrayOf(0, -1, 4, 2, 6, -2, 1, 3, 5, 7) + for (key in keys) rbTree[key] = key + rbTree.remove(-2) + + val expectedResult = arrayOf(0, -1, 4, 2, 6, null, 1, 3, 5, 7) + val actualResult = Array(keys.size) { i -> rbTree[keys[i]] } + assertContentEquals( + expectedResult, + actualResult, + ) + } + + @Test + fun `rotate right`() { + val keys = intArrayOf(0, 1, -1, -3, -2, -4) + for (key in keys) rbTree[key] = key + + val expectedResult = Array(keys.size) { i -> keys[i] } + val actualResult = Array(keys.size) { i -> rbTree[keys[i]] } + assertContentEquals( + expectedResult, + actualResult, + ) + } } From b4e7c4fa3c3c88b181f701d7173425338737f629 Mon Sep 17 00:00:00 2001 From: Alexei Dmitrievtsev Date: Mon, 1 Apr 2024 18:05:21 -0400 Subject: [PATCH 069/108] fix: root remove now works properly --- .../kotlin/trees/implementations/RBTree.kt | 53 ++++++++++--------- .../kotlin/trees/implementations/Vertices.kt | 2 +- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/lib/src/main/kotlin/trees/implementations/RBTree.kt b/lib/src/main/kotlin/trees/implementations/RBTree.kt index 287f9b7..05c3c14 100644 --- a/lib/src/main/kotlin/trees/implementations/RBTree.kt +++ b/lib/src/main/kotlin/trees/implementations/RBTree.kt @@ -67,7 +67,7 @@ class RBTree, V> : BalanceBSTreeTemplate> if (result > 0) { if (currentVertex.left == null) { val newVertex = RBVertex(key, value) - newVertex.color = RBVertex.Color.RED + newVertex.color = red currentVertex.left = newVertex newVertex.parent = currentVertex size += 1 @@ -77,7 +77,7 @@ class RBTree, V> : BalanceBSTreeTemplate> } else if (result < 0) { if (currentVertex.right == null) { val newVertex = RBVertex(key, value) - newVertex.color = RBVertex.Color.RED + newVertex.color = red currentVertex.right = newVertex newVertex.parent = currentVertex size += 1 @@ -152,16 +152,15 @@ class RBTree, V> : BalanceBSTreeTemplate> replacedVertex = deleteNullChild(vertex) deletedVertexColor = vertex.color } else { - val minVertex = findMin(vertex.right!!) - minVertex.color = vertex.color - minVertex.left = vertex.left - minVertex.right = vertex.right - replaceChild(vertex.parent, vertex, minVertex) + var minVertex = findMin(vertex.right!!) + + vertex.value = minVertex.value + vertex.key = minVertex.key replacedVertex = deleteNullChild(minVertex) deletedVertexColor = minVertex.color } - if (deletedVertexColor == RBVertex.Color.BLACK) { + if (deletedVertexColor == black) { balanceTreeAfterDelete(replacedVertex) if (replacedVertex?.nullType == true) { replaceChild(replacedVertex.parent, replacedVertex, null) @@ -172,19 +171,20 @@ class RBTree, V> : BalanceBSTreeTemplate> private fun balanceTreeAfterDelete(vertex: RBVertex?) { if (vertex == root) { - vertex?.color = RBVertex.Color.BLACK + vertex?.color = black return } var brother = getBrother(vertex) - if (brother?.color === RBVertex.Color.RED) { + if (brother?.color == red) { manageRedBrother(vertex, brother) brother = getBrother(vertex) } - if (brother?.left?.color == RBVertex.Color.BLACK && brother.right?.color == RBVertex.Color.BLACK) { - brother.color = RBVertex.Color.RED - if (vertex?.parent?.color == RBVertex.Color.RED) { - vertex.parent?.color = RBVertex.Color.BLACK + + if (brother?.left?.color == black && brother.right?.color == black) { + brother.color = red + if (vertex?.parent?.color == red) { + vertex.parent?.color = black } else { balanceTreeAfterDelete(vertex?.parent) } @@ -206,31 +206,32 @@ class RBTree, V> : BalanceBSTreeTemplate> private fun manageBlackRedOne(vertex: RBVertex?, argBrother: RBVertex?) { var brother = argBrother - if (vertex == vertex?.parent?.left && brother?.right?.color == black) { + val isParent = if (vertex == vertex?.parent?.left) true else false + if (isParent && brother?.right?.color == black) { brother.left?.color = black brother.color = red rotateRight(brother) brother = vertex?.parent?.right - } else if (vertex != vertex?.parent?.left && brother?.left?.color == black) { + + } else if (!isParent && brother?.left?.color == black) { brother.right?.color = black brother.color = red rotateLeft(brother) brother = vertex?.parent?.left } brother?.color = vertex?.parent!!.color - vertex.parent?.color = black - if (vertex == vertex.parent?.left) { - brother?.right?.color = black + if (isParent) { + brother?.left?.color = black rotateLeft(vertex.parent) } else { - brother?.left?.color = black + brother?.right?.color = black rotateRight(vertex.parent) } } private fun manageRedBrother(vertex: RBVertex?, brother: RBVertex) { - brother.color = RBVertex.Color.BLACK - vertex?.parent?.color = RBVertex.Color.RED + brother.color = black + vertex?.parent?.color = red if (vertex === vertex?.parent?.left) { rotateLeft(vertex?.parent) } else { @@ -241,9 +242,9 @@ class RBTree, V> : BalanceBSTreeTemplate> private fun replaceChild(parent: RBVertex?, oldChild: RBVertex, newChild: RBVertex?) { if (parent == null) { root = newChild - } else if (parent.left === oldChild) { + } else if (parent.left == oldChild) { parent.left = newChild - } else if (parent.right === oldChild) { + } else if (parent.right == oldChild) { parent.right = newChild } else { throw IllegalStateException() @@ -254,6 +255,7 @@ class RBTree, V> : BalanceBSTreeTemplate> } private fun deleteNullChild(vertex: RBVertex): RBVertex? { + println(vertex.key) if (vertex.left != null) { replaceChild(vertex.parent, vertex, vertex.left) return vertex.left @@ -262,8 +264,9 @@ class RBTree, V> : BalanceBSTreeTemplate> return vertex.right } else { var newChild: RBVertex? = RBVertex(vertex.key, vertex.value) - if (vertex.color == RBVertex.Color.BLACK) { + if (vertex.color == black) { newChild?.nullType = true + newChild?.color = black } else { newChild = null } diff --git a/lib/src/main/kotlin/trees/implementations/Vertices.kt b/lib/src/main/kotlin/trees/implementations/Vertices.kt index be19b63..3a63980 100644 --- a/lib/src/main/kotlin/trees/implementations/Vertices.kt +++ b/lib/src/main/kotlin/trees/implementations/Vertices.kt @@ -16,7 +16,7 @@ class AVLVertex, V>(key: K, value: V) : VertexTemplate, V>(key: K, value: V) : VertexTemplate>(key, value) { var color: Color = Color.BLACK - var nullType = true + var nullType = false enum class Color { BLACK, From 7c9247975371f6bf15ea4f3acd13f6e23e1f632d Mon Sep 17 00:00:00 2001 From: Alexei Dmitrievtsev Date: Mon, 1 Apr 2024 18:06:32 -0400 Subject: [PATCH 070/108] add: new RBTree tests --- lib/src/test/kotlin/trees/rbtest/RBTest.kt | 40 ++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/lib/src/test/kotlin/trees/rbtest/RBTest.kt b/lib/src/test/kotlin/trees/rbtest/RBTest.kt index ec3f461..ae8dca3 100644 --- a/lib/src/test/kotlin/trees/rbtest/RBTest.kt +++ b/lib/src/test/kotlin/trees/rbtest/RBTest.kt @@ -1,5 +1,6 @@ package trees.rbtest +import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import trees.implementations.RBTree @@ -87,6 +88,9 @@ class RBTest { for (i in 10..19) { rbTree.remove(i) } + println(rbTree.root?.key) + println(rbTree.root?.left?.key) + println(rbTree.root?.right?.key) for (i in 10..19) { val expectedNotContains = rbTree[i] assertEquals(expectedNotContains, null, "Removed element contains in the tree") @@ -104,6 +108,25 @@ class RBTest { assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") } + @Test + fun `not simple array set remove test`() { + + for (i in 19 downTo 0) { + rbTree[19 - i] = i + } + for (i in 8..19) { + rbTree.remove(i) + } + + for (i in 8..19) { + val expectedNotContains = rbTree[i] + assertEquals(expectedNotContains, null, "Removed element contains in the tree") + } + for (i in 0..7) { + val expectedContains = rbTree[i] + assertEquals(expectedContains, 19 - i, "Added and not removed element does not contain in the tree") + } + } @Test fun `adding and removing all elements test`() { for (i in 0..19) { @@ -151,4 +174,21 @@ class RBTest { actualResult, ) } + + @Test + fun `remove root with rotate`() { + val keys = intArrayOf(4, 1, 6, 0, 3, 5, 2) + for (key in keys) rbTree[key] = key + println(Array(keys.size){i -> rbTree[keys[i]]}.toList()) + rbTree.remove(4) + println((Array(keys.size) { i -> rbTree[keys[i]] }).toList()) + Assertions.assertTrue(rbTree.root != null) + + val expectedResult = arrayOf(null, 1, 6, 0, 3, 5, 2) + val actualResult = Array(keys.size) { i -> rbTree[keys[i]] } + assertContentEquals( + expectedResult, + actualResult, + ) + } } From 95f31b24f255f2a6e49857c334cc227b2a02cb46 Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Tue, 2 Apr 2024 10:36:50 +0300 Subject: [PATCH 071/108] Refactor SimpleTree --- lib/src/main/kotlin/trees/implementations/SimpleTree.kt | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/src/main/kotlin/trees/implementations/SimpleTree.kt b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt index dabe244..34c2bd7 100644 --- a/lib/src/main/kotlin/trees/implementations/SimpleTree.kt +++ b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt @@ -35,10 +35,7 @@ class SimpleTree, V> : BSTreeTemplate return oldValue } - override operator fun set( - key: K, - value: V, - ): V? { + override operator fun set(key: K, value: V): V? { if (root == null) { val vertex = SimpleVertex(key, value) root = vertex @@ -70,7 +67,7 @@ class SimpleTree, V> : BSTreeTemplate } else { val oldValue = current.value current.value = value - return null + return oldValue } } } From 239c11a88dc3884932d573d626ec8ccdec642e50 Mon Sep 17 00:00:00 2001 From: Alexei Dmitrievtsev Date: Sun, 31 Mar 2024 14:46:55 -0400 Subject: [PATCH 072/108] fix: RBTree size counter bug fix --- lib/src/main/kotlin/trees/implementations/RBTree.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/src/main/kotlin/trees/implementations/RBTree.kt b/lib/src/main/kotlin/trees/implementations/RBTree.kt index e5731e6..287f9b7 100644 --- a/lib/src/main/kotlin/trees/implementations/RBTree.kt +++ b/lib/src/main/kotlin/trees/implementations/RBTree.kt @@ -142,6 +142,7 @@ class RBTree, V> : BalanceBSTreeTemplate> vertex = vertex.right } } + size -= 1 if (vertex == null) { return null } From 8547b330d691342829d8db7c049db04ee864ad36 Mon Sep 17 00:00:00 2001 From: Alexei Dmitrievtsev Date: Sun, 31 Mar 2024 14:49:32 -0400 Subject: [PATCH 073/108] add: simple RBTree tests --- lib/src/test/kotlin/trees/rbtest/RBTest.kt | 116 +++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 lib/src/test/kotlin/trees/rbtest/RBTest.kt diff --git a/lib/src/test/kotlin/trees/rbtest/RBTest.kt b/lib/src/test/kotlin/trees/rbtest/RBTest.kt new file mode 100644 index 0000000..921a4c0 --- /dev/null +++ b/lib/src/test/kotlin/trees/rbtest/RBTest.kt @@ -0,0 +1,116 @@ +package trees.avlTest + +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import trees.implementations.RBTree +import kotlin.test.assertContentEquals +import kotlin.test.assertEquals +import trees.implementations.RBVertex +import kotlin.test.assertIs + +class RBTest { + private lateinit var rbTree: RBTree + + @BeforeEach + fun setup() { + rbTree = RBTree() + } + + @Test + fun `simple array test`() { + val array = intArrayOf(0, 1, 2, 3, 4) + for (i in array) { + rbTree[i] = i + } + val expectedGet: Array = Array(5, { i -> i }) + val actualGet: Array = Array(5, { i -> rbTree.get(i) }) + assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") + val expectedSize = 5 + val actualSize = rbTree.size + assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") + } + + @Test + fun `size of red black tree with duplicate keys`() { + for (i in 1..10) { + rbTree[i] = i + 30 + } + for (i in 6..10) { + rbTree[i] = 0 + } + + val expectedSize = 10 + val actualSize = rbTree.size + assertEquals( + expectedSize, + actualSize, + "Size of the tree must not change after overwriting an existing key", + ) + } + + @Test + fun `simple array set test`() { + for (i in 0 .. 19) { + rbTree.set(i, i) + } + + for (i in 0 .. 19) { + val expectedContains = rbTree.get(i) + assertEquals(expectedContains, i, "Added and not removed element does not contain in the tree") + } + + val expectedGet: Array = Array(20, { i -> i }) + val actualGet: Array = Array(20, { i -> rbTree.get(i) }) + assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") + val expectedSize = 20 + val actualSize = rbTree.size + assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") + } + @Test + fun `simple array set remove test`() { + for (i in 0 .. 19) { + rbTree.set(i, i) + } + for (i in 10 .. 19) { + rbTree.remove(i) + } + for (i in 10 .. 19) { + val expectedNotContains = rbTree.get(i) + assertEquals(expectedNotContains, null, "Removed element contains in the tree") + } + for (i in 0 .. 9) { + val expectedContains = rbTree.get(i) + assertEquals(expectedContains, i, "Added and not removed element does not contain in the tree") + } + + val expectedGet: Array = Array(10, { i -> i }) + val actualGet: Array = Array(10, { i -> rbTree.get(i) }) + assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") + val expectedSize = 10 + val actualSize = rbTree.size + assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") + } + + @Test + fun `adding and removing all elements test`() { + for (i in 0 .. 19) { + rbTree.set(i, i) + } + for (i in 0 .. 19) { + rbTree.remove(i) + } + for (i in 0 .. 19) { + val expectedNotContains = rbTree.get(i) + assertEquals(expectedNotContains, null, "Removed element contains in the tree") + } + + val expectedGet: Array = emptyArray() + val actualGet: Array = Array(rbTree.size, { i -> rbTree.get(i) }) + assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") + val expectedSize = 0 + val actualSize = rbTree.size + assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") + } +} \ No newline at end of file From 0c8f3650f33228635f12be9aded2c8a4d72bf830 Mon Sep 17 00:00:00 2001 From: admitrievtsev Date: Sun, 31 Mar 2024 18:57:07 +0000 Subject: [PATCH 074/108] [MegaLinter] Apply linters fixes --- lib/src/test/kotlin/trees/rbtest/RBTest.kt | 27 ++--- .../linters_logs/SUCCESS-KOTLIN_KTLINT.log | 3 +- megalinter-reports/megalinter.log | 19 +-- .../src/test/kotlin/trees/rbtest/RBTest.kt | 113 ++++++++++++++++++ .../linters_logs/SUCCESS-KOTLIN_KTLINT.log | 3 +- .../megalinter-reports/megalinter.log | 17 +-- 6 files changed, 148 insertions(+), 34 deletions(-) create mode 100644 megalinter-reports/updated_sources/lib/src/test/kotlin/trees/rbtest/RBTest.kt diff --git a/lib/src/test/kotlin/trees/rbtest/RBTest.kt b/lib/src/test/kotlin/trees/rbtest/RBTest.kt index 921a4c0..064a221 100644 --- a/lib/src/test/kotlin/trees/rbtest/RBTest.kt +++ b/lib/src/test/kotlin/trees/rbtest/RBTest.kt @@ -1,14 +1,10 @@ package trees.avlTest -import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertThrows import trees.implementations.RBTree import kotlin.test.assertContentEquals import kotlin.test.assertEquals -import trees.implementations.RBVertex -import kotlin.test.assertIs class RBTest { private lateinit var rbTree: RBTree @@ -52,11 +48,11 @@ class RBTest { @Test fun `simple array set test`() { - for (i in 0 .. 19) { + for (i in 0..19) { rbTree.set(i, i) } - for (i in 0 .. 19) { + for (i in 0..19) { val expectedContains = rbTree.get(i) assertEquals(expectedContains, i, "Added and not removed element does not contain in the tree") } @@ -68,21 +64,22 @@ class RBTest { val actualSize = rbTree.size assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") } + @Test fun `simple array set remove test`() { - for (i in 0 .. 19) { + for (i in 0..19) { rbTree.set(i, i) } - for (i in 10 .. 19) { + for (i in 10..19) { rbTree.remove(i) } - for (i in 10 .. 19) { + for (i in 10..19) { val expectedNotContains = rbTree.get(i) assertEquals(expectedNotContains, null, "Removed element contains in the tree") } - for (i in 0 .. 9) { + for (i in 0..9) { val expectedContains = rbTree.get(i) - assertEquals(expectedContains, i, "Added and not removed element does not contain in the tree") + assertEquals(expectedContains, i, "Added and not removed element does not contain in the tree") } val expectedGet: Array = Array(10, { i -> i }) @@ -95,13 +92,13 @@ class RBTest { @Test fun `adding and removing all elements test`() { - for (i in 0 .. 19) { + for (i in 0..19) { rbTree.set(i, i) } - for (i in 0 .. 19) { + for (i in 0..19) { rbTree.remove(i) } - for (i in 0 .. 19) { + for (i in 0..19) { val expectedNotContains = rbTree.get(i) assertEquals(expectedNotContains, null, "Removed element contains in the tree") } @@ -113,4 +110,4 @@ class RBTest { val actualSize = rbTree.size assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") } -} \ No newline at end of file +} diff --git a/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log b/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log index f7ae4cd..d229ece 100644 --- a/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log +++ b/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log @@ -2,4 +2,5 @@ Results of ktlint linter (version 1.2.1) See documentation on https://megalinter.io/7.10.0/descriptors/kotlin_ktlint/ ----------------------------------------------- -✅ [SUCCESS] lib/src/test/kotlin/trees/AVLTreeTest.kt - FIXED +✅ [SUCCESS] lib/src/main/kotlin/trees/implementations/RBTree.kt +✅ [SUCCESS] lib/src/test/kotlin/trees/rbtest/RBTest.kt - FIXED diff --git a/megalinter-reports/megalinter.log b/megalinter-reports/megalinter.log index 443c99e..e720373 100644 --- a/megalinter-reports/megalinter.log +++ b/megalinter-reports/megalinter.log @@ -11,8 +11,8 @@ The MegaLinter documentation can be found at: ::group::MegaLinter initialization (expand for details) MegaLinter will analyze workspace [/github/workspace] GITHUB_REPOSITORY: spbu-coding-2023/trees-8 -GITHUB_REF: refs/pull/14/merge -GITHUB_RUN_ID: 8497650337 +GITHUB_REF: refs/pull/18/merge +GITHUB_RUN_ID: 8500266858 CLOJURE_CLJSTYLE has been temporary disabled in MegaLinter, please use a previous MegaLinter version or wait for the next one ! @@ -23,32 +23,33 @@ To receive reports as email, please set variable EMAIL_REPORTER_EMAIL ::group::MegaLinter now collects the files to analyse (expand for details) Listing updated files in [/github/workspace] using git diff. Modified files: -lib/src/test/kotlin/trees/AVLTreeTest.kt +lib/src/main/kotlin/trees/implementations/RBTree.kt +lib/src/test/kotlin/trees/rbtest/RBTest.kt megalinter-reports/megalinter.log - File extensions: .kt, .kts - Excluding .gitignored files [0]: -Kept [1] files on [2] found files +Kept [2] files on [3] found files +----MATCHING LINTERS-+----------+----------------+------------+ | Descriptor | Linter | Criteria | Matching files | Format/Fix | +------------+--------+----------+----------------+------------+ -| KOTLIN | ktlint | .kt|.kts | 1 | yes | +| KOTLIN | ktlint | .kt|.kts | 2 | yes | +------------+--------+----------+----------------+------------+ ::endgroup:: -::group::✅ Linted [KOTLIN] files with [ktlint] successfully - (1.88s) (expand for details) +::group::✅ Linted [KOTLIN] files with [ktlint] successfully - (2.95s) (expand for details) - Using [ktlint v1.2.1] https://megalinter.io/7.10.0/descriptors/kotlin_ktlint - MegaLinter key: [KOTLIN_KTLINT] - Rules config: identified by [ktlint] -- Number of files analyzed: [1] +- Number of files analyzed: [2] ::endgroup:: +----SUMMARY-+--------+------+-------+-------+--------+--------------+ | Descriptor | Linter | Mode | Files | Fixed | Errors | Elapsed time | +------------+--------+------+-------+-------+--------+--------------+ -| ✅ KOTLIN | ktlint | file | 1 | 1 | 0 | 1.88s | +| ✅ KOTLIN | ktlint | file | 2 | 1 | 0 | 2.95s | +------------+--------+------+-------+-------+--------+--------------+ [Updated Sources Reporter] copied 3 fixed source files in folder /github/workspace/megalinter-reports/updated_sources. Download it from artifacts then copy-paste it in your local repo to apply linters updates -[GitHub Comment Reporter] Posted summary as comment on spbu-coding-2023/trees-8 #PR14 +[GitHub Comment Reporter] Posted summary as comment on spbu-coding-2023/trees-8 #PR18 ✅ Successfully linted all files without errors diff --git a/megalinter-reports/updated_sources/lib/src/test/kotlin/trees/rbtest/RBTest.kt b/megalinter-reports/updated_sources/lib/src/test/kotlin/trees/rbtest/RBTest.kt new file mode 100644 index 0000000..064a221 --- /dev/null +++ b/megalinter-reports/updated_sources/lib/src/test/kotlin/trees/rbtest/RBTest.kt @@ -0,0 +1,113 @@ +package trees.avlTest + +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import trees.implementations.RBTree +import kotlin.test.assertContentEquals +import kotlin.test.assertEquals + +class RBTest { + private lateinit var rbTree: RBTree + + @BeforeEach + fun setup() { + rbTree = RBTree() + } + + @Test + fun `simple array test`() { + val array = intArrayOf(0, 1, 2, 3, 4) + for (i in array) { + rbTree[i] = i + } + val expectedGet: Array = Array(5, { i -> i }) + val actualGet: Array = Array(5, { i -> rbTree.get(i) }) + assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") + val expectedSize = 5 + val actualSize = rbTree.size + assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") + } + + @Test + fun `size of red black tree with duplicate keys`() { + for (i in 1..10) { + rbTree[i] = i + 30 + } + for (i in 6..10) { + rbTree[i] = 0 + } + + val expectedSize = 10 + val actualSize = rbTree.size + assertEquals( + expectedSize, + actualSize, + "Size of the tree must not change after overwriting an existing key", + ) + } + + @Test + fun `simple array set test`() { + for (i in 0..19) { + rbTree.set(i, i) + } + + for (i in 0..19) { + val expectedContains = rbTree.get(i) + assertEquals(expectedContains, i, "Added and not removed element does not contain in the tree") + } + + val expectedGet: Array = Array(20, { i -> i }) + val actualGet: Array = Array(20, { i -> rbTree.get(i) }) + assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") + val expectedSize = 20 + val actualSize = rbTree.size + assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") + } + + @Test + fun `simple array set remove test`() { + for (i in 0..19) { + rbTree.set(i, i) + } + for (i in 10..19) { + rbTree.remove(i) + } + for (i in 10..19) { + val expectedNotContains = rbTree.get(i) + assertEquals(expectedNotContains, null, "Removed element contains in the tree") + } + for (i in 0..9) { + val expectedContains = rbTree.get(i) + assertEquals(expectedContains, i, "Added and not removed element does not contain in the tree") + } + + val expectedGet: Array = Array(10, { i -> i }) + val actualGet: Array = Array(10, { i -> rbTree.get(i) }) + assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") + val expectedSize = 10 + val actualSize = rbTree.size + assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") + } + + @Test + fun `adding and removing all elements test`() { + for (i in 0..19) { + rbTree.set(i, i) + } + for (i in 0..19) { + rbTree.remove(i) + } + for (i in 0..19) { + val expectedNotContains = rbTree.get(i) + assertEquals(expectedNotContains, null, "Removed element contains in the tree") + } + + val expectedGet: Array = emptyArray() + val actualGet: Array = Array(rbTree.size, { i -> rbTree.get(i) }) + assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") + val expectedSize = 0 + val actualSize = rbTree.size + assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") + } +} diff --git a/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log b/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log index f7ae4cd..d229ece 100644 --- a/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log +++ b/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log @@ -2,4 +2,5 @@ Results of ktlint linter (version 1.2.1) See documentation on https://megalinter.io/7.10.0/descriptors/kotlin_ktlint/ ----------------------------------------------- -✅ [SUCCESS] lib/src/test/kotlin/trees/AVLTreeTest.kt - FIXED +✅ [SUCCESS] lib/src/main/kotlin/trees/implementations/RBTree.kt +✅ [SUCCESS] lib/src/test/kotlin/trees/rbtest/RBTest.kt - FIXED diff --git a/megalinter-reports/updated_sources/megalinter-reports/megalinter.log b/megalinter-reports/updated_sources/megalinter-reports/megalinter.log index 9a87511..06fa11f 100644 --- a/megalinter-reports/updated_sources/megalinter-reports/megalinter.log +++ b/megalinter-reports/updated_sources/megalinter-reports/megalinter.log @@ -11,8 +11,8 @@ The MegaLinter documentation can be found at: ::group::MegaLinter initialization (expand for details) MegaLinter will analyze workspace [/github/workspace] GITHUB_REPOSITORY: spbu-coding-2023/trees-8 -GITHUB_REF: refs/pull/14/merge -GITHUB_RUN_ID: 8497650337 +GITHUB_REF: refs/pull/18/merge +GITHUB_RUN_ID: 8500266858 CLOJURE_CLJSTYLE has been temporary disabled in MegaLinter, please use a previous MegaLinter version or wait for the next one ! @@ -23,28 +23,29 @@ To receive reports as email, please set variable EMAIL_REPORTER_EMAIL ::group::MegaLinter now collects the files to analyse (expand for details) Listing updated files in [/github/workspace] using git diff. Modified files: -lib/src/test/kotlin/trees/AVLTreeTest.kt +lib/src/main/kotlin/trees/implementations/RBTree.kt +lib/src/test/kotlin/trees/rbtest/RBTest.kt megalinter-reports/megalinter.log - File extensions: .kt, .kts - Excluding .gitignored files [0]: -Kept [1] files on [2] found files +Kept [2] files on [3] found files +----MATCHING LINTERS-+----------+----------------+------------+ | Descriptor | Linter | Criteria | Matching files | Format/Fix | +------------+--------+----------+----------------+------------+ -| KOTLIN | ktlint | .kt|.kts | 1 | yes | +| KOTLIN | ktlint | .kt|.kts | 2 | yes | +------------+--------+----------+----------------+------------+ ::endgroup:: -::group::✅ Linted [KOTLIN] files with [ktlint] successfully - (1.88s) (expand for details) +::group::✅ Linted [KOTLIN] files with [ktlint] successfully - (2.95s) (expand for details) - Using [ktlint v1.2.1] https://megalinter.io/7.10.0/descriptors/kotlin_ktlint - MegaLinter key: [KOTLIN_KTLINT] - Rules config: identified by [ktlint] -- Number of files analyzed: [1] +- Number of files analyzed: [2] ::endgroup:: +----SUMMARY-+--------+------+-------+-------+--------+--------------+ | Descriptor | Linter | Mode | Files | Fixed | Errors | Elapsed time | +------------+--------+------+-------+-------+--------+--------------+ -| ✅ KOTLIN | ktlint | file | 1 | 1 | 0 | 1.88s | +| ✅ KOTLIN | ktlint | file | 2 | 1 | 0 | 2.95s | +------------+--------+------+-------+-------+--------+--------------+ From b8754a213e97cab9ea8986bf6efb075c6f8c7767 Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Mon, 1 Apr 2024 00:01:18 +0300 Subject: [PATCH 075/108] Fix `set` method in SimpleTree --- lib/src/main/kotlin/trees/implementations/SimpleTree.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/main/kotlin/trees/implementations/SimpleTree.kt b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt index c493101..dabe244 100644 --- a/lib/src/main/kotlin/trees/implementations/SimpleTree.kt +++ b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt @@ -48,7 +48,7 @@ class SimpleTree, V> : BSTreeTemplate var current = root ?: throw IllegalStateException("Can't be null, there was a check above") while (true) { - val result = current.key.compareTo(key) + val result = key.compareTo(current.key) if (result < 0) { if (current.left == null) { val newVertex = SimpleVertex(key, value) From 584b1e9e43daee5765c275e4995ba37f45210818 Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Mon, 1 Apr 2024 00:01:35 +0300 Subject: [PATCH 076/108] Add SimpleTree tests --- lib/src/test/kotlin/trees/BSTreeTest.kt | 147 ++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 lib/src/test/kotlin/trees/BSTreeTest.kt diff --git a/lib/src/test/kotlin/trees/BSTreeTest.kt b/lib/src/test/kotlin/trees/BSTreeTest.kt new file mode 100644 index 0000000..f842d91 --- /dev/null +++ b/lib/src/test/kotlin/trees/BSTreeTest.kt @@ -0,0 +1,147 @@ +package trees + +import bstrees.implementations.SimpleTree +import org.junit.jupiter.api.Assertions.assertNull +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import kotlin.test.assertContentEquals +import kotlin.test.assertEquals + +class BSTreeTest { + private lateinit var simpleTree: SimpleTree + + @BeforeEach + fun setup() { + simpleTree = SimpleTree() + } + + @Test + fun testCheckEmptyTree() { + assertNull(simpleTree.root) + assertEquals(0, simpleTree.size) + } + + @Test + fun testInsertAndFind() { + val array = intArrayOf(0, 1, 2, 3, 4, 5, 6, 7) + for (i in array) { + simpleTree[i] = -i + } + val expectedGet: Array = Array(7) { i -> -i } + val actualGet: Array = Array(7) { i -> simpleTree[i] } + assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") + val expectedSize = array.size + val actualSize = simpleTree.size + assertEquals(expectedSize, actualSize) + } + + @Test + fun testSimpleDelete() { + val array = intArrayOf(0, 1, 2, 3, 4, 5, 6) + for (i in array) { + simpleTree[i] = i + } + + val expectedResult = 3 + val actualResult = simpleTree.remove(3) + assertEquals(expectedResult, actualResult) + + val expectedSize = array.size - 1 + val actualSize = simpleTree.size + assertEquals(expectedSize, actualSize) + } + + @Test + fun testSizeWithDuplicateKeys() { + for (i in 1..10) { + simpleTree[i] = i + 30 + } + for (i in 6..10) { + simpleTree[i] = 0 + } + + val expectedSize = 10 + val actualSize = simpleTree.size + assertEquals(expectedSize, actualSize) + } + + @Test + fun testTwiceKeys() { + for (i in 1..10) { + simpleTree[i] = 30 + i + } + for (i in 1..10) { + simpleTree[i] = 0 + } + + val expectedSize = 10 + val actualSize = simpleTree.size + assertEquals(expectedSize, actualSize) + } + + @Test + fun testRemoveNonExistentKey(){ + simpleTree[0] = 15 + val actualResult = simpleTree.remove(3) + val expectedResult = null + assertEquals(expectedResult, actualResult) + } + + @Test + fun testRemoveRootOfLeftSubtree() { + val keys = intArrayOf(0, -1, 1, -2) + for (i in keys) { + simpleTree[i] = i + } + simpleTree.remove(-1) + + val expectedResult: Array = arrayOf(0, null, 1, -2) + val actualResult = Array(keys.size) { j -> simpleTree[keys[j]] } + assertContentEquals(expectedResult, actualResult) + } + + @Test + fun testRemoveRootOfRightSubtree() { + val keys = intArrayOf(0, -1, 2, 1) + for (i in keys) { + simpleTree[i] = i + } + simpleTree.remove(-1) + + val expectedResult: Array = arrayOf(0, null, 2, 1) + val actualResult = Array(keys.size) { j -> simpleTree[keys[j]] } + assertContentEquals(expectedResult, actualResult) + } + + @Test + fun testRemoveRootWith2Childs() { + val keys = intArrayOf(0, -1, 2, 1, 3) + for (key in keys) { + simpleTree[key] = key + } + simpleTree.remove(2) + + val expectedResult: Array = arrayOf(0, -1, null, 1, 3) + val actualResult = Array(keys.size) { i -> simpleTree[keys[i]] } + assertContentEquals(expectedResult, actualResult) + } +} + + + + + + + + + + + + + + + + + + + From 7eab970f6e20f975655d41f488381552aa5d8791 Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Mon, 1 Apr 2024 00:17:55 +0300 Subject: [PATCH 077/108] Fix after change the file structure Add `bstest` folder --- lib/src/test/kotlin/trees/{ => bstest}/BSTreeTest.kt | 4 ++-- lib/src/test/kotlin/trees/rbtest/RBTest.kt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename lib/src/test/kotlin/trees/{ => bstest}/BSTreeTest.kt (98%) diff --git a/lib/src/test/kotlin/trees/BSTreeTest.kt b/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt similarity index 98% rename from lib/src/test/kotlin/trees/BSTreeTest.kt rename to lib/src/test/kotlin/trees/bstest/BSTreeTest.kt index f842d91..9ea75e1 100644 --- a/lib/src/test/kotlin/trees/BSTreeTest.kt +++ b/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt @@ -1,6 +1,6 @@ -package trees +package trees.bstest -import bstrees.implementations.SimpleTree +import trees.implementations.SimpleTree import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test diff --git a/lib/src/test/kotlin/trees/rbtest/RBTest.kt b/lib/src/test/kotlin/trees/rbtest/RBTest.kt index 064a221..5d606dc 100644 --- a/lib/src/test/kotlin/trees/rbtest/RBTest.kt +++ b/lib/src/test/kotlin/trees/rbtest/RBTest.kt @@ -1,4 +1,4 @@ -package trees.avlTest +package trees.rbtest import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test From f8f1b7636137ae099f4eb069e4c3f439d9e8d0b0 Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Mon, 1 Apr 2024 00:39:06 +0300 Subject: [PATCH 078/108] Add test on SimpleTree for 100% coverage --- lib/src/test/kotlin/trees/bstest/BSTreeTest.kt | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt b/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt index 9ea75e1..3751a41 100644 --- a/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt +++ b/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt @@ -80,7 +80,7 @@ class BSTreeTest { } @Test - fun testRemoveNonExistentKey(){ + fun testRemoveNonExistentKey() { simpleTree[0] = 15 val actualResult = simpleTree.remove(3) val expectedResult = null @@ -125,6 +125,19 @@ class BSTreeTest { val actualResult = Array(keys.size) { i -> simpleTree[keys[i]] } assertContentEquals(expectedResult, actualResult) } + + @Test + fun testRemoveRigthRootWithoutChilds() { + val keys = intArrayOf(0, -1, 2) + for (key in keys) { + simpleTree[key] = key + } + simpleTree.remove(2) + + val expectedResult: Array = arrayOf(0, -1, null) + val actualResult = Array(keys.size) { i -> simpleTree[keys[i]] } + assertContentEquals(expectedResult, actualResult) + } } From 3277c7c45c4ae85f78e517bb82e955441ee6ec9e Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Mon, 1 Apr 2024 02:25:39 +0300 Subject: [PATCH 079/108] Add tests on RB | Increased coverage to 86% Fix warnings --- lib/src/test/kotlin/trees/rbtest/RBTest.kt | 71 +++++++++++++++++----- 1 file changed, 56 insertions(+), 15 deletions(-) diff --git a/lib/src/test/kotlin/trees/rbtest/RBTest.kt b/lib/src/test/kotlin/trees/rbtest/RBTest.kt index 5d606dc..ec3f461 100644 --- a/lib/src/test/kotlin/trees/rbtest/RBTest.kt +++ b/lib/src/test/kotlin/trees/rbtest/RBTest.kt @@ -11,7 +11,7 @@ class RBTest { @BeforeEach fun setup() { - rbTree = RBTree() + rbTree = RBTree() } @Test @@ -20,8 +20,22 @@ class RBTest { for (i in array) { rbTree[i] = i } - val expectedGet: Array = Array(5, { i -> i }) - val actualGet: Array = Array(5, { i -> rbTree.get(i) }) + val expectedGet: Array = Array(5) { i -> i } + val actualGet: Array = Array(5) { i -> rbTree[i] } + assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") + val expectedSize = 5 + val actualSize = rbTree.size + assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") + } + + @Test + fun `array test`() { + val array = intArrayOf(2, 1, 3, 0, 4) + for (i in array) { + rbTree[i] = i + } + val expectedGet: Array = Array(5) { i -> i } + val actualGet: Array = Array(5) { i -> rbTree[i] } assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") val expectedSize = 5 val actualSize = rbTree.size @@ -49,16 +63,16 @@ class RBTest { @Test fun `simple array set test`() { for (i in 0..19) { - rbTree.set(i, i) + rbTree[i] = i } for (i in 0..19) { - val expectedContains = rbTree.get(i) + val expectedContains = rbTree[i] assertEquals(expectedContains, i, "Added and not removed element does not contain in the tree") } - val expectedGet: Array = Array(20, { i -> i }) - val actualGet: Array = Array(20, { i -> rbTree.get(i) }) + val expectedGet: Array = Array(20) { i -> i } + val actualGet: Array = Array(20) { i -> rbTree[i] } assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") val expectedSize = 20 val actualSize = rbTree.size @@ -68,22 +82,22 @@ class RBTest { @Test fun `simple array set remove test`() { for (i in 0..19) { - rbTree.set(i, i) + rbTree[i] = i } for (i in 10..19) { rbTree.remove(i) } for (i in 10..19) { - val expectedNotContains = rbTree.get(i) + val expectedNotContains = rbTree[i] assertEquals(expectedNotContains, null, "Removed element contains in the tree") } for (i in 0..9) { - val expectedContains = rbTree.get(i) + val expectedContains = rbTree[i] assertEquals(expectedContains, i, "Added and not removed element does not contain in the tree") } - val expectedGet: Array = Array(10, { i -> i }) - val actualGet: Array = Array(10, { i -> rbTree.get(i) }) + val expectedGet: Array = Array(10) { i -> i } + val actualGet: Array = Array(10) { i -> rbTree[i] } assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") val expectedSize = 10 val actualSize = rbTree.size @@ -93,21 +107,48 @@ class RBTest { @Test fun `adding and removing all elements test`() { for (i in 0..19) { - rbTree.set(i, i) + rbTree[i] = i } for (i in 0..19) { rbTree.remove(i) } for (i in 0..19) { - val expectedNotContains = rbTree.get(i) + val expectedNotContains = rbTree[i] assertEquals(expectedNotContains, null, "Removed element contains in the tree") } val expectedGet: Array = emptyArray() - val actualGet: Array = Array(rbTree.size, { i -> rbTree.get(i) }) + val actualGet: Array = Array(rbTree.size) { i -> rbTree[i] } assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") val expectedSize = 0 val actualSize = rbTree.size assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") } + + @Test + fun `rotate left`() { + val keys = intArrayOf(0, -1, 4, 2, 6, -2, 1, 3, 5, 7) + for (key in keys) rbTree[key] = key + rbTree.remove(-2) + + val expectedResult = arrayOf(0, -1, 4, 2, 6, null, 1, 3, 5, 7) + val actualResult = Array(keys.size) { i -> rbTree[keys[i]] } + assertContentEquals( + expectedResult, + actualResult, + ) + } + + @Test + fun `rotate right`() { + val keys = intArrayOf(0, 1, -1, -3, -2, -4) + for (key in keys) rbTree[key] = key + + val expectedResult = Array(keys.size) { i -> keys[i] } + val actualResult = Array(keys.size) { i -> rbTree[keys[i]] } + assertContentEquals( + expectedResult, + actualResult, + ) + } } From 1b171483d7bcc84917f4aeec6a65fa4baf671f6e Mon Sep 17 00:00:00 2001 From: Alexei Dmitrievtsev Date: Mon, 1 Apr 2024 18:05:21 -0400 Subject: [PATCH 080/108] fix: root remove now works properly --- .../kotlin/trees/implementations/RBTree.kt | 53 ++++++++++--------- .../kotlin/trees/implementations/Vertices.kt | 2 +- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/lib/src/main/kotlin/trees/implementations/RBTree.kt b/lib/src/main/kotlin/trees/implementations/RBTree.kt index 287f9b7..05c3c14 100644 --- a/lib/src/main/kotlin/trees/implementations/RBTree.kt +++ b/lib/src/main/kotlin/trees/implementations/RBTree.kt @@ -67,7 +67,7 @@ class RBTree, V> : BalanceBSTreeTemplate> if (result > 0) { if (currentVertex.left == null) { val newVertex = RBVertex(key, value) - newVertex.color = RBVertex.Color.RED + newVertex.color = red currentVertex.left = newVertex newVertex.parent = currentVertex size += 1 @@ -77,7 +77,7 @@ class RBTree, V> : BalanceBSTreeTemplate> } else if (result < 0) { if (currentVertex.right == null) { val newVertex = RBVertex(key, value) - newVertex.color = RBVertex.Color.RED + newVertex.color = red currentVertex.right = newVertex newVertex.parent = currentVertex size += 1 @@ -152,16 +152,15 @@ class RBTree, V> : BalanceBSTreeTemplate> replacedVertex = deleteNullChild(vertex) deletedVertexColor = vertex.color } else { - val minVertex = findMin(vertex.right!!) - minVertex.color = vertex.color - minVertex.left = vertex.left - minVertex.right = vertex.right - replaceChild(vertex.parent, vertex, minVertex) + var minVertex = findMin(vertex.right!!) + + vertex.value = minVertex.value + vertex.key = minVertex.key replacedVertex = deleteNullChild(minVertex) deletedVertexColor = minVertex.color } - if (deletedVertexColor == RBVertex.Color.BLACK) { + if (deletedVertexColor == black) { balanceTreeAfterDelete(replacedVertex) if (replacedVertex?.nullType == true) { replaceChild(replacedVertex.parent, replacedVertex, null) @@ -172,19 +171,20 @@ class RBTree, V> : BalanceBSTreeTemplate> private fun balanceTreeAfterDelete(vertex: RBVertex?) { if (vertex == root) { - vertex?.color = RBVertex.Color.BLACK + vertex?.color = black return } var brother = getBrother(vertex) - if (brother?.color === RBVertex.Color.RED) { + if (brother?.color == red) { manageRedBrother(vertex, brother) brother = getBrother(vertex) } - if (brother?.left?.color == RBVertex.Color.BLACK && brother.right?.color == RBVertex.Color.BLACK) { - brother.color = RBVertex.Color.RED - if (vertex?.parent?.color == RBVertex.Color.RED) { - vertex.parent?.color = RBVertex.Color.BLACK + + if (brother?.left?.color == black && brother.right?.color == black) { + brother.color = red + if (vertex?.parent?.color == red) { + vertex.parent?.color = black } else { balanceTreeAfterDelete(vertex?.parent) } @@ -206,31 +206,32 @@ class RBTree, V> : BalanceBSTreeTemplate> private fun manageBlackRedOne(vertex: RBVertex?, argBrother: RBVertex?) { var brother = argBrother - if (vertex == vertex?.parent?.left && brother?.right?.color == black) { + val isParent = if (vertex == vertex?.parent?.left) true else false + if (isParent && brother?.right?.color == black) { brother.left?.color = black brother.color = red rotateRight(brother) brother = vertex?.parent?.right - } else if (vertex != vertex?.parent?.left && brother?.left?.color == black) { + + } else if (!isParent && brother?.left?.color == black) { brother.right?.color = black brother.color = red rotateLeft(brother) brother = vertex?.parent?.left } brother?.color = vertex?.parent!!.color - vertex.parent?.color = black - if (vertex == vertex.parent?.left) { - brother?.right?.color = black + if (isParent) { + brother?.left?.color = black rotateLeft(vertex.parent) } else { - brother?.left?.color = black + brother?.right?.color = black rotateRight(vertex.parent) } } private fun manageRedBrother(vertex: RBVertex?, brother: RBVertex) { - brother.color = RBVertex.Color.BLACK - vertex?.parent?.color = RBVertex.Color.RED + brother.color = black + vertex?.parent?.color = red if (vertex === vertex?.parent?.left) { rotateLeft(vertex?.parent) } else { @@ -241,9 +242,9 @@ class RBTree, V> : BalanceBSTreeTemplate> private fun replaceChild(parent: RBVertex?, oldChild: RBVertex, newChild: RBVertex?) { if (parent == null) { root = newChild - } else if (parent.left === oldChild) { + } else if (parent.left == oldChild) { parent.left = newChild - } else if (parent.right === oldChild) { + } else if (parent.right == oldChild) { parent.right = newChild } else { throw IllegalStateException() @@ -254,6 +255,7 @@ class RBTree, V> : BalanceBSTreeTemplate> } private fun deleteNullChild(vertex: RBVertex): RBVertex? { + println(vertex.key) if (vertex.left != null) { replaceChild(vertex.parent, vertex, vertex.left) return vertex.left @@ -262,8 +264,9 @@ class RBTree, V> : BalanceBSTreeTemplate> return vertex.right } else { var newChild: RBVertex? = RBVertex(vertex.key, vertex.value) - if (vertex.color == RBVertex.Color.BLACK) { + if (vertex.color == black) { newChild?.nullType = true + newChild?.color = black } else { newChild = null } diff --git a/lib/src/main/kotlin/trees/implementations/Vertices.kt b/lib/src/main/kotlin/trees/implementations/Vertices.kt index be19b63..3a63980 100644 --- a/lib/src/main/kotlin/trees/implementations/Vertices.kt +++ b/lib/src/main/kotlin/trees/implementations/Vertices.kt @@ -16,7 +16,7 @@ class AVLVertex, V>(key: K, value: V) : VertexTemplate, V>(key: K, value: V) : VertexTemplate>(key, value) { var color: Color = Color.BLACK - var nullType = true + var nullType = false enum class Color { BLACK, From 7dfd73360f7c3a6a0c1977bb4b607fcb4d6ca506 Mon Sep 17 00:00:00 2001 From: Alexei Dmitrievtsev Date: Mon, 1 Apr 2024 18:06:32 -0400 Subject: [PATCH 081/108] add: new RBTree tests --- lib/src/test/kotlin/trees/rbtest/RBTest.kt | 40 ++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/lib/src/test/kotlin/trees/rbtest/RBTest.kt b/lib/src/test/kotlin/trees/rbtest/RBTest.kt index ec3f461..ae8dca3 100644 --- a/lib/src/test/kotlin/trees/rbtest/RBTest.kt +++ b/lib/src/test/kotlin/trees/rbtest/RBTest.kt @@ -1,5 +1,6 @@ package trees.rbtest +import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import trees.implementations.RBTree @@ -87,6 +88,9 @@ class RBTest { for (i in 10..19) { rbTree.remove(i) } + println(rbTree.root?.key) + println(rbTree.root?.left?.key) + println(rbTree.root?.right?.key) for (i in 10..19) { val expectedNotContains = rbTree[i] assertEquals(expectedNotContains, null, "Removed element contains in the tree") @@ -104,6 +108,25 @@ class RBTest { assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") } + @Test + fun `not simple array set remove test`() { + + for (i in 19 downTo 0) { + rbTree[19 - i] = i + } + for (i in 8..19) { + rbTree.remove(i) + } + + for (i in 8..19) { + val expectedNotContains = rbTree[i] + assertEquals(expectedNotContains, null, "Removed element contains in the tree") + } + for (i in 0..7) { + val expectedContains = rbTree[i] + assertEquals(expectedContains, 19 - i, "Added and not removed element does not contain in the tree") + } + } @Test fun `adding and removing all elements test`() { for (i in 0..19) { @@ -151,4 +174,21 @@ class RBTest { actualResult, ) } + + @Test + fun `remove root with rotate`() { + val keys = intArrayOf(4, 1, 6, 0, 3, 5, 2) + for (key in keys) rbTree[key] = key + println(Array(keys.size){i -> rbTree[keys[i]]}.toList()) + rbTree.remove(4) + println((Array(keys.size) { i -> rbTree[keys[i]] }).toList()) + Assertions.assertTrue(rbTree.root != null) + + val expectedResult = arrayOf(null, 1, 6, 0, 3, 5, 2) + val actualResult = Array(keys.size) { i -> rbTree[keys[i]] } + assertContentEquals( + expectedResult, + actualResult, + ) + } } From f319fa01747da5cf4294cdb36db319118d497663 Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Tue, 2 Apr 2024 10:36:50 +0300 Subject: [PATCH 082/108] Refactor SimpleTree --- lib/src/main/kotlin/trees/implementations/SimpleTree.kt | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/src/main/kotlin/trees/implementations/SimpleTree.kt b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt index dabe244..34c2bd7 100644 --- a/lib/src/main/kotlin/trees/implementations/SimpleTree.kt +++ b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt @@ -35,10 +35,7 @@ class SimpleTree, V> : BSTreeTemplate return oldValue } - override operator fun set( - key: K, - value: V, - ): V? { + override operator fun set(key: K, value: V): V? { if (root == null) { val vertex = SimpleVertex(key, value) root = vertex @@ -70,7 +67,7 @@ class SimpleTree, V> : BSTreeTemplate } else { val oldValue = current.value current.value = value - return null + return oldValue } } } From 8ac8645e47f1e03aa7ba03bf4212edcf6b67bd2a Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Tue, 2 Apr 2024 12:02:21 +0300 Subject: [PATCH 083/108] Fix remove in SimpleTree -add protected maxVert method in BSTreeTemplate --- .../kotlin/trees/implementations/SimpleTree.kt | 15 ++++++++++----- .../main/kotlin/trees/templates/BSTreeTemplate.kt | 8 ++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/lib/src/main/kotlin/trees/implementations/SimpleTree.kt b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt index 34c2bd7..c98c963 100644 --- a/lib/src/main/kotlin/trees/implementations/SimpleTree.kt +++ b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt @@ -14,21 +14,26 @@ class SimpleTree, V> : BSTreeTemplate else -> parent.right = null } } else if (vertex.right == null) { - vertex.left?.let { + val successor = maxVertex(vertex.left) + val successorParent = successor?.parent + successor?.let { vertex.key = it.key vertex.value = it.value - vertex.left = null + } + when { + successorParent?.left == successor -> successorParent?.left = null + successorParent?.right == successor -> successorParent?.right = null } } else { val successor = minVertex(vertex.right) val successorParent = successor?.parent successor?.let { - vertex.key = successor.key - vertex.value = successor.value + vertex.key = it.key + vertex.value = it.value } when { successorParent?.left == successor -> successorParent?.left = null - else -> vertex.right = null + successorParent?.right == successor -> successorParent?.right = null } } --size diff --git a/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt b/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt index ced9399..f79d82c 100644 --- a/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt +++ b/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt @@ -107,6 +107,14 @@ abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate by maximum key in the tree. If tree is empty then returns null */ From b94caef9818324c971e1d2677af0fc0e07753d6a Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Tue, 2 Apr 2024 12:08:56 +0300 Subject: [PATCH 084/108] Add test for RBTree --- lib/src/test/kotlin/trees/rbtest/RBTest.kt | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/src/test/kotlin/trees/rbtest/RBTest.kt b/lib/src/test/kotlin/trees/rbtest/RBTest.kt index ae8dca3..1d65757 100644 --- a/lib/src/test/kotlin/trees/rbtest/RBTest.kt +++ b/lib/src/test/kotlin/trees/rbtest/RBTest.kt @@ -127,6 +127,7 @@ class RBTest { assertEquals(expectedContains, 19 - i, "Added and not removed element does not contain in the tree") } } + @Test fun `adding and removing all elements test`() { for (i in 0..19) { @@ -179,7 +180,7 @@ class RBTest { fun `remove root with rotate`() { val keys = intArrayOf(4, 1, 6, 0, 3, 5, 2) for (key in keys) rbTree[key] = key - println(Array(keys.size){i -> rbTree[keys[i]]}.toList()) + println(Array(keys.size) { i -> rbTree[keys[i]] }.toList()) rbTree.remove(4) println((Array(keys.size) { i -> rbTree[keys[i]] }).toList()) Assertions.assertTrue(rbTree.root != null) @@ -191,4 +192,18 @@ class RBTest { actualResult, ) } + + @Test + fun `remove a non-existent key`() { + rbTree[0] = 15 + rbTree.remove(0) + + val expectedResult = null + val actualResult = rbTree.remove(0) + assertEquals( + expectedResult, + actualResult, + "Remove a non-existent key must return null", + ) + } } From ef8c39c3f0b111ed711861c41e21d29c38c398a7 Mon Sep 17 00:00:00 2001 From: Alexei Dmitrievtsev Date: Tue, 2 Apr 2024 05:43:08 -0400 Subject: [PATCH 085/108] fix: tree size counter --- .../main/kotlin/trees/implementations/RBTree.kt | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/lib/src/main/kotlin/trees/implementations/RBTree.kt b/lib/src/main/kotlin/trees/implementations/RBTree.kt index 05c3c14..d3688d2 100644 --- a/lib/src/main/kotlin/trees/implementations/RBTree.kt +++ b/lib/src/main/kotlin/trees/implementations/RBTree.kt @@ -1,6 +1,7 @@ package trees.implementations import trees.templates.BalanceBSTreeTemplate +import java.sql.Blob class RBTree, V> : BalanceBSTreeTemplate>() { override fun set(key: K, value: V): V? { @@ -142,7 +143,8 @@ class RBTree, V> : BalanceBSTreeTemplate> vertex = vertex.right } } - size -= 1 + if(vertex?.key == key) size -= 1 + if (vertex == null) { return null } @@ -210,23 +212,17 @@ class RBTree, V> : BalanceBSTreeTemplate> if (isParent && brother?.right?.color == black) { brother.left?.color = black brother.color = red - rotateRight(brother) + rotateLeft(brother) brother = vertex?.parent?.right } else if (!isParent && brother?.left?.color == black) { brother.right?.color = black brother.color = red - rotateLeft(brother) + rotateRight(brother) brother = vertex?.parent?.left } brother?.color = vertex?.parent!!.color - if (isParent) { - brother?.left?.color = black - rotateLeft(vertex.parent) - } else { - brother?.right?.color = black - rotateRight(vertex.parent) - } + vertex.parent?.color = black } private fun manageRedBrother(vertex: RBVertex?, brother: RBVertex) { @@ -255,7 +251,6 @@ class RBTree, V> : BalanceBSTreeTemplate> } private fun deleteNullChild(vertex: RBVertex): RBVertex? { - println(vertex.key) if (vertex.left != null) { replaceChild(vertex.parent, vertex, vertex.left) return vertex.left From a0c1cda805fd6bf27ea6173cd061034ace0fdacb Mon Sep 17 00:00:00 2001 From: Alexei Dmitrievtsev Date: Tue, 2 Apr 2024 05:43:48 -0400 Subject: [PATCH 086/108] ref: RBTest code refactoring --- lib/src/test/kotlin/trees/rbtest/RBTest.kt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/src/test/kotlin/trees/rbtest/RBTest.kt b/lib/src/test/kotlin/trees/rbtest/RBTest.kt index 1d65757..a567477 100644 --- a/lib/src/test/kotlin/trees/rbtest/RBTest.kt +++ b/lib/src/test/kotlin/trees/rbtest/RBTest.kt @@ -88,9 +88,6 @@ class RBTest { for (i in 10..19) { rbTree.remove(i) } - println(rbTree.root?.key) - println(rbTree.root?.left?.key) - println(rbTree.root?.right?.key) for (i in 10..19) { val expectedNotContains = rbTree[i] assertEquals(expectedNotContains, null, "Removed element contains in the tree") @@ -180,9 +177,7 @@ class RBTest { fun `remove root with rotate`() { val keys = intArrayOf(4, 1, 6, 0, 3, 5, 2) for (key in keys) rbTree[key] = key - println(Array(keys.size) { i -> rbTree[keys[i]] }.toList()) rbTree.remove(4) - println((Array(keys.size) { i -> rbTree[keys[i]] }).toList()) Assertions.assertTrue(rbTree.root != null) val expectedResult = arrayOf(null, 1, 6, 0, 3, 5, 2) From 9ae92cebe8b096ebfe9680c30176fc334c4e028b Mon Sep 17 00:00:00 2001 From: Alexei Dmitrievtsev Date: Tue, 2 Apr 2024 06:03:50 -0400 Subject: [PATCH 087/108] ref: code refactoring --- .../kotlin/trees/implementations/RBTree.kt | 48 ++++++++----------- .../kotlin/trees/implementations/Vertices.kt | 2 +- 2 files changed, 20 insertions(+), 30 deletions(-) diff --git a/lib/src/main/kotlin/trees/implementations/RBTree.kt b/lib/src/main/kotlin/trees/implementations/RBTree.kt index d3688d2..cc1bb46 100644 --- a/lib/src/main/kotlin/trees/implementations/RBTree.kt +++ b/lib/src/main/kotlin/trees/implementations/RBTree.kt @@ -135,36 +135,32 @@ class RBTree, V> : BalanceBSTreeTemplate> } override fun remove(key: K): V? { - var vertex = root - while (vertex != null && vertex.key != key) { - if (key < vertex.key) { - vertex = vertex.left - } else { - vertex = vertex.right - } - } - if(vertex?.key == key) size -= 1 - + val vertex = vertByKey(key) + println("REMOVE: ${key}") + println(size) + println(" ${root?.key}") + println(" ${root?.left?.key} ${root?.right?.key}") + println("${root?.left?.left?.key} ${root?.left?.right?.key} ${root?.right?.left?.key} ${root?.right?.right?.key}") if (vertex == null) { return null } + size -= 1 val replacedVertex: RBVertex? val deletedVertexColor: RBVertex.Color if (vertex.left == null || vertex.right == null) { replacedVertex = deleteNullChild(vertex) deletedVertexColor = vertex.color } else { - var minVertex = findMin(vertex.right!!) - - vertex.value = minVertex.value - vertex.key = minVertex.key - replacedVertex = deleteNullChild(minVertex) - deletedVertexColor = minVertex.color + val mVertex = minVertex(vertex.right!!)!! + vertex.value = mVertex.value + vertex.key = mVertex.key + replacedVertex = deleteNullChild(mVertex) + deletedVertexColor = mVertex.color } if (deletedVertexColor == black) { balanceTreeAfterDelete(replacedVertex) - if (replacedVertex?.nullType == true) { + if (replacedVertex?.additionalType == true) { replaceChild(replacedVertex.parent, replacedVertex, null) } } @@ -177,20 +173,20 @@ class RBTree, V> : BalanceBSTreeTemplate> return } var brother = getBrother(vertex) - if (brother?.color == red) { manageRedBrother(vertex, brother) brother = getBrother(vertex) } - if (brother?.left?.color == black && brother.right?.color == black) { brother.color = red if (vertex?.parent?.color == red) { vertex.parent?.color = black - } else { + } + else { balanceTreeAfterDelete(vertex?.parent) } - } else { + } + else { manageBlackRedOne(vertex, brother) } } @@ -260,7 +256,7 @@ class RBTree, V> : BalanceBSTreeTemplate> } else { var newChild: RBVertex? = RBVertex(vertex.key, vertex.value) if (vertex.color == black) { - newChild?.nullType = true + newChild?.additionalType = true newChild?.color = black } else { newChild = null @@ -270,13 +266,7 @@ class RBTree, V> : BalanceBSTreeTemplate> } } - private fun findMin(argVertex: RBVertex): RBVertex { - var vertex = argVertex - while (vertex.left != null) { - vertex = vertex.left!! - } - return vertex - } + private fun getVertexUncle(parent: RBVertex): RBVertex? { val grandparent = parent.parent diff --git a/lib/src/main/kotlin/trees/implementations/Vertices.kt b/lib/src/main/kotlin/trees/implementations/Vertices.kt index 3a63980..6be7d32 100644 --- a/lib/src/main/kotlin/trees/implementations/Vertices.kt +++ b/lib/src/main/kotlin/trees/implementations/Vertices.kt @@ -16,7 +16,7 @@ class AVLVertex, V>(key: K, value: V) : VertexTemplate, V>(key: K, value: V) : VertexTemplate>(key, value) { var color: Color = Color.BLACK - var nullType = false + var additionalType = false enum class Color { BLACK, From c3bea686bd8991734d157acfc1792bff28e9dbdb Mon Sep 17 00:00:00 2001 From: Alexei Dmitrievtsev Date: Tue, 2 Apr 2024 06:04:44 -0400 Subject: [PATCH 088/108] ref: remove dev-only features --- lib/src/main/kotlin/trees/implementations/RBTree.kt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/src/main/kotlin/trees/implementations/RBTree.kt b/lib/src/main/kotlin/trees/implementations/RBTree.kt index cc1bb46..504bf7e 100644 --- a/lib/src/main/kotlin/trees/implementations/RBTree.kt +++ b/lib/src/main/kotlin/trees/implementations/RBTree.kt @@ -136,11 +136,6 @@ class RBTree, V> : BalanceBSTreeTemplate> override fun remove(key: K): V? { val vertex = vertByKey(key) - println("REMOVE: ${key}") - println(size) - println(" ${root?.key}") - println(" ${root?.left?.key} ${root?.right?.key}") - println("${root?.left?.left?.key} ${root?.left?.right?.key} ${root?.right?.left?.key} ${root?.right?.right?.key}") if (vertex == null) { return null } From a48f9c614a36a3f998780d39850cb837560ad165 Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Tue, 2 Apr 2024 14:30:28 +0300 Subject: [PATCH 089/108] Move setWithoutBalance method to abstract class -remove setWithoutBalance in trees implementations -add setWithoutBalance common implementation to BSTreeTemplate class -add abstract fabric method in BSTreeTemplate abstract class --- .../kotlin/trees/implementations/AvlTree.kt | 43 ++----------- .../kotlin/trees/implementations/RBTree.kt | 61 +++++-------------- .../trees/implementations/SimpleTree.kt | 41 +++---------- .../kotlin/trees/implementations/Vertices.kt | 2 +- .../kotlin/trees/templates/BSTreeTemplate.kt | 43 +++++++++++++ 5 files changed, 72 insertions(+), 118 deletions(-) diff --git a/lib/src/main/kotlin/trees/implementations/AvlTree.kt b/lib/src/main/kotlin/trees/implementations/AvlTree.kt index 9b913eb..81d6293 100644 --- a/lib/src/main/kotlin/trees/implementations/AvlTree.kt +++ b/lib/src/main/kotlin/trees/implementations/AvlTree.kt @@ -4,7 +4,7 @@ import trees.templates.BalanceBSTreeTemplate class AvlTree, V> : BalanceBSTreeTemplate>() { override operator fun set(key: K, value: V): V? { - val (currentVert, oldValue) = setWithoutBalance(key, value) + val (currentVert, oldValue) = setWithoutBalance(key, value, ::fabricVertex) if (oldValue == null) { size += 1 balanceAfterSet(currentVert) @@ -12,46 +12,11 @@ class AvlTree, V> : BalanceBSTreeTemplate, V?> { - if (root == null) { - val newVertex = AVLVertex(key, value) - root = newVertex - return Pair(newVertex, null) - } - - var cur = root ?: throw IllegalStateException("Case when root is null is processed above") - while (true) { - val result = key.compareTo(cur.key) - if (result < 0) { - if (cur.left == null) { - val newVertex = AVLVertex(key, value) - cur.left = newVertex - newVertex.parent = cur - return Pair(newVertex, null) - } - cur = cur.left ?: throw IllegalStateException("Case when cur.left is null is processed above") - } else if (result > 0) { - if (cur.right == null) { - val newVertex = AVLVertex(key, value) - cur.right = newVertex - newVertex.parent = cur - return Pair(newVertex, null) - } - cur = cur.right ?: throw IllegalStateException("Case when cur.right is null is processed above") - } else { - val oldValue = cur.value - cur.value = value - return Pair(cur, oldValue) - } - } + override fun fabricVertex(key: K, value: V): AVLVertex { + return AVLVertex(key, value) } + /** * Climbing up the tree, updates diffHeights of vertices after set and calls * [balanceOnce] if vertex became unbalanced diff --git a/lib/src/main/kotlin/trees/implementations/RBTree.kt b/lib/src/main/kotlin/trees/implementations/RBTree.kt index a2743f1..187af77 100644 --- a/lib/src/main/kotlin/trees/implementations/RBTree.kt +++ b/lib/src/main/kotlin/trees/implementations/RBTree.kt @@ -4,10 +4,21 @@ import trees.templates.BalanceBSTreeTemplate import java.sql.Blob class RBTree, V> : BalanceBSTreeTemplate>() { + + override fun fabricVertex(key: K, value: V): RBVertex { + return RBVertex(key, value) + } + override fun set(key: K, value: V): V? { - val (currentVert, returnResult) = unbalancedSet(key, value) + val (currentVert, oldValue) = setWithoutBalance(key, value, ::fabricVertex) + if (oldValue == null) { + size += 1 + } + if (currentVert == root) { + currentVert.color = black + } balanceTreeAfterInsert(currentVert) - return returnResult + return oldValue } private val red = RBVertex.Color.RED @@ -55,44 +66,6 @@ class RBTree, V> : BalanceBSTreeTemplate> } } - private fun unbalancedSet(key: K, value: V): Pair, V?> { - if (root == null) { - val newVertex = RBVertex(key, value) - root = newVertex - size += 1 - return Pair(newVertex, null) - } - var currentVertex = root ?: throw IllegalStateException() - while (true) { - val result = currentVertex.key.compareTo(key) - if (result > 0) { - if (currentVertex.left == null) { - val newVertex = RBVertex(key, value) - newVertex.color = red - currentVertex.left = newVertex - newVertex.parent = currentVertex - size += 1 - return Pair(newVertex, null) - } - currentVertex = currentVertex.left ?: throw IllegalStateException() - } else if (result < 0) { - if (currentVertex.right == null) { - val newVertex = RBVertex(key, value) - newVertex.color = red - currentVertex.right = newVertex - newVertex.parent = currentVertex - size += 1 - return Pair(newVertex, null) - } - currentVertex = currentVertex.right ?: throw IllegalStateException() - } else { - val oldValue = currentVertex.value - currentVertex.value = value - return Pair(currentVertex, oldValue) - } - } - } - private fun balanceTreeAfterInsert(vertex: RBVertex) { var parent = vertex.parent if (parent == null) { @@ -135,7 +108,6 @@ class RBTree, V> : BalanceBSTreeTemplate> } override fun remove(key: K): V? { - val vertex = vertByKey(key) if (vertex == null) { @@ -179,12 +151,10 @@ class RBTree, V> : BalanceBSTreeTemplate> brother.color = red if (vertex?.parent?.color == red) { vertex.parent?.color = black - } - else { + } else { balanceTreeAfterDelete(vertex?.parent) } - } - else { + } else { manageBlackRedOne(vertex, brother) } } @@ -266,7 +236,6 @@ class RBTree, V> : BalanceBSTreeTemplate> } - private fun getVertexUncle(parent: RBVertex): RBVertex? { val grandparent = parent.parent return if (grandparent?.left == parent) { diff --git a/lib/src/main/kotlin/trees/implementations/SimpleTree.kt b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt index c98c963..d4a5fe3 100644 --- a/lib/src/main/kotlin/trees/implementations/SimpleTree.kt +++ b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt @@ -3,6 +3,11 @@ package trees.implementations import trees.templates.BSTreeTemplate class SimpleTree, V> : BSTreeTemplate>() { + + override fun fabricVertex(key: K, value: V): SimpleVertex { + return SimpleVertex(key, value) + } + override fun remove(key: K): V? { val vertex = vertByKey(key) ?: return null val parent = vertex.parent @@ -41,39 +46,11 @@ class SimpleTree, V> : BSTreeTemplate } override operator fun set(key: K, value: V): V? { - if (root == null) { - val vertex = SimpleVertex(key, value) - root = vertex + val (currentVert, oldValue) = setWithoutBalance(key, value, ::fabricVertex) + if (oldValue == null) { size += 1 - return null - } - - var current = root ?: throw IllegalStateException("Can't be null, there was a check above") - while (true) { - val result = key.compareTo(current.key) - if (result < 0) { - if (current.left == null) { - val newVertex = SimpleVertex(key, value) - current.left = newVertex - newVertex.parent = current - size += 1 - return null - } - current = current.left ?: throw IllegalStateException("Case when cur.left is null is processed above") - } else if (result > 0) { - if (current.right == null) { - val newVertex = SimpleVertex(key, value) - current.right = newVertex - newVertex.parent = current - size += 1 - return null - } - current = current.right ?: throw IllegalStateException("Case when cur.right is null is processed above") - } else { - val oldValue = current.value - current.value = value - return oldValue - } } + return oldValue } + } diff --git a/lib/src/main/kotlin/trees/implementations/Vertices.kt b/lib/src/main/kotlin/trees/implementations/Vertices.kt index 6be7d32..c79bcdf 100644 --- a/lib/src/main/kotlin/trees/implementations/Vertices.kt +++ b/lib/src/main/kotlin/trees/implementations/Vertices.kt @@ -15,7 +15,7 @@ class AVLVertex, V>(key: K, value: V) : VertexTemplate, V>(key: K, value: V) : VertexTemplate>(key, value) { - var color: Color = Color.BLACK + var color: Color = Color.RED var additionalType = false enum class Color { diff --git a/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt b/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt index f79d82c..e4a9252 100644 --- a/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt +++ b/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt @@ -1,5 +1,6 @@ package trees.templates +import trees.implementations.AVLVertex import java.util.Stack abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate> { @@ -21,6 +22,48 @@ abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate Vertex_t): Pair { + if (root == null) { + val newVertex = fabric(key, value) + root = newVertex + return Pair(newVertex, null) + } + + var cur = root ?: throw IllegalStateException("Case when root is null is processed above") + while (true) { + val result = key.compareTo(cur.key) + if (result < 0) { + if (cur.left == null) { + val newVertex = fabric(key, value) + cur.left = newVertex + newVertex.parent = cur + return Pair(newVertex, null) + } + cur = cur.left ?: throw IllegalStateException("Case when cur.left is null is processed above") + } else if (result > 0) { + if (cur.right == null) { + val newVertex = fabric(key, value) + cur.right = newVertex + newVertex.parent = cur + return Pair(newVertex, null) + } + cur = cur.right ?: throw IllegalStateException("Case when cur.right is null is processed above") + } else { + val oldValue = cur.value + cur.value = value + return Pair(cur, oldValue) + } + } + } + /** * Associates the specified value with the specified key if this key is not in the tree. * @return true if this key is not in the tree, otherwise false From dfdbb7d805c662067b0bf8515d82e7bb87fc1459 Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Tue, 2 Apr 2024 14:47:59 +0300 Subject: [PATCH 090/108] ref: code refactor --- .../main/kotlin/trees/implementations/RBTree.kt | 8 ++------ .../kotlin/trees/implementations/SimpleTree.kt | 17 ++++------------- .../kotlin/trees/templates/BSTreeTemplate.kt | 1 - 3 files changed, 6 insertions(+), 20 deletions(-) diff --git a/lib/src/main/kotlin/trees/implementations/RBTree.kt b/lib/src/main/kotlin/trees/implementations/RBTree.kt index 187af77..b074153 100644 --- a/lib/src/main/kotlin/trees/implementations/RBTree.kt +++ b/lib/src/main/kotlin/trees/implementations/RBTree.kt @@ -1,7 +1,6 @@ package trees.implementations import trees.templates.BalanceBSTreeTemplate -import java.sql.Blob class RBTree, V> : BalanceBSTreeTemplate>() { @@ -108,11 +107,8 @@ class RBTree, V> : BalanceBSTreeTemplate> } override fun remove(key: K): V? { - val vertex = vertByKey(key) + val vertex = vertByKey(key) ?: return null - if (vertex == null) { - return null - } size -= 1 val replacedVertex: RBVertex? val deletedVertexColor: RBVertex.Color @@ -172,7 +168,7 @@ class RBTree, V> : BalanceBSTreeTemplate> private fun manageBlackRedOne(vertex: RBVertex?, argBrother: RBVertex?) { var brother = argBrother - val isParent = if (vertex == vertex?.parent?.left) true else false + val isParent = vertex == vertex?.parent?.left if (isParent && brother?.right?.color == black) { brother.left?.color = black brother.color = red diff --git a/lib/src/main/kotlin/trees/implementations/SimpleTree.kt b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt index d4a5fe3..ffc277a 100644 --- a/lib/src/main/kotlin/trees/implementations/SimpleTree.kt +++ b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt @@ -18,19 +18,10 @@ class SimpleTree, V> : BSTreeTemplate parent.left == vertex -> parent.left = null else -> parent.right = null } - } else if (vertex.right == null) { - val successor = maxVertex(vertex.left) - val successorParent = successor?.parent - successor?.let { - vertex.key = it.key - vertex.value = it.value - } - when { - successorParent?.left == successor -> successorParent?.left = null - successorParent?.right == successor -> successorParent?.right = null - } } else { - val successor = minVertex(vertex.right) + val successor = if (vertex.right == null) { + maxVertex(vertex.left) + } else minVertex(vertex.right) val successorParent = successor?.parent successor?.let { vertex.key = it.key @@ -46,7 +37,7 @@ class SimpleTree, V> : BSTreeTemplate } override operator fun set(key: K, value: V): V? { - val (currentVert, oldValue) = setWithoutBalance(key, value, ::fabricVertex) + val oldValue = setWithoutBalance(key, value, ::fabricVertex).second if (oldValue == null) { size += 1 } diff --git a/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt b/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt index e4a9252..902c0cf 100644 --- a/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt +++ b/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt @@ -1,6 +1,5 @@ package trees.templates -import trees.implementations.AVLVertex import java.util.Stack abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate> { From d81081e82a5e70accca7bf1d43fcaa144209a5b2 Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Tue, 2 Apr 2024 15:01:23 +0300 Subject: [PATCH 091/108] Fix typos --- lib/src/test/kotlin/trees/bstest/BSTreeTest.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt b/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt index 3751a41..d5f9b1b 100644 --- a/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt +++ b/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt @@ -114,7 +114,7 @@ class BSTreeTest { } @Test - fun testRemoveRootWith2Childs() { + fun testRemoveRootWith2Children() { val keys = intArrayOf(0, -1, 2, 1, 3) for (key in keys) { simpleTree[key] = key @@ -127,7 +127,7 @@ class BSTreeTest { } @Test - fun testRemoveRigthRootWithoutChilds() { + fun testRemoveRightRootWithoutChildren() { val keys = intArrayOf(0, -1, 2) for (key in keys) { simpleTree[key] = key From 8b1cd35dfd2fc28b142528a66d98cf8ee48c6fb9 Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Wed, 3 Apr 2024 11:32:01 +0300 Subject: [PATCH 092/108] Delete private method `maxVert` Delete because the `maxVertex` method already exists --- lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt b/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt index 902c0cf..efcc548 100644 --- a/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt +++ b/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt @@ -161,15 +161,7 @@ abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate by maximum key in the tree. If tree is empty then returns null */ fun max(): Pair? { - return maxVert(root)?.toPair() - } - - private fun maxVert(vertex: Vertex_t?): Vertex_t? { - var cur = vertex - while (cur?.right != null) { - cur = cur.right - } - return cur + return maxVertex(root)?.toPair() } protected fun vertByKey(key: K): Vertex_t? { From 5311898cc7829712b15d8c918fa6b49611b86073 Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Fri, 5 Apr 2024 07:22:35 +0300 Subject: [PATCH 093/108] Change root visibility modifier to protected -open AvlTree, RBTree and SimpleTree for extension -create AvlTestTree, RBTestTree and SimpleTestTree for getting root and testing inner structure of the trees --- .../kotlin/trees/implementations/AvlTree.kt | 3 +- .../kotlin/trees/implementations/RBTree.kt | 2 +- .../trees/implementations/SimpleTree.kt | 3 +- .../kotlin/trees/templates/BSTreeTemplate.kt | 3 +- .../kotlin/trees/avltest/AvlGeneralTest.kt | 32 +++++++++---------- .../kotlin/trees/avltest/AvlSpecificTest.kt | 30 ++++++++--------- .../test/kotlin/trees/avltest/AvlTestTree.kt | 10 ++++++ .../test/kotlin/trees/bstest/BSTreeTest.kt | 6 ++-- .../kotlin/trees/bstest/SimpleTestTree.kt | 10 ++++++ lib/src/test/kotlin/trees/rbtest/RBTest.kt | 8 ++--- .../test/kotlin/trees/rbtest/RBTestTree.kt | 12 +++++++ 11 files changed, 74 insertions(+), 45 deletions(-) create mode 100644 lib/src/test/kotlin/trees/avltest/AvlTestTree.kt create mode 100644 lib/src/test/kotlin/trees/bstest/SimpleTestTree.kt create mode 100644 lib/src/test/kotlin/trees/rbtest/RBTestTree.kt diff --git a/lib/src/main/kotlin/trees/implementations/AvlTree.kt b/lib/src/main/kotlin/trees/implementations/AvlTree.kt index 81d6293..d0a2b49 100644 --- a/lib/src/main/kotlin/trees/implementations/AvlTree.kt +++ b/lib/src/main/kotlin/trees/implementations/AvlTree.kt @@ -2,7 +2,7 @@ package trees.implementations import trees.templates.BalanceBSTreeTemplate -class AvlTree, V> : BalanceBSTreeTemplate>() { +open class AvlTree, V> : BalanceBSTreeTemplate>() { override operator fun set(key: K, value: V): V? { val (currentVert, oldValue) = setWithoutBalance(key, value, ::fabricVertex) if (oldValue == null) { @@ -16,7 +16,6 @@ class AvlTree, V> : BalanceBSTreeTemplate, V> : BalanceBSTreeTemplate>() { +open class RBTree, V> : BalanceBSTreeTemplate>() { override fun fabricVertex(key: K, value: V): RBVertex { return RBVertex(key, value) diff --git a/lib/src/main/kotlin/trees/implementations/SimpleTree.kt b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt index ffc277a..f20a0fd 100644 --- a/lib/src/main/kotlin/trees/implementations/SimpleTree.kt +++ b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt @@ -2,7 +2,7 @@ package trees.implementations import trees.templates.BSTreeTemplate -class SimpleTree, V> : BSTreeTemplate>() { +open class SimpleTree, V> : BSTreeTemplate>() { override fun fabricVertex(key: K, value: V): SimpleVertex { return SimpleVertex(key, value) @@ -43,5 +43,4 @@ class SimpleTree, V> : BSTreeTemplate } return oldValue } - } diff --git a/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt b/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt index 902c0cf..b65b363 100644 --- a/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt +++ b/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt @@ -3,8 +3,7 @@ package trees.templates import java.util.Stack abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate> { - var root: Vertex_t? = null - protected set + protected var root: Vertex_t? = null var size: Int = 0 protected set(value) { if (value >= 0) { diff --git a/lib/src/test/kotlin/trees/avltest/AvlGeneralTest.kt b/lib/src/test/kotlin/trees/avltest/AvlGeneralTest.kt index a5dcc27..e8619d4 100644 --- a/lib/src/test/kotlin/trees/avltest/AvlGeneralTest.kt +++ b/lib/src/test/kotlin/trees/avltest/AvlGeneralTest.kt @@ -10,11 +10,11 @@ import trees.avltest.AvlSpecificTest.Companion.checkTreeInvariant import kotlin.test.assertIs class AvlGeneralTest { - private lateinit var avlTree: AvlTree + private lateinit var avlTree: AvlTestTree @BeforeEach fun setup() { - avlTree = AvlTree() + avlTree = AvlTestTree() } @Test @@ -29,7 +29,7 @@ class AvlGeneralTest { val expectedSize = 5 val actualSize = avlTree.size assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") - checkTreeInvariant(avlTree.root) + checkTreeInvariant(avlTree.getRootAvl()) } @Test @@ -48,7 +48,7 @@ class AvlGeneralTest { actualSize, "Size of the tree must not change after overwriting an existing key", ) - checkTreeInvariant(avlTree.root) + checkTreeInvariant(avlTree.getRootAvl()) } @Test @@ -67,7 +67,7 @@ class AvlGeneralTest { actualSize, "Size of the tree must not change after overwriting an existing key", ) - checkTreeInvariant(avlTree.root) + checkTreeInvariant(avlTree.getRootAvl()) } @Test @@ -131,7 +131,7 @@ class AvlGeneralTest { actualResult, "Tree must save all other vertices after remove vertex with existing left vertex", ) - checkTreeInvariant(avlTree.root) + checkTreeInvariant(avlTree.getRootAvl()) } @Test @@ -147,7 +147,7 @@ class AvlGeneralTest { actualResult, "Tree must save all other vertices after remove root of right subtree with existing left vertex", ) - checkTreeInvariant(avlTree.root) + checkTreeInvariant(avlTree.getRootAvl()) } @Test @@ -163,7 +163,7 @@ class AvlGeneralTest { actualResult, "Tree must save all other vertices after remove vertex with right subtree of height 1", ) - checkTreeInvariant(avlTree.root) + checkTreeInvariant(avlTree.getRootAvl()) } @Test @@ -179,9 +179,9 @@ class AvlGeneralTest { actualResult, "Tree must save all other vertices after remove vertex with right subtree of height >1", ) - checkTreeInvariant(avlTree.root) + checkTreeInvariant(avlTree.getRootAvl()) avlTree[5] = 5 - checkTreeInvariant(avlTree.root) + checkTreeInvariant(avlTree.getRootAvl()) } @Test @@ -196,7 +196,7 @@ class AvlGeneralTest { val iterator = avlTree.iterator() val actualResult: Array = Array(7, { iterator.next().second }) assertContentEquals(expectedResult, actualResult, "Iterator must return vertices in keys order") - checkTreeInvariant(avlTree.root) + checkTreeInvariant(avlTree.getRootAvl()) } @Test @@ -223,7 +223,7 @@ class AvlGeneralTest { avlTree.clear() assertEquals(avlTree.size, 0, "Size of the tree must be 0 after clear") - assertEquals(avlTree.root, null, "Root of the tree must be null after clear") + assertEquals(avlTree.getRootAvl(), null, "Root of the tree must be null after clear") } @Test @@ -284,7 +284,7 @@ class AvlGeneralTest { val actualResult = avlTree.max() assertEquals(expectedResult, actualResult, "Max must return Pairs by max key in the tree") - checkTreeInvariant(avlTree.root) + checkTreeInvariant(avlTree.getRootAvl()) } @@ -298,7 +298,7 @@ class AvlGeneralTest { val actualResult = avlTree.max() assertEquals(expectedResult, actualResult, "Max must return Pair by max key in the tree") - checkTreeInvariant(avlTree.root) + checkTreeInvariant(avlTree.getRootAvl()) } @Test @@ -310,7 +310,7 @@ class AvlGeneralTest { val expectedResult = Pair(-46, -46) val actualResult = avlTree.min() assertEquals(expectedResult, actualResult, "Min must return Pair by min key in the tree") - checkTreeInvariant(avlTree.root) + checkTreeInvariant(avlTree.getRootAvl()) } @@ -325,7 +325,7 @@ class AvlGeneralTest { val actualResult = avlTree.min() assertEquals(expectedResult, actualResult, "Min must return Pair by min key in the tree") - checkTreeInvariant(avlTree.root) + checkTreeInvariant(avlTree.getRootAvl()) } @Test diff --git a/lib/src/test/kotlin/trees/avltest/AvlSpecificTest.kt b/lib/src/test/kotlin/trees/avltest/AvlSpecificTest.kt index 7408070..7153079 100644 --- a/lib/src/test/kotlin/trees/avltest/AvlSpecificTest.kt +++ b/lib/src/test/kotlin/trees/avltest/AvlSpecificTest.kt @@ -9,7 +9,7 @@ import kotlin.test.assertContentEquals import kotlin.test.assertEquals class AvlSpecificTest { - private lateinit var avlTree: AvlTree + private lateinit var avlTree: AvlTestTree companion object { /** @@ -38,7 +38,7 @@ class AvlSpecificTest { @BeforeEach fun setup() { - avlTree = AvlTree() + avlTree = AvlTestTree() } @Test @@ -54,7 +54,7 @@ class AvlSpecificTest { actualResult, "Tree must save all other vertices after remove that creates unbalance situation", ) - checkTreeInvariant(avlTree.root) + checkTreeInvariant(avlTree.getRootAvl()) } @Test @@ -63,7 +63,7 @@ class AvlSpecificTest { for (key in keys) avlTree[key] = key avlTree.remove(4) - assertTrue(avlTree.root != null) + assertTrue(avlTree.getRootAvl() != null) val expectedResult = arrayOf(null, 1, 6, 0, 3, 5, 2) val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( @@ -71,7 +71,7 @@ class AvlSpecificTest { actualResult, "Tree must save all other vertices after root remove", ) - checkTreeInvariant(avlTree.root) + checkTreeInvariant(avlTree.getRootAvl()) } @Test @@ -86,7 +86,7 @@ class AvlSpecificTest { actualResult, "Get must return corresponding values after left rotate ( right.diffHeight = -1)", ) - checkTreeInvariant(avlTree.root) + checkTreeInvariant(avlTree.getRootAvl()) // 0 0 2 // / \ / \ / \ @@ -110,7 +110,7 @@ class AvlSpecificTest { actualResult, "Get must return corresponding values after left rotate (right.diffHeight = 0)", ) - checkTreeInvariant(avlTree.root) + checkTreeInvariant(avlTree.getRootAvl()) // 0 0 4 // / \ / \ / \ // -1 4 -1 4 0 6 @@ -132,7 +132,7 @@ class AvlSpecificTest { actualResult, "Get must return corresponding values after right rotate (left.diffHeight = 1)", ) - checkTreeInvariant(avlTree.root) + checkTreeInvariant(avlTree.getRootAvl()) // 0 0 -1 // / \ / \ / \ @@ -156,7 +156,7 @@ class AvlSpecificTest { actualResult, "Get must return corresponding values after right rotate (left.diffHeight = 0)", ) - checkTreeInvariant(avlTree.root) + checkTreeInvariant(avlTree.getRootAvl()) // 7 7 3 // / \ / \ / \ @@ -179,7 +179,7 @@ class AvlSpecificTest { actualResult, "Get must return corresponding values after right-left rotate with right.left.diffHeight = 1", ) - checkTreeInvariant(avlTree.root) + checkTreeInvariant(avlTree.getRootAvl()) // 1 1 3 // / \ / \ / \ @@ -203,7 +203,7 @@ class AvlSpecificTest { actualResult, "Get must return corresponding values after right-left rotate with right.left.diffHeight = 0", ) - checkTreeInvariant(avlTree.root) + checkTreeInvariant(avlTree.getRootAvl()) } @Test @@ -218,7 +218,7 @@ class AvlSpecificTest { actualResult, "Get must return corresponding values after right-left rotate with right.left.diffHeight = -1", ) - checkTreeInvariant(avlTree.root) + checkTreeInvariant(avlTree.getRootAvl()) } @Test @@ -233,7 +233,7 @@ class AvlSpecificTest { actualResult, "Get must return corresponding values after left-right rotate with left.right.diffHeight = -1", ) - checkTreeInvariant(avlTree.root) + checkTreeInvariant(avlTree.getRootAvl()) } @Test @@ -249,7 +249,7 @@ class AvlSpecificTest { actualResult, "Get must return corresponding values after left-right rotate with left.right.diffHeight = 0", ) - checkTreeInvariant(avlTree.root) + checkTreeInvariant(avlTree.getRootAvl()) } @Test @@ -264,6 +264,6 @@ class AvlSpecificTest { actualResult, "Get must return corresponding values after left-right rotate with left.right.diffHeight = 1", ) - checkTreeInvariant(avlTree.root) + checkTreeInvariant(avlTree.getRootAvl()) } } diff --git a/lib/src/test/kotlin/trees/avltest/AvlTestTree.kt b/lib/src/test/kotlin/trees/avltest/AvlTestTree.kt new file mode 100644 index 0000000..272035f --- /dev/null +++ b/lib/src/test/kotlin/trees/avltest/AvlTestTree.kt @@ -0,0 +1,10 @@ +package trees.avltest + +import trees.implementations.AVLVertex +import trees.implementations.AvlTree + +class AvlTestTree, V> : AvlTree() { + fun getRootAvl(): AVLVertex? { + return this.root + } +} \ No newline at end of file diff --git a/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt b/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt index d5f9b1b..a489a5b 100644 --- a/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt +++ b/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt @@ -8,16 +8,16 @@ import kotlin.test.assertContentEquals import kotlin.test.assertEquals class BSTreeTest { - private lateinit var simpleTree: SimpleTree + private lateinit var simpleTree: SimpleTestTree @BeforeEach fun setup() { - simpleTree = SimpleTree() + simpleTree = SimpleTestTree() } @Test fun testCheckEmptyTree() { - assertNull(simpleTree.root) + assertNull(simpleTree.getRootSimple()) assertEquals(0, simpleTree.size) } diff --git a/lib/src/test/kotlin/trees/bstest/SimpleTestTree.kt b/lib/src/test/kotlin/trees/bstest/SimpleTestTree.kt new file mode 100644 index 0000000..e9828f0 --- /dev/null +++ b/lib/src/test/kotlin/trees/bstest/SimpleTestTree.kt @@ -0,0 +1,10 @@ +package trees.bstest + +import trees.implementations.SimpleTree +import trees.implementations.SimpleVertex + +class SimpleTestTree, V> : SimpleTree() { + fun getRootSimple(): SimpleVertex? { + return this.root + } +} \ No newline at end of file diff --git a/lib/src/test/kotlin/trees/rbtest/RBTest.kt b/lib/src/test/kotlin/trees/rbtest/RBTest.kt index 59d4546..b7913d9 100644 --- a/lib/src/test/kotlin/trees/rbtest/RBTest.kt +++ b/lib/src/test/kotlin/trees/rbtest/RBTest.kt @@ -8,11 +8,11 @@ import kotlin.test.assertContentEquals import kotlin.test.assertEquals class RBTest { - private lateinit var rbTree: RBTree + private lateinit var rbTree: RBTestTree @BeforeEach fun setup() { - rbTree = RBTree() + rbTree = RBTestTree() } @Test @@ -178,7 +178,7 @@ class RBTest { val keys = intArrayOf(4, 1, 6, 0, 3, 5, 2) for (key in keys) rbTree[key] = key rbTree.remove(4) - Assertions.assertTrue(rbTree.root != null) + Assertions.assertTrue(rbTree.getRootRB() != null) val expectedResult = arrayOf(null, 1, 6, 0, 3, 5, 2) val actualResult = Array(keys.size) { i -> rbTree[keys[i]] } assertContentEquals( @@ -186,7 +186,7 @@ class RBTest { actualResult, ) } - + @Test fun `remove a non-existent key`() { rbTree[0] = 15 diff --git a/lib/src/test/kotlin/trees/rbtest/RBTestTree.kt b/lib/src/test/kotlin/trees/rbtest/RBTestTree.kt new file mode 100644 index 0000000..a88a28e --- /dev/null +++ b/lib/src/test/kotlin/trees/rbtest/RBTestTree.kt @@ -0,0 +1,12 @@ +package trees.rbtest + +import trees.implementations.AVLVertex +import trees.implementations.AvlTree +import trees.implementations.RBTree +import trees.implementations.RBVertex + +class RBTestTree, V> : RBTree() { + fun getRootRB(): RBVertex? { + return this.root + } +} \ No newline at end of file From 6010250352e3486478021ef0b9775a357d0eaf8e Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Sun, 7 Apr 2024 00:27:52 +0300 Subject: [PATCH 094/108] Change: add megalinter-report in .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 889ee4e..3e8f2f6 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ # Ignore Gradle build output directory build /.idea/ +/megalinter-reports/ From 2efe0bf0b15e4642ef6c73de4c62cbb25d708aa8 Mon Sep 17 00:00:00 2001 From: Azamat Ishbaev <143432879+odiumuniverse@users.noreply.github.com> Date: Sun, 7 Apr 2024 00:28:24 +0300 Subject: [PATCH 095/108] Delete megalinter-reports directory --- megalinter-reports/IDE-config.txt | 15 - .../linters_logs/SUCCESS-KOTLIN_KTLINT.log | 6 - megalinter-reports/megalinter.log | 55 --- .../kotlin/bstrees/implementations/AVLTree.kt | 307 ------------ .../kotlin/bstrees/implementations/RBTree.kt | 292 ------------ .../bstrees/implementations/SimpleTree.kt | 77 --- .../bstrees/implementations/Vertices.kt | 25 - .../bstrees/templates/BSTreeTemplate.kt | 155 ------- .../templates/BalanceBSTreeTemplate.kt | 4 - .../bstrees/templates/VertexTemplate.kt | 15 - .../lib/src/test/kotlin/trees/AVLTreeTest.kt | 439 ------------------ .../src/test/kotlin/trees/rbtest/RBTest.kt | 113 ----- .../linters_logs/SUCCESS-KOTLIN_KTLINT.log | 6 - .../megalinter-reports/megalinter.log | 51 -- 14 files changed, 1560 deletions(-) delete mode 100644 megalinter-reports/IDE-config.txt delete mode 100644 megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log delete mode 100644 megalinter-reports/megalinter.log delete mode 100644 megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt delete mode 100644 megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/RBTree.kt delete mode 100644 megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt delete mode 100644 megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/Vertices.kt delete mode 100644 megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt delete mode 100644 megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt delete mode 100644 megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt delete mode 100644 megalinter-reports/updated_sources/lib/src/test/kotlin/trees/AVLTreeTest.kt delete mode 100644 megalinter-reports/updated_sources/lib/src/test/kotlin/trees/rbtest/RBTest.kt delete mode 100644 megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log delete mode 100644 megalinter-reports/updated_sources/megalinter-reports/megalinter.log diff --git a/megalinter-reports/IDE-config.txt b/megalinter-reports/IDE-config.txt deleted file mode 100644 index be5715f..0000000 --- a/megalinter-reports/IDE-config.txt +++ /dev/null @@ -1,15 +0,0 @@ -MegaLinter can help you to define the same linter configuration locally - -INSTRUCTIONS - -- Copy the content of IDE-config folder at the root of your repository -- if you are using Visual Studio Code, just reopen your project after the copy, and you will be prompted to install recommended extensions -- If not, you can install extensions manually using the following links. - -IDE EXTENSIONS APPLICABLE TO YOUR PROJECT - -ktlint (KOTLIN) - - emacs: - - flycheck-kotlin: https://github.com/whirm/flycheck-kotlin - - vim: - - ale: https://github.com/w0rp/ale diff --git a/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log b/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log deleted file mode 100644 index d229ece..0000000 --- a/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log +++ /dev/null @@ -1,6 +0,0 @@ -Results of ktlint linter (version 1.2.1) -See documentation on https://megalinter.io/7.10.0/descriptors/kotlin_ktlint/ ------------------------------------------------ - -✅ [SUCCESS] lib/src/main/kotlin/trees/implementations/RBTree.kt -✅ [SUCCESS] lib/src/test/kotlin/trees/rbtest/RBTest.kt - FIXED diff --git a/megalinter-reports/megalinter.log b/megalinter-reports/megalinter.log deleted file mode 100644 index e720373..0000000 --- a/megalinter-reports/megalinter.log +++ /dev/null @@ -1,55 +0,0 @@ ----------------------------------------------------------------------------------------------------- ------------------------------------- MegaLinter, by OX Security ------------------------------------ ----------------------------------------------------------------------------------------------------- - - Image Creation Date: 2024-03-10T20:25:08Z - - Image Revision: a7a0163b6c8ff7474a283d99a706e27483ddd80f - - Image Version: v7.10.0 ----------------------------------------------------------------------------------------------------- -The MegaLinter documentation can be found at: - - https://megalinter.io/7.10.0 ----------------------------------------------------------------------------------------------------- -::group::MegaLinter initialization (expand for details) -MegaLinter will analyze workspace [/github/workspace] -GITHUB_REPOSITORY: spbu-coding-2023/trees-8 -GITHUB_REF: refs/pull/18/merge -GITHUB_RUN_ID: 8500266858 - - -CLOJURE_CLJSTYLE has been temporary disabled in MegaLinter, please use a previous MegaLinter version or wait for the next one ! -MARKDOWN_REMARK_LINT has been temporary disabled in MegaLinter, please use a previous MegaLinter version or wait for the next one ! -Skipped linters: ACTION_ACTIONLINT, ANSIBLE_ANSIBLE_LINT, ARM_ARM_TTK, BASH_EXEC, BASH_SHELLCHECK, BASH_SHFMT, BICEP_BICEP_LINTER, CLOJURE_CLJSTYLE, CLOJURE_CLJ_KONDO, CLOUDFORMATION_CFN_LINT, COFFEE_COFFEELINT, COPYPASTE_JSCPD, CPP_CLANG_FORMAT, CPP_CPPLINT, CSHARP_CSHARPIER, CSHARP_DOTNET_FORMAT, CSHARP_ROSLYNATOR, CSS_SCSS_LINT, CSS_STYLELINT, C_CLANG_FORMAT, C_CPPLINT, DART_DARTANALYZER, DOCKERFILE_HADOLINT, EDITORCONFIG_EDITORCONFIG_CHECKER, ENV_DOTENV_LINTER, GHERKIN_GHERKIN_LINT, GO_GOLANGCI_LINT, GO_REVIVE, GRAPHQL_GRAPHQL_SCHEMA_LINTER, GROOVY_NPM_GROOVY_LINT, HTML_DJLINT, HTML_HTMLHINT, JAVASCRIPT_ES, JAVASCRIPT_PRETTIER, JAVASCRIPT_STANDARD, JAVA_CHECKSTYLE, JAVA_PMD, JSON_ESLINT_PLUGIN_JSONC, JSON_JSONLINT, JSON_NPM_PACKAGE_JSON_LINT, JSON_PRETTIER, JSON_V8R, JSX_ESLINT, KUBERNETES_HELM, KUBERNETES_KUBECONFORM, KUBERNETES_KUBESCAPE, LATEX_CHKTEX, LUA_LUACHECK, MAKEFILE_CHECKMAKE, MARKDOWN_MARKDOWNLINT, MARKDOWN_MARKDOWN_LINK_CHECK, MARKDOWN_MARKDOWN_TABLE_FORMATTER, MARKDOWN_REMARK_LINT, OPENAPI_SPECTRAL, PERL_PERLCRITIC, PHP_PHPCS, PHP_PHPLINT, PHP_PHPSTAN, PHP_PSALM, POWERSHELL_POWERSHELL, POWERSHELL_POWERSHELL_FORMATTER, PROTOBUF_PROTOLINT, PUPPET_PUPPET_LINT, PYTHON_BANDIT, PYTHON_BLACK, PYTHON_FLAKE8, PYTHON_ISORT, PYTHON_MYPY, PYTHON_PYLINT, PYTHON_PYRIGHT, PYTHON_RUFF, RAKU_RAKU, REPOSITORY_CHECKOV, REPOSITORY_DEVSKIM, REPOSITORY_DUSTILOCK, REPOSITORY_GITLEAKS, REPOSITORY_GIT_DIFF, REPOSITORY_GRYPE, REPOSITORY_KICS, REPOSITORY_SECRETLINT, REPOSITORY_SEMGREP, REPOSITORY_SYFT, REPOSITORY_TRIVY, REPOSITORY_TRIVY_SBOM, REPOSITORY_TRUFFLEHOG, RST_RSTCHECK, RST_RSTFMT, RST_RST_LINT, RUBY_RUBOCOP, RUST_CLIPPY, R_LINTR, SALESFORCE_LIGHTNING_FLOW_SCANNER, SALESFORCE_SFDX_SCANNER_APEX, SALESFORCE_SFDX_SCANNER_AURA, SALESFORCE_SFDX_SCANNER_LWC, SCALA_SCALAFIX, SNAKEMAKE_LINT, SNAKEMAKE_SNAKEFMT, SPELL_CSPELL, SPELL_LYCHEE, SPELL_PROSELINT, SPELL_VALE, SQL_SQLFLUFF, SQL_SQL_LINT, SQL_TSQLLINT, SWIFT_SWIFTLINT, TEKTON_TEKTON_LINT, TERRAFORM_TERRAFORM_FMT, TERRAFORM_TERRAGRUNT, TERRAFORM_TERRASCAN, TERRAFORM_TFLINT, TSX_ESLINT, TYPESCRIPT_ES, TYPESCRIPT_PRETTIER, TYPESCRIPT_STANDARD, VBDOTNET_DOTNET_FORMAT, XML_XMLLINT, YAML_PRETTIER, YAML_V8R, YAML_YAMLLINT -To receive reports as email, please set variable EMAIL_REPORTER_EMAIL -::endgroup:: -::group::MegaLinter now collects the files to analyse (expand for details) -Listing updated files in [/github/workspace] using git diff. -Modified files: -lib/src/main/kotlin/trees/implementations/RBTree.kt -lib/src/test/kotlin/trees/rbtest/RBTest.kt -megalinter-reports/megalinter.log -- File extensions: .kt, .kts -- Excluding .gitignored files [0]: -Kept [2] files on [3] found files - -+----MATCHING LINTERS-+----------+----------------+------------+ -| Descriptor | Linter | Criteria | Matching files | Format/Fix | -+------------+--------+----------+----------------+------------+ -| KOTLIN | ktlint | .kt|.kts | 2 | yes | -+------------+--------+----------+----------------+------------+ -::endgroup:: -::group::✅ Linted [KOTLIN] files with [ktlint] successfully - (2.95s) (expand for details) -- Using [ktlint v1.2.1] https://megalinter.io/7.10.0/descriptors/kotlin_ktlint -- MegaLinter key: [KOTLIN_KTLINT] -- Rules config: identified by [ktlint] -- Number of files analyzed: [2] -::endgroup:: - -+----SUMMARY-+--------+------+-------+-------+--------+--------------+ -| Descriptor | Linter | Mode | Files | Fixed | Errors | Elapsed time | -+------------+--------+------+-------+-------+--------+--------------+ -| ✅ KOTLIN | ktlint | file | 2 | 1 | 0 | 2.95s | -+------------+--------+------+-------+-------+--------+--------------+ - -[Updated Sources Reporter] copied 3 fixed source files in folder /github/workspace/megalinter-reports/updated_sources. -Download it from artifacts then copy-paste it in your local repo to apply linters updates -[GitHub Comment Reporter] Posted summary as comment on spbu-coding-2023/trees-8 #PR18 -✅ Successfully linted all files without errors diff --git a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt deleted file mode 100644 index 77f2377..0000000 --- a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/AVLTree.kt +++ /dev/null @@ -1,307 +0,0 @@ -package bstrees.implementations - -import bstrees.templates.BalanceBSTreeTemplate - -class AVLTree, V> : BalanceBSTreeTemplate>() { - public override operator fun set( - key: K, - value: V, - ): V? { - val (currentVert, oldValue) = setWithoutBalance(key, value) - if (oldValue == null) { - size += 1 - balanceAfterSet(currentVert) - } - return oldValue - } - - /** - * Set specified value by specified key - * - * Returns: a pair of set vertex and old value. - * If key didn't exist, the returned value is null. - */ - private fun setWithoutBalance( - key: K, - value: V, - ): Pair, V?> { - if (root == null) { - val newVertex = AVLVertex(key, value) - root = newVertex - return Pair(newVertex, null) - } - - var cur = root ?: throw IllegalStateException("Case when root is null is processed above") - while (true) { - val result = key.compareTo(cur.key) - if (result < 0) { - if (cur.left == null) { - val newVertex = AVLVertex(key, value) - cur.left = newVertex - newVertex.parent = cur - return Pair(newVertex, null) - } - cur = cur.left ?: throw IllegalStateException("Case when cur.left is null is processed above") - } else if (result > 0) { - if (cur.right == null) { - val newVertex = AVLVertex(key, value) - cur.right = newVertex - newVertex.parent = cur - return Pair(newVertex, null) - } - cur = cur.right ?: throw IllegalStateException("Case when cur.rightt is null is processed above") - } else { - val oldValue = cur.value - cur.value = value - return Pair(cur, oldValue) - } - } - } - - /** - * Climbing up the tree, updates diffHeights of vertices after set and calls - * [balanceOnce] if vertex became unbalanced - */ - private fun balanceAfterSet(vertex: AVLVertex) { - var cur = vertex - var prevKey = cur.key - while (cur.parent != null) { - prevKey = cur.key - cur = cur.parent ?: throw IllegalStateException("Parent can't be null due to while condition") - if (prevKey == cur.left?.key) { - cur.diffHeight += 1 - } else if (prevKey == cur.right?.key) { - cur.diffHeight -= 1 - } - - cur = balanceOnce(cur) - if (cur.diffHeight == 0) break - } - } - - public override fun remove(key: K): V? { - val toRemove = vertByKey(key) ?: return null - val oldValue = toRemove.value - removeVert(toRemove) - size -= 1 - return oldValue - } - - /** - * Removes specified vertex and balances the tree - */ - private fun removeVert(toRemove: AVLVertex) { - val parent = toRemove.parent - if (toRemove.left == null && toRemove.right == null) { - when { - parent == null -> root = null - - parent.left == toRemove -> { - parent.left = null - parent.diffHeight -= 1 - } - - parent.right == toRemove -> { - parent.right = null - parent.diffHeight += 1 - } - } - balanceAfterRemove(parent) - } else if (toRemove.right == null) { - toRemove.left?.let { - toRemove.key = it.key - toRemove.value = it.value - toRemove.left = null - toRemove.diffHeight = 0 - } - balanceAfterRemove(parent) - when { - parent?.left == toRemove -> parent.diffHeight -= 1 - parent?.right == toRemove -> parent.diffHeight += 1 - } - } else { - val minRight = - minVertex(toRemove.right) - ?: throw IllegalStateException("min of subtree can't be null if it's contains at least one element") - toRemove.key = minRight.key - toRemove.value = minRight.value - removeVert(minRight) - } - } - - /** - * Climbing up the tree, updates diffHeights of vertices after remove and calls - * [balanceOnce] if vertex became unbalanced - */ - private fun balanceAfterRemove(vertex: AVLVertex?) { - var cur = vertex ?: return - while (cur.diffHeight != 1 && cur.diffHeight != -1) { - cur = balanceOnce(cur) - if (cur.diffHeight != 1 && cur.diffHeight != -1) { - when { - cur.parent?.left == cur -> cur.parent?.let { it.diffHeight -= 1 } - cur.parent?.right == cur -> cur.parent?.let { it.diffHeight += 1 } - } - } - cur = cur.parent ?: return - } - } - - private fun getDiffHeight(vertex: AVLVertex?): Int { - return vertex?.diffHeight ?: 0 - } - - /** - * Balances subtree by specified root, updates diffHeights of vertices - * @return new root of subtree - */ - private fun balanceOnce(_vertex: AVLVertex): AVLVertex { - var vertex = _vertex - if (vertex.diffHeight == 2) { - if (getDiffHeight(vertex.left) >= 0) { - vertex = rotateRight(vertex) - } else if (getDiffHeight(vertex.left) == -1) { - vertex.left?.let { - vertex.left = rotateLeft(it) - vertex = rotateRight(vertex) - } - } - } else if (vertex.diffHeight == -2) { - if (getDiffHeight(vertex.right) <= 0) { - vertex = rotateLeft(vertex) - } else if (getDiffHeight(vertex.right) == 1) { - vertex.right?.let { - rotateRight(it) - vertex = rotateLeft(vertex) - } - } - } - return vertex - } - - private fun rotateRight(origin: AVLVertex): AVLVertex { - val left = - origin.left - ?: throw IllegalStateException("Height difference can't be 2 if left Vertex doesn't exist") - - left.parent = origin.parent - if (origin.parent?.left == origin) { - origin.parent?.left = left - } else { - origin.parent?.right = left - } - - origin.parent = left - origin.left = left.right - origin.left?.parent = origin - left.right = origin - - when (origin.diffHeight) { - 2 -> { - when (left.diffHeight) { - 0 -> { - origin.diffHeight = 1 - left.diffHeight = -1 - } - - 1 -> { - origin.diffHeight = 0 - left.diffHeight = 0 - } - - 2 -> { - origin.diffHeight = -1 - left.diffHeight = 0 - } - } - } - - 1 -> { - when (left.diffHeight) { - 0 -> { - origin.diffHeight = 0 - left.diffHeight = -1 - } - - 1 -> { - origin.diffHeight = -1 - left.diffHeight = -1 - } - - -1 -> { - origin.diffHeight = 0 - left.diffHeight = -2 - } - } - } - } - - if (origin == root) { - root = left - } - return left - } - - private fun rotateLeft(origin: AVLVertex): AVLVertex { - val right = - origin.right - ?: throw IllegalStateException("Height difference can't be 2 if left Vertex doesn't exist") - - right.parent = origin.parent - if (origin.parent?.left == origin) { - origin.parent?.left = right - } else { - origin.parent?.right = right - } - - origin.parent = right - origin.right = right.left - origin.right?.parent = origin - right.left = origin - - when (origin.diffHeight) { - -2 -> { - when (right.diffHeight) { - 0 -> { - origin.diffHeight = -1 - right.diffHeight = 1 - } - - -1 -> { - origin.diffHeight = 0 - right.diffHeight = 0 - } - - -2 -> { - origin.diffHeight = 1 - right.diffHeight = 0 - } - } - } - - -1 -> { - when (right.diffHeight) { - 0 -> { - origin.diffHeight = 0 - right.diffHeight = 1 - } - - -1 -> { - origin.diffHeight = 1 - right.diffHeight = 1 - } - - 1 -> { - origin.diffHeight = 0 - right.diffHeight = 2 - } - } - } - } - - if (origin == root) { - root = right - } - return right - } -} diff --git a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/RBTree.kt b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/RBTree.kt deleted file mode 100644 index 2580c31..0000000 --- a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/RBTree.kt +++ /dev/null @@ -1,292 +0,0 @@ -package bstrees.implementations - -import bstrees.templates.BalanceBSTreeTemplate - -class RBTree, V> : BalanceBSTreeTemplate>() { - override fun set(key: K, value: V): V? { - val (currentVert, returnResult) = unbalancedSet(key, value) - balanceTreeAfterInsert(currentVert) - return returnResult - } - - private val red = RBVertex.Color.RED - private val black = RBVertex.Color.BLACK - - private fun rotateRight(vertex: RBVertex?) { - val parent = vertex?.parent - val leftChild = vertex?.left - vertex?.left = leftChild?.right - if (leftChild?.right != null) { - leftChild.right?.parent = vertex - } - leftChild?.right = vertex - vertex?.parent = leftChild - if (parent == null) { - root = leftChild - } else if (parent.left == vertex) { - parent.left = leftChild - } else if (parent.right == vertex) { - parent.right = leftChild - } - if (leftChild != null) { - leftChild.parent = parent - } - } - - private fun rotateLeft(vertex: RBVertex?) { - val parent = vertex?.parent - val rightChild = vertex?.right - vertex?.right = rightChild?.left - if (rightChild?.left != null) { - rightChild.left?.parent = vertex - } - rightChild?.left = vertex - vertex?.parent = rightChild - if (parent == null) { - root = rightChild - } else if (parent.left == vertex) { - parent.left = rightChild - } else if (parent.right == vertex) { - parent.right = rightChild - } - if (rightChild != null) { - rightChild.parent = parent - } - } - - private fun unbalancedSet(key: K, value: V): Pair, V?> { - if (root == null) { - val newVertex = RBVertex(key, value) - root = newVertex - size += 1 - return Pair(newVertex, null) - } - var currentVertex = root ?: throw IllegalStateException() - while (true) { - val result = currentVertex.key.compareTo(key) - if (result > 0) { - if (currentVertex.left == null) { - val newVertex = RBVertex(key, value) - newVertex.color = RBVertex.Color.RED - currentVertex.left = newVertex - newVertex.parent = currentVertex - size += 1 - return Pair(newVertex, null) - } - currentVertex = currentVertex.left ?: throw IllegalStateException() - } else if (result < 0) { - if (currentVertex.right == null) { - val newVertex = RBVertex(key, value) - newVertex.color = RBVertex.Color.RED - currentVertex.right = newVertex - newVertex.parent = currentVertex - size += 1 - return Pair(newVertex, null) - } - currentVertex = currentVertex.right ?: throw IllegalStateException() - } else { - val oldValue = currentVertex.value - currentVertex.value = value - return Pair(currentVertex, oldValue) - } - } - } - - private fun balanceTreeAfterInsert(vertex: RBVertex) { - var parent = vertex.parent - if (parent == null) { - vertex.color = black - return - } - if (parent.color == black) { - return - } - val grandparent = parent.parent - - if (grandparent == null) { - parent.color = black - return - } - - val uncle = getVertexUncle(parent) - if (uncle != null && uncle.color == red) { - parent.color = black - grandparent.color = red - uncle.color = black - balanceTreeAfterInsert(grandparent) - } else if (parent == grandparent.left) { - if (vertex == parent.right) { - rotateLeft(parent) - parent = vertex - } - rotateRight(grandparent) - parent.color = black - grandparent.color = red - } else { - if (vertex == parent.left) { - rotateRight(parent) - parent = vertex - } - rotateLeft(grandparent) - parent.color = black - grandparent.color = red - } - } - - override fun remove(key: K): V? { - var vertex = root - while (vertex != null && vertex.key != key) { - if (key < vertex.key) { - vertex = vertex.left - } else { - vertex = vertex.right - } - } - if (vertex == null) { - return null - } - val replacedVertex: RBVertex? - val deletedVertexColor: RBVertex.Color - if (vertex.left == null || vertex.right == null) { - replacedVertex = deleteNullChild(vertex) - deletedVertexColor = vertex.color - } else { - val minVertex = findMin(vertex.right!!) - minVertex.color = vertex.color - minVertex.left = vertex.left - minVertex.right = vertex.right - replaceChild(vertex.parent, vertex, minVertex) - replacedVertex = deleteNullChild(minVertex) - deletedVertexColor = minVertex.color - } - - if (deletedVertexColor == RBVertex.Color.BLACK) { - balanceTreeAfterDelete(replacedVertex) - if (replacedVertex?.nullType == true) { - replaceChild(replacedVertex.parent, replacedVertex, null) - } - } - return replacedVertex?.value - } - - private fun balanceTreeAfterDelete(vertex: RBVertex?) { - if (vertex == root) { - vertex?.color = RBVertex.Color.BLACK - return - } - var brother = getBrother(vertex) - - if (brother?.color === RBVertex.Color.RED) { - manageRedBrother(vertex, brother) - brother = getBrother(vertex) - } - if (brother?.left?.color == RBVertex.Color.BLACK && brother.right?.color == RBVertex.Color.BLACK) { - brother.color = RBVertex.Color.RED - if (vertex?.parent?.color == RBVertex.Color.RED) { - vertex.parent?.color = RBVertex.Color.BLACK - } else { - balanceTreeAfterDelete(vertex?.parent) - } - } else { - manageBlackRedOne(vertex, brother) - } - } - - private fun getBrother(vertex: RBVertex?): RBVertex? { - val parent = vertex?.parent - return if (vertex == parent?.left) { - parent?.right - } else if (vertex == parent?.right) { - parent?.left - } else { - throw IllegalStateException() - } - } - - private fun manageBlackRedOne(vertex: RBVertex?, argBrother: RBVertex?) { - var brother = argBrother - if (vertex == vertex?.parent?.left && brother?.right?.color == black) { - brother.left?.color = black - brother.color = red - rotateRight(brother) - brother = vertex?.parent?.right - } else if (vertex != vertex?.parent?.left && brother?.left?.color == black) { - brother.right?.color = black - brother.color = red - rotateLeft(brother) - brother = vertex?.parent?.left - } - brother?.color = vertex?.parent!!.color - vertex.parent?.color = black - if (vertex == vertex.parent?.left) { - brother?.right?.color = black - rotateLeft(vertex.parent) - } else { - brother?.left?.color = black - rotateRight(vertex.parent) - } - } - - private fun manageRedBrother(vertex: RBVertex?, brother: RBVertex) { - brother.color = RBVertex.Color.BLACK - vertex?.parent?.color = RBVertex.Color.RED - if (vertex === vertex?.parent?.left) { - rotateLeft(vertex?.parent) - } else { - rotateRight(vertex?.parent) - } - } - - private fun replaceChild(parent: RBVertex?, oldChild: RBVertex, newChild: RBVertex?) { - if (parent == null) { - root = newChild - } else if (parent.left === oldChild) { - parent.left = newChild - } else if (parent.right === oldChild) { - parent.right = newChild - } else { - throw IllegalStateException() - } - if (newChild != null) { - newChild.parent = parent - } - } - - private fun deleteNullChild(vertex: RBVertex): RBVertex? { - if (vertex.left != null) { - replaceChild(vertex.parent, vertex, vertex.left) - return vertex.left - } else if (vertex.right != null) { - replaceChild(vertex.parent, vertex, vertex.right) - return vertex.right - } else { - var newChild: RBVertex? = RBVertex(vertex.key, vertex.value) - if (vertex.color == RBVertex.Color.BLACK) { - newChild?.nullType = true - } else { - newChild = null - } - replaceChild(vertex.parent, vertex, newChild) - return newChild - } - } - - private fun findMin(argVertex: RBVertex): RBVertex { - var vertex = argVertex - while (vertex.left != null) { - vertex = vertex.left!! - } - return vertex - } - - private fun getVertexUncle(parent: RBVertex): RBVertex? { - val grandparent = parent.parent - return if (grandparent?.left == parent) { - grandparent.right - } else if (grandparent?.right == parent) { - grandparent.left - } else { - throw IllegalStateException("Grandparent/Parent dependency mistake") - } - } -} diff --git a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt deleted file mode 100644 index eae8bf1..0000000 --- a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/SimpleTree.kt +++ /dev/null @@ -1,77 +0,0 @@ -package bstrees.implementations - -import bstrees.templates.BSTreeTemplate - -class SimpleTree, V> : BSTreeTemplate>() { - override fun remove(key: K): V? { - val vertex = vertByKey(key) ?: return null - val parent = vertex.parent - val oldValue = vertex.value - if (vertex.left == null && vertex.right == null) { - when { - parent == null -> root = null - parent.left == vertex -> parent.left = null - else -> parent.right = null - } - } else if (vertex.right == null) { - vertex.left?.let { - vertex.key = it.key - vertex.value = it.value - vertex.left = null - } - } else { - val successor = minVertex(vertex.right) - val successorParent = successor?.parent - successor?.let { - vertex.key = successor.key - vertex.value = successor.value - } - when { - successorParent?.left == successor -> successorParent?.left = null - else -> vertex.right = null - } - } - --size - return oldValue - } - - override operator fun set( - key: K, - value: V, - ): V? { - if (root == null) { - val vertex = SimpleVertex(key, value) - root = vertex - size += 1 - return null - } - - var current = root ?: throw IllegalStateException("Can't be null, there was a check above") - while (true) { - val result = current.key.compareTo(key) - if (result < 0) { - if (current.left == null) { - val newVertex = SimpleVertex(key, value) - current.left = newVertex - newVertex.parent = current - size += 1 - return null - } - current = current.left ?: throw IllegalStateException("Case when cur.left is null is processed above") - } else if (result > 0) { - if (current.right == null) { - val newVertex = SimpleVertex(key, value) - current.right = newVertex - newVertex.parent = current - size += 1 - return null - } - current = current.right ?: throw IllegalStateException("Case when cur.right is null is processed above") - } else { - val oldValue = current.value - current.value = value - return null - } - } - } -} diff --git a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/Vertices.kt b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/Vertices.kt deleted file mode 100644 index 542ef83..0000000 --- a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/implementations/Vertices.kt +++ /dev/null @@ -1,25 +0,0 @@ -package bstrees.implementations - -import bstrees.templates.VertexTemplate - -class SimpleVertex, V>(key: K, value: V) : VertexTemplate>(key, value) - -class AVLVertex, V>(key: K, value: V) : VertexTemplate>(key, value) { - var diffHeight: Int = 0 - internal set(value) { - if (value !in -2..2) { - throw IllegalArgumentException("difference of heights can't be out of [-2,2]") - } - field = value - } -} - -class RBVertex, V>(key: K, value: V) : VertexTemplate>(key, value) { - var color: Color = Color.BLACK - var nullType = true - - enum class Color { - BLACK, - RED, - } -} diff --git a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt deleted file mode 100644 index 9361017..0000000 --- a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/BSTreeTemplate.kt +++ /dev/null @@ -1,155 +0,0 @@ -package bstrees.templates - -import java.util.Stack - -abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate> { - var root: Vertex_t? = null - protected set - var size: Int = 0 - protected set(value) { - if (value >= 0) { - field = value - } else { - throw IllegalArgumentException("Tree size cannot be a negative number") - } - } - - /** - * Associates the specified [value] with the specified [key] in the tree. - * - * @return the previous value associated with the key, or `null` if the key was not present in the tree. - */ - public abstract operator fun set(key: K, value: V): V? - - /** - * Associates the specified value with the specified key if this key is not in the tree. - * @return [true] if this key is not in the tree, otherwise [false] - */ - public fun setIfAbsent(key: K, value: V): Boolean { - if (get(key) == null) { - set(key, value) - return true - } - return false - } - - /** - * Returns the value corresponding to the given [key], or `null` if such a key is not present in the tree. - */ - public operator fun get(key: K): V? { - return vertByKey(key)?.value - } - - /** - * Returns the value corresponding to the given [key], or [defaultValue] if such a key is not present in the map. - */ - public fun getOrDefault(key: K, defaultValue: Any): Any { - return get(key) ?: defaultValue - } - - /** - * Returns the value for the given [key] if the value is present and not `null`. - * Otherwise, calls the [set] function, - * set [defaultValue] into the tree under the given key and returns the call result. - */ - public fun getOrSet(key: K, defaultValue: V): V? { - return get(key) ?: set(key, defaultValue) - } - - /** - * Removes the specified key and its corresponding value from the tree. - * - * @return the previous value associated with the key, or `null` if the key was not present in the map. - */ - public abstract fun remove(key: K): V? - - public operator fun iterator(): TreeIterator { - return TreeIterator() - } - - inner class TreeIterator : Iterator> { - var cur = root - val stack = Stack() - - override fun next(): Pair { - while (hasNext()) { - if (cur != null) { - cur?.let { - stack.push(it) - cur = it.left - } - } else { - val returnVert = stack.pop() - cur = returnVert.right - return returnVert.toPair() - } - } - throw IndexOutOfBoundsException() - } - - override fun hasNext(): Boolean { - return stack.isNotEmpty() or (cur != null) - } - } - - /** - * Returns Pair by minimum key in the tree. If tree is empty then returns null - */ - public fun min(): Pair? { - return minVertex(root)?.toPair() - } - - protected fun minVertex(vertex: Vertex_t?): Vertex_t? { - var cur = vertex - while (cur?.left != null) { - cur = cur.left - } - return cur - } - - /** - * Returns Pair by maximum key in the tree. If tree is empty then returns null - */ - public fun max(): Pair? { - return maxVert(root)?.toPair() - } - - private fun maxVert(vertex: Vertex_t?): Vertex_t? { - var cur = vertex - while (cur?.right != null) { - cur = cur.right - } - return cur - } - - protected fun vertByKey(key: K): Vertex_t? { - var cur = root - while (cur != null) { - if (key < cur.key) { - cur = cur.left - } else if (key > cur.key) { - cur = cur.right - } else if (key == cur.key) { - break - } - } - return cur - } - - public fun isEmpty(): Boolean { - return size == 0 - } - - public fun isNotEmpty(): Boolean { - return size != 0 - } - - public fun containsKey(key: K): Boolean { - return get(key) != null - } - - public fun clear() { - size = 0 - root = null - } -} diff --git a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt deleted file mode 100644 index 1c2cb99..0000000 --- a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/BalanceBSTreeTemplate.kt +++ /dev/null @@ -1,4 +0,0 @@ -package bstrees.templates - -abstract class BalanceBSTreeTemplate, V, Vertex_t : VertexTemplate> : - BSTreeTemplate() diff --git a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt b/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt deleted file mode 100644 index 8c0fcb0..0000000 --- a/megalinter-reports/updated_sources/lib/src/main/kotlin/bstrees/templates/VertexTemplate.kt +++ /dev/null @@ -1,15 +0,0 @@ -package bstrees.templates - -abstract class VertexTemplate, V, Vertex_t : VertexTemplate>(val key: K, var value: V) { - var parent: Vertex_t? = null - var left: Vertex_t? = null - var right: Vertex_t? = null - - operator fun compareTo(other: VertexTemplate): Int { - return key.compareTo(other.key) - } - - fun toPair(): Pair { - return Pair(key, value) - } -} diff --git a/megalinter-reports/updated_sources/lib/src/test/kotlin/trees/AVLTreeTest.kt b/megalinter-reports/updated_sources/lib/src/test/kotlin/trees/AVLTreeTest.kt deleted file mode 100644 index 9f2ec3a..0000000 --- a/megalinter-reports/updated_sources/lib/src/test/kotlin/trees/AVLTreeTest.kt +++ /dev/null @@ -1,439 +0,0 @@ -/* - * This Kotlin source file was generated by the Gradle 'init' task. - */ -package trees - -import bstrees.implementations.AVLTree -import bstrees.implementations.AVLVertex -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import kotlin.test.assertContentEquals -import kotlin.test.assertEquals - -class AVLTreeTest { - private lateinit var avlTree: AVLTree - - /** - * Traverse all vertices of the tree and asserts that their diffHeights are - * equal to real height difference of the subtrees. - * @return height of the subtree with the root at the specified [vertex] - */ - fun checkTreeInvariant(vertex: AVLVertex<*, *>?): Int { - if (vertex == null) return 0 - - val leftSubtreeHeight = checkTreeInvariant(vertex.left) - val rightSubtreeHeight = checkTreeInvariant(vertex.right) - val difference = leftSubtreeHeight - rightSubtreeHeight - assertTrue( - difference in -1..1, - "Height difference of subtrees must be in [-1,1]", - ) - assertEquals( - difference, - vertex.diffHeight, - "Property diffHeights must match real Height difference of subtrees (key = ${vertex.key})", - ) - return maxOf(checkTreeInvariant(vertex.left), checkTreeInvariant(vertex.right)) + 1 - } - - @BeforeEach - fun setup() { - avlTree = AVLTree() - } - - @Test - fun `simple array test`() { - val array = intArrayOf(0, 1, 2, 3, 4) - for (i in array) { - avlTree[i] = -i - } - val expectedGet: Array = Array(5, { i -> -i }) - val actualGet: Array = Array(5, { i -> avlTree.get(i) }) - assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") - val expectedSize = 5 - val actualSize = avlTree.size - assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") - checkTreeInvariant(avlTree.root) - } - - @Test - fun `size of avl tree with duplicate keys`() { - for (i in 1..10) { - avlTree[i] = i + 30 - } - for (i in 6..10) { - avlTree[i] = 0 - } - - val expectedSize = 10 - val actualSize = avlTree.size - assertEquals( - expectedSize, - actualSize, - "Size of the tree must not change after overwriting an existing key", - ) - checkTreeInvariant(avlTree.root) - } - - @Test - fun `set keys twice`() { - for (i in 1..10) { - avlTree[i] = 30 + i - } - for (i in 1..10) { - avlTree[i] = 0 - } - - val expectedSize = 10 - val actualSize = avlTree.size - assertEquals( - expectedSize, - actualSize, - "Size of the tree must not change after overwriting an existing key", - ) - checkTreeInvariant(avlTree.root) - } - - @Test - fun `simple remove`() { - avlTree[0] = 5 - - val expectedResult = 5 - val actualResult = avlTree.remove(0) - val expectedSize = 0 - val actualSize = avlTree.size - - assertEquals( - expectedResult, - actualResult, - "Remove must return removed value", - ) - assertEquals( - expectedSize, - actualSize, - "Size of the tree must decrease after removing the existing key", - ) - } - - @Test - fun `remove root of left subtree with existing left vertex`() { - val keys = intArrayOf(0, -1, 1, -2) - for (key in keys) avlTree[key] = key - avlTree.remove(-1) - - val expectedResult = arrayOf(0, null, 1, -2) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Tree must save all other vertices after remove vertex with existing left vertex", - ) - checkTreeInvariant(avlTree.root) - } - - @Test - fun `remove root of right subtree with existing left vertex`() { - val keys = intArrayOf(0, -1, 2, 1) - for (key in keys) avlTree[key] = key - avlTree.remove(2) - - val expectedResult = arrayOf(0, -1, null, 1) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Tree must save all other vertices after remove root of right subtree with existing left vertex", - ) - checkTreeInvariant(avlTree.root) - } - - @Test - fun `remove with right subtree of height 1`() { - val keys = intArrayOf(0, -1, 3, 1, 2) - for (key in keys) avlTree[key] = key - avlTree.remove(3) - - val expectedResult = arrayOf(0, -1, null, 1, 2) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Tree must save all other vertices after remove vertex with right subtree of height 1", - ) - checkTreeInvariant(avlTree.root) - } - - @Test - fun `remove with right subtree of height more than 1`() { - val keys = intArrayOf(0, -1, 3, -2, 1, 6, 4, 7) - for (key in keys) avlTree[key] = key - avlTree.remove(3) - - val expectedResult = arrayOf(0, -1, null, -2, 1, 6, 4, 7) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Tree must save all other vertices after remove vertex with right subtree of height >1", - ) - checkTreeInvariant(avlTree.root) - avlTree[5] = 5 - checkTreeInvariant(avlTree.root) - } - - @Test - fun `remove with double rotate`() { - val keys = intArrayOf(5, 0, 7, -1, 2, 6, 9, -2, 1, 3, 8, 4) - for (key in keys) avlTree[key] = key - avlTree.remove(7) - - val expectedResult = arrayOf(5, 0, null, -1, 2, 6, 9, -2, 1, 3, 8, 4) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Tree must save all other vertices after remove that creates unbalance situation", - ) - checkTreeInvariant(avlTree.root) - } - - @Test - fun `remove root with double rotate`() { - val keys = intArrayOf(4, 1, 6, 0, 3, 5, 2) - for (key in keys) avlTree[key] = key - avlTree.remove(4) - - assertTrue(avlTree.root != null) - val expectedResult = arrayOf(null, 1, 6, 0, 3, 5, 2) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Tree must save all other vertices after root remove", - ) - checkTreeInvariant(avlTree.root) - } - - @Test - fun `remove a non-existent key`() { - avlTree[0] = 15 - avlTree.remove(0) - - val expectedResult = null - val actualResult = avlTree.remove(0) - assertEquals( - expectedResult, - actualResult, - "Remove a non-existent key must return null", - ) - } - - @Test - fun `simple iteration`() { - val keys = intArrayOf(1, 7, 4, 9, 2, -44, 3) - val values = intArrayOf(19, 14, 31, 17, 12, -34, 0) - for (i in 0.. = arrayOf(-34, 19, 12, 0, 31, 14, 17) - val iterator = avlTree.iterator() - val actualResult: Array = Array(7, { iterator.next().second }) - assertContentEquals(expectedResult, actualResult, "Iterator must return vertices in keys order") - checkTreeInvariant(avlTree.root) - } - - @Test - fun `rotate left, right diffHeight = -1`() { - val keys = intArrayOf(0, -1, 2, 1, 3, 4) - for (key in keys) avlTree[key] = key - - val expectedResult = Array(keys.size, { i -> keys[i] }) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Get must return corresponding values after left rotate ( right.diffHeight = -1)", - ) - checkTreeInvariant(avlTree.root) - -// 0 0 2 -// / \ / \ / \ -// -1 2 -1 2 0 3 -// / \ --> / \ --> / \ \ -// 1 3 1 3 -1 1 4 -// \ -// 4 - } - - @Test - fun `rotate left, right diffHeiht = 0`() { - val keys = intArrayOf(0, -1, 4, 2, 6, -2, 1, 3, 5, 7) - for (key in keys) avlTree[key] = key - avlTree.remove(-2) - - val expectedResult = arrayOf(0, -1, 4, 2, 6, null, 1, 3, 5, 7) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Get must return corresponding values after left rotate (right.diffHeight = 0)", - ) - checkTreeInvariant(avlTree.root) -// 0 0 4 -// / \ / \ / \ -// -1 4 -1 4 0 6 -// / / \ --> / \ --> / \ / \ -// -2 2 6 2 6 -1 2 5 7 -// / \ / \ / \ / \ / \ -// 1 3 5 7 1 3 5 7 1 3 - } - - @Test - fun `rotate right, left diffHeight = 1`() { - val keys = intArrayOf(0, 1, -1, -3, -2, -4) - for (key in keys) avlTree[key] = key - - val expectedResult = Array(keys.size, { i -> keys[i] }) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Get must return corresponding values after right rotate (left.diffHeight = 1)", - ) - checkTreeInvariant(avlTree.root) - -// 0 0 -1 -// / \ / \ / \ -// -1 1 -1 1 -3 0 -// / \ --> / \ --> / / \ -// -3 -2 -3 -2 -4 -2 1 -// / -// -4 - } - - @Test - fun `rotate right, left diffHeight = 0`() { - val keys = intArrayOf(7, 3, 8, 9, 1, 5, 0, 2, 4, 6) - for (key in keys) avlTree[key] = key - avlTree.remove(9) - - val expectedResult = arrayOf(7, 3, 8, null, 1, 5, 0, 2, 4, 6) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Get must return corresponding values after right rotate (left.diffHeight = 0)", - ) - checkTreeInvariant(avlTree.root) - -// 7 7 3 -// / \ / \ / \ -// 3 8 3 8 1 7 -// / \ \ --> / \ --> / \ / \ -// 1 5 9 1 5 0 2 5 8 -// / \ / \ / \ / \ / \ -// 0 2 4 6 0 2 4 6 4 6 - } - - @Test - fun `rotate right-left, right diffHeight is 1, right-left diffHeight is 1`() { - val keys = intArrayOf(1, 0, 4, 3, 5, 2) - for (key in keys) avlTree[key] = key - - val expectedResult = Array(keys.size, { i -> keys[i] }) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Get must return corresponding values after right-left rotate with right.left.diffHeight = 1", - ) - checkTreeInvariant(avlTree.root) - -// 1 1 3 -// / \ / \ / \ -// 0 4 0 3 1 4 -// / \ --> / \ --> / \ \ -// 3 5 2 4 0 2 5 -// / \ -// 2 5 - } - - @Test - fun `rotate right-left, right diffHeight is 1, right-left diffHeight is 0`() { - val keys = intArrayOf(2, 1, 6, 0, 4, 7, 3, 5) - for (key in keys) avlTree[key] = key - avlTree.remove(0) - - val expectedResult: Array = arrayOf(2, 1, 6, null, 4, 7, 3, 5) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Get must return corresponding values after right-left rotate with right.left.diffHeight = 0", - ) - checkTreeInvariant(avlTree.root) - } - - @Test - fun `rotate right-left, right diffHeight is 1, right-left diffHeight is -1`() { - val keys = intArrayOf(1, 0, 4, 2, 5, 3) - for (key in keys) avlTree[key] = key - - val expectedResult = Array(keys.size, { i -> keys[i] }) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Get must return corresponding values after right-left rotate with right.left.diffHeight = -1", - ) - checkTreeInvariant(avlTree.root) - } - - @Test - fun `rotate left-right, left diffHeight is -1, left-right diffHeight is -1`() { - val keys = intArrayOf(4, 1, 5, 0, 2, 3) - for (key in keys) avlTree[key] = key - - val expectedResult = Array(keys.size, { i -> keys[i] }) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Get must return corresponding values after left-right rotate with left.right.diffHeight = -1", - ) - checkTreeInvariant(avlTree.root) - } - - @Test - fun `rotate left-right, left diffHeight is -1, left-right diffHeight is 0`() { - val keys = intArrayOf(5, 1, 6, 0, 3, 7, 2, 4) - for (key in keys) avlTree[key] = key - avlTree.remove(7) - - val expectedResult = arrayOf(5, 1, 6, 0, 3, null, 2, 4) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Get must return corresponding values after left-right rotate with left.right.diffHeight = 0", - ) - checkTreeInvariant(avlTree.root) - } - - @Test - fun `rotate left-right, left diffHeight is -1, left-right diffHeight is 1`() { - val keys = intArrayOf(4, 1, 5, 0, 3, 2) - for (key in keys) avlTree[key] = key - - val expectedResult = Array(keys.size, { i -> keys[i] }) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) - assertContentEquals( - expectedResult, - actualResult, - "Get must return corresponding values after left-right rotate with left.right.diffHeight = 1", - ) - checkTreeInvariant(avlTree.root) - } -} diff --git a/megalinter-reports/updated_sources/lib/src/test/kotlin/trees/rbtest/RBTest.kt b/megalinter-reports/updated_sources/lib/src/test/kotlin/trees/rbtest/RBTest.kt deleted file mode 100644 index 064a221..0000000 --- a/megalinter-reports/updated_sources/lib/src/test/kotlin/trees/rbtest/RBTest.kt +++ /dev/null @@ -1,113 +0,0 @@ -package trees.avlTest - -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import trees.implementations.RBTree -import kotlin.test.assertContentEquals -import kotlin.test.assertEquals - -class RBTest { - private lateinit var rbTree: RBTree - - @BeforeEach - fun setup() { - rbTree = RBTree() - } - - @Test - fun `simple array test`() { - val array = intArrayOf(0, 1, 2, 3, 4) - for (i in array) { - rbTree[i] = i - } - val expectedGet: Array = Array(5, { i -> i }) - val actualGet: Array = Array(5, { i -> rbTree.get(i) }) - assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") - val expectedSize = 5 - val actualSize = rbTree.size - assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") - } - - @Test - fun `size of red black tree with duplicate keys`() { - for (i in 1..10) { - rbTree[i] = i + 30 - } - for (i in 6..10) { - rbTree[i] = 0 - } - - val expectedSize = 10 - val actualSize = rbTree.size - assertEquals( - expectedSize, - actualSize, - "Size of the tree must not change after overwriting an existing key", - ) - } - - @Test - fun `simple array set test`() { - for (i in 0..19) { - rbTree.set(i, i) - } - - for (i in 0..19) { - val expectedContains = rbTree.get(i) - assertEquals(expectedContains, i, "Added and not removed element does not contain in the tree") - } - - val expectedGet: Array = Array(20, { i -> i }) - val actualGet: Array = Array(20, { i -> rbTree.get(i) }) - assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") - val expectedSize = 20 - val actualSize = rbTree.size - assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") - } - - @Test - fun `simple array set remove test`() { - for (i in 0..19) { - rbTree.set(i, i) - } - for (i in 10..19) { - rbTree.remove(i) - } - for (i in 10..19) { - val expectedNotContains = rbTree.get(i) - assertEquals(expectedNotContains, null, "Removed element contains in the tree") - } - for (i in 0..9) { - val expectedContains = rbTree.get(i) - assertEquals(expectedContains, i, "Added and not removed element does not contain in the tree") - } - - val expectedGet: Array = Array(10, { i -> i }) - val actualGet: Array = Array(10, { i -> rbTree.get(i) }) - assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") - val expectedSize = 10 - val actualSize = rbTree.size - assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") - } - - @Test - fun `adding and removing all elements test`() { - for (i in 0..19) { - rbTree.set(i, i) - } - for (i in 0..19) { - rbTree.remove(i) - } - for (i in 0..19) { - val expectedNotContains = rbTree.get(i) - assertEquals(expectedNotContains, null, "Removed element contains in the tree") - } - - val expectedGet: Array = emptyArray() - val actualGet: Array = Array(rbTree.size, { i -> rbTree.get(i) }) - assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") - val expectedSize = 0 - val actualSize = rbTree.size - assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") - } -} diff --git a/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log b/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log deleted file mode 100644 index d229ece..0000000 --- a/megalinter-reports/updated_sources/megalinter-reports/linters_logs/SUCCESS-KOTLIN_KTLINT.log +++ /dev/null @@ -1,6 +0,0 @@ -Results of ktlint linter (version 1.2.1) -See documentation on https://megalinter.io/7.10.0/descriptors/kotlin_ktlint/ ------------------------------------------------ - -✅ [SUCCESS] lib/src/main/kotlin/trees/implementations/RBTree.kt -✅ [SUCCESS] lib/src/test/kotlin/trees/rbtest/RBTest.kt - FIXED diff --git a/megalinter-reports/updated_sources/megalinter-reports/megalinter.log b/megalinter-reports/updated_sources/megalinter-reports/megalinter.log deleted file mode 100644 index 06fa11f..0000000 --- a/megalinter-reports/updated_sources/megalinter-reports/megalinter.log +++ /dev/null @@ -1,51 +0,0 @@ ----------------------------------------------------------------------------------------------------- ------------------------------------- MegaLinter, by OX Security ------------------------------------ ----------------------------------------------------------------------------------------------------- - - Image Creation Date: 2024-03-10T20:25:08Z - - Image Revision: a7a0163b6c8ff7474a283d99a706e27483ddd80f - - Image Version: v7.10.0 ----------------------------------------------------------------------------------------------------- -The MegaLinter documentation can be found at: - - https://megalinter.io/7.10.0 ----------------------------------------------------------------------------------------------------- -::group::MegaLinter initialization (expand for details) -MegaLinter will analyze workspace [/github/workspace] -GITHUB_REPOSITORY: spbu-coding-2023/trees-8 -GITHUB_REF: refs/pull/18/merge -GITHUB_RUN_ID: 8500266858 - - -CLOJURE_CLJSTYLE has been temporary disabled in MegaLinter, please use a previous MegaLinter version or wait for the next one ! -MARKDOWN_REMARK_LINT has been temporary disabled in MegaLinter, please use a previous MegaLinter version or wait for the next one ! -Skipped linters: ACTION_ACTIONLINT, ANSIBLE_ANSIBLE_LINT, ARM_ARM_TTK, BASH_EXEC, BASH_SHELLCHECK, BASH_SHFMT, BICEP_BICEP_LINTER, CLOJURE_CLJSTYLE, CLOJURE_CLJ_KONDO, CLOUDFORMATION_CFN_LINT, COFFEE_COFFEELINT, COPYPASTE_JSCPD, CPP_CLANG_FORMAT, CPP_CPPLINT, CSHARP_CSHARPIER, CSHARP_DOTNET_FORMAT, CSHARP_ROSLYNATOR, CSS_SCSS_LINT, CSS_STYLELINT, C_CLANG_FORMAT, C_CPPLINT, DART_DARTANALYZER, DOCKERFILE_HADOLINT, EDITORCONFIG_EDITORCONFIG_CHECKER, ENV_DOTENV_LINTER, GHERKIN_GHERKIN_LINT, GO_GOLANGCI_LINT, GO_REVIVE, GRAPHQL_GRAPHQL_SCHEMA_LINTER, GROOVY_NPM_GROOVY_LINT, HTML_DJLINT, HTML_HTMLHINT, JAVASCRIPT_ES, JAVASCRIPT_PRETTIER, JAVASCRIPT_STANDARD, JAVA_CHECKSTYLE, JAVA_PMD, JSON_ESLINT_PLUGIN_JSONC, JSON_JSONLINT, JSON_NPM_PACKAGE_JSON_LINT, JSON_PRETTIER, JSON_V8R, JSX_ESLINT, KUBERNETES_HELM, KUBERNETES_KUBECONFORM, KUBERNETES_KUBESCAPE, LATEX_CHKTEX, LUA_LUACHECK, MAKEFILE_CHECKMAKE, MARKDOWN_MARKDOWNLINT, MARKDOWN_MARKDOWN_LINK_CHECK, MARKDOWN_MARKDOWN_TABLE_FORMATTER, MARKDOWN_REMARK_LINT, OPENAPI_SPECTRAL, PERL_PERLCRITIC, PHP_PHPCS, PHP_PHPLINT, PHP_PHPSTAN, PHP_PSALM, POWERSHELL_POWERSHELL, POWERSHELL_POWERSHELL_FORMATTER, PROTOBUF_PROTOLINT, PUPPET_PUPPET_LINT, PYTHON_BANDIT, PYTHON_BLACK, PYTHON_FLAKE8, PYTHON_ISORT, PYTHON_MYPY, PYTHON_PYLINT, PYTHON_PYRIGHT, PYTHON_RUFF, RAKU_RAKU, REPOSITORY_CHECKOV, REPOSITORY_DEVSKIM, REPOSITORY_DUSTILOCK, REPOSITORY_GITLEAKS, REPOSITORY_GIT_DIFF, REPOSITORY_GRYPE, REPOSITORY_KICS, REPOSITORY_SECRETLINT, REPOSITORY_SEMGREP, REPOSITORY_SYFT, REPOSITORY_TRIVY, REPOSITORY_TRIVY_SBOM, REPOSITORY_TRUFFLEHOG, RST_RSTCHECK, RST_RSTFMT, RST_RST_LINT, RUBY_RUBOCOP, RUST_CLIPPY, R_LINTR, SALESFORCE_LIGHTNING_FLOW_SCANNER, SALESFORCE_SFDX_SCANNER_APEX, SALESFORCE_SFDX_SCANNER_AURA, SALESFORCE_SFDX_SCANNER_LWC, SCALA_SCALAFIX, SNAKEMAKE_LINT, SNAKEMAKE_SNAKEFMT, SPELL_CSPELL, SPELL_LYCHEE, SPELL_PROSELINT, SPELL_VALE, SQL_SQLFLUFF, SQL_SQL_LINT, SQL_TSQLLINT, SWIFT_SWIFTLINT, TEKTON_TEKTON_LINT, TERRAFORM_TERRAFORM_FMT, TERRAFORM_TERRAGRUNT, TERRAFORM_TERRASCAN, TERRAFORM_TFLINT, TSX_ESLINT, TYPESCRIPT_ES, TYPESCRIPT_PRETTIER, TYPESCRIPT_STANDARD, VBDOTNET_DOTNET_FORMAT, XML_XMLLINT, YAML_PRETTIER, YAML_V8R, YAML_YAMLLINT -To receive reports as email, please set variable EMAIL_REPORTER_EMAIL -::endgroup:: -::group::MegaLinter now collects the files to analyse (expand for details) -Listing updated files in [/github/workspace] using git diff. -Modified files: -lib/src/main/kotlin/trees/implementations/RBTree.kt -lib/src/test/kotlin/trees/rbtest/RBTest.kt -megalinter-reports/megalinter.log -- File extensions: .kt, .kts -- Excluding .gitignored files [0]: -Kept [2] files on [3] found files - -+----MATCHING LINTERS-+----------+----------------+------------+ -| Descriptor | Linter | Criteria | Matching files | Format/Fix | -+------------+--------+----------+----------------+------------+ -| KOTLIN | ktlint | .kt|.kts | 2 | yes | -+------------+--------+----------+----------------+------------+ -::endgroup:: -::group::✅ Linted [KOTLIN] files with [ktlint] successfully - (2.95s) (expand for details) -- Using [ktlint v1.2.1] https://megalinter.io/7.10.0/descriptors/kotlin_ktlint -- MegaLinter key: [KOTLIN_KTLINT] -- Rules config: identified by [ktlint] -- Number of files analyzed: [2] -::endgroup:: - -+----SUMMARY-+--------+------+-------+-------+--------+--------------+ -| Descriptor | Linter | Mode | Files | Fixed | Errors | Elapsed time | -+------------+--------+------+-------+-------+--------+--------------+ -| ✅ KOTLIN | ktlint | file | 2 | 1 | 0 | 2.95s | -+------------+--------+------+-------+-------+--------+--------------+ - From e2b73695a8f6f3366f40fa11c1786aa90c830d4e Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Mon, 8 Apr 2024 20:11:47 +0300 Subject: [PATCH 096/108] refactor: rename tests on Simple Tree --- .../test/kotlin/trees/bstest/BSTreeTest.kt | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt b/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt index a489a5b..8f29970 100644 --- a/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt +++ b/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt @@ -1,6 +1,5 @@ package trees.bstest -import trees.implementations.SimpleTree import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test @@ -16,13 +15,13 @@ class BSTreeTest { } @Test - fun testCheckEmptyTree() { + fun `check empty tree`() { assertNull(simpleTree.getRootSimple()) assertEquals(0, simpleTree.size) } @Test - fun testInsertAndFind() { + fun `insert and find`() { val array = intArrayOf(0, 1, 2, 3, 4, 5, 6, 7) for (i in array) { simpleTree[i] = -i @@ -36,7 +35,7 @@ class BSTreeTest { } @Test - fun testSimpleDelete() { + fun `simple delete`() { val array = intArrayOf(0, 1, 2, 3, 4, 5, 6) for (i in array) { simpleTree[i] = i @@ -52,7 +51,7 @@ class BSTreeTest { } @Test - fun testSizeWithDuplicateKeys() { + fun `size with duplicate keys`() { for (i in 1..10) { simpleTree[i] = i + 30 } @@ -66,7 +65,7 @@ class BSTreeTest { } @Test - fun testTwiceKeys() { + fun `twice keys`() { for (i in 1..10) { simpleTree[i] = 30 + i } @@ -80,7 +79,7 @@ class BSTreeTest { } @Test - fun testRemoveNonExistentKey() { + fun `remove non existent key`() { simpleTree[0] = 15 val actualResult = simpleTree.remove(3) val expectedResult = null @@ -88,7 +87,7 @@ class BSTreeTest { } @Test - fun testRemoveRootOfLeftSubtree() { + fun `remove root of left subtree`() { val keys = intArrayOf(0, -1, 1, -2) for (i in keys) { simpleTree[i] = i @@ -101,7 +100,7 @@ class BSTreeTest { } @Test - fun testRemoveRootOfRightSubtree() { + fun `remove root of right subtree`() { val keys = intArrayOf(0, -1, 2, 1) for (i in keys) { simpleTree[i] = i @@ -114,7 +113,7 @@ class BSTreeTest { } @Test - fun testRemoveRootWith2Children() { + fun `remove root with 2 children`() { val keys = intArrayOf(0, -1, 2, 1, 3) for (key in keys) { simpleTree[key] = key @@ -127,7 +126,7 @@ class BSTreeTest { } @Test - fun testRemoveRightRootWithoutChildren() { + fun `remove right root without children`() { val keys = intArrayOf(0, -1, 2) for (key in keys) { simpleTree[key] = key From 09af4ec12120e33dffe526d71bef42e9c4a1353a Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Fri, 12 Apr 2024 07:36:21 +0300 Subject: [PATCH 097/108] Refactor: remove redundat function reference argument -rename fabricVertex to createVertex -remove redundant argument in createVertex --- lib/src/main/kotlin/trees/implementations/AvlTree.kt | 4 ++-- lib/src/main/kotlin/trees/implementations/RBTree.kt | 4 ++-- .../main/kotlin/trees/implementations/SimpleTree.kt | 4 ++-- lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt | 10 +++++----- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/src/main/kotlin/trees/implementations/AvlTree.kt b/lib/src/main/kotlin/trees/implementations/AvlTree.kt index d0a2b49..bb8b3e0 100644 --- a/lib/src/main/kotlin/trees/implementations/AvlTree.kt +++ b/lib/src/main/kotlin/trees/implementations/AvlTree.kt @@ -4,7 +4,7 @@ import trees.templates.BalanceBSTreeTemplate open class AvlTree, V> : BalanceBSTreeTemplate>() { override operator fun set(key: K, value: V): V? { - val (currentVert, oldValue) = setWithoutBalance(key, value, ::fabricVertex) + val (currentVert, oldValue) = setWithoutBalance(key, value) if (oldValue == null) { size += 1 balanceAfterSet(currentVert) @@ -12,7 +12,7 @@ open class AvlTree, V> : BalanceBSTreeTemplate { + override fun createVertex(key: K, value: V): AVLVertex { return AVLVertex(key, value) } diff --git a/lib/src/main/kotlin/trees/implementations/RBTree.kt b/lib/src/main/kotlin/trees/implementations/RBTree.kt index deb6b5a..cf39863 100644 --- a/lib/src/main/kotlin/trees/implementations/RBTree.kt +++ b/lib/src/main/kotlin/trees/implementations/RBTree.kt @@ -4,12 +4,12 @@ import trees.templates.BalanceBSTreeTemplate open class RBTree, V> : BalanceBSTreeTemplate>() { - override fun fabricVertex(key: K, value: V): RBVertex { + override fun createVertex(key: K, value: V): RBVertex { return RBVertex(key, value) } override fun set(key: K, value: V): V? { - val (currentVert, oldValue) = setWithoutBalance(key, value, ::fabricVertex) + val (currentVert, oldValue) = setWithoutBalance(key, value) if (oldValue == null) { size += 1 } diff --git a/lib/src/main/kotlin/trees/implementations/SimpleTree.kt b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt index f20a0fd..3a4333b 100644 --- a/lib/src/main/kotlin/trees/implementations/SimpleTree.kt +++ b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt @@ -4,7 +4,7 @@ import trees.templates.BSTreeTemplate open class SimpleTree, V> : BSTreeTemplate>() { - override fun fabricVertex(key: K, value: V): SimpleVertex { + override fun createVertex(key: K, value: V): SimpleVertex { return SimpleVertex(key, value) } @@ -37,7 +37,7 @@ open class SimpleTree, V> : BSTreeTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate Vertex_t): Pair { + protected fun setWithoutBalance(key: K, value: V): Pair { if (root == null) { - val newVertex = fabric(key, value) + val newVertex = createVertex(key, value) root = newVertex return Pair(newVertex, null) } @@ -40,7 +40,7 @@ abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate, V, Vertex_t : VertexTemplate 0) { if (cur.right == null) { - val newVertex = fabric(key, value) + val newVertex = createVertex(key, value) cur.right = newVertex newVertex.parent = cur return Pair(newVertex, null) From c04846cf9dc18e3bddad82d8b3f84ab2bb5772c6 Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Fri, 12 Apr 2024 07:53:07 +0300 Subject: [PATCH 098/108] Refactor: remove redundant XTestTrees, change root visibility -remove XTestTrees classes from test package -change root visibility to internal --- .../kotlin/trees/implementations/AvlTree.kt | 2 +- .../kotlin/trees/implementations/RBTree.kt | 2 +- .../trees/implementations/SimpleTree.kt | 2 +- .../kotlin/trees/templates/BSTreeTemplate.kt | 2 +- .../kotlin/trees/avltest/AvlGeneralTest.kt | 32 +++++++++---------- .../kotlin/trees/avltest/AvlSpecificTest.kt | 30 ++++++++--------- .../test/kotlin/trees/avltest/AvlTestTree.kt | 10 ------ .../test/kotlin/trees/bstest/BSTreeTest.kt | 7 ++-- .../kotlin/trees/bstest/SimpleTestTree.kt | 10 ------ lib/src/test/kotlin/trees/rbtest/RBTest.kt | 6 ++-- .../test/kotlin/trees/rbtest/RBTestTree.kt | 12 ------- 11 files changed, 42 insertions(+), 73 deletions(-) delete mode 100644 lib/src/test/kotlin/trees/avltest/AvlTestTree.kt delete mode 100644 lib/src/test/kotlin/trees/bstest/SimpleTestTree.kt delete mode 100644 lib/src/test/kotlin/trees/rbtest/RBTestTree.kt diff --git a/lib/src/main/kotlin/trees/implementations/AvlTree.kt b/lib/src/main/kotlin/trees/implementations/AvlTree.kt index bb8b3e0..5aa8f3c 100644 --- a/lib/src/main/kotlin/trees/implementations/AvlTree.kt +++ b/lib/src/main/kotlin/trees/implementations/AvlTree.kt @@ -2,7 +2,7 @@ package trees.implementations import trees.templates.BalanceBSTreeTemplate -open class AvlTree, V> : BalanceBSTreeTemplate>() { +class AvlTree, V> : BalanceBSTreeTemplate>() { override operator fun set(key: K, value: V): V? { val (currentVert, oldValue) = setWithoutBalance(key, value) if (oldValue == null) { diff --git a/lib/src/main/kotlin/trees/implementations/RBTree.kt b/lib/src/main/kotlin/trees/implementations/RBTree.kt index cf39863..ed17a5f 100644 --- a/lib/src/main/kotlin/trees/implementations/RBTree.kt +++ b/lib/src/main/kotlin/trees/implementations/RBTree.kt @@ -2,7 +2,7 @@ package trees.implementations import trees.templates.BalanceBSTreeTemplate -open class RBTree, V> : BalanceBSTreeTemplate>() { +class RBTree, V> : BalanceBSTreeTemplate>() { override fun createVertex(key: K, value: V): RBVertex { return RBVertex(key, value) diff --git a/lib/src/main/kotlin/trees/implementations/SimpleTree.kt b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt index 3a4333b..20533fc 100644 --- a/lib/src/main/kotlin/trees/implementations/SimpleTree.kt +++ b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt @@ -2,7 +2,7 @@ package trees.implementations import trees.templates.BSTreeTemplate -open class SimpleTree, V> : BSTreeTemplate>() { +class SimpleTree, V> : BSTreeTemplate>() { override fun createVertex(key: K, value: V): SimpleVertex { return SimpleVertex(key, value) diff --git a/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt b/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt index 46621bd..acf3592 100644 --- a/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt +++ b/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt @@ -3,7 +3,7 @@ package trees.templates import java.util.Stack abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate> { - protected var root: Vertex_t? = null + internal var root: Vertex_t? = null var size: Int = 0 protected set(value) { if (value >= 0) { diff --git a/lib/src/test/kotlin/trees/avltest/AvlGeneralTest.kt b/lib/src/test/kotlin/trees/avltest/AvlGeneralTest.kt index e8619d4..0b0dbbd 100644 --- a/lib/src/test/kotlin/trees/avltest/AvlGeneralTest.kt +++ b/lib/src/test/kotlin/trees/avltest/AvlGeneralTest.kt @@ -10,11 +10,11 @@ import trees.avltest.AvlSpecificTest.Companion.checkTreeInvariant import kotlin.test.assertIs class AvlGeneralTest { - private lateinit var avlTree: AvlTestTree + private lateinit var avlTree: AvlTree @BeforeEach fun setup() { - avlTree = AvlTestTree() + avlTree = AvlTree() } @Test @@ -29,7 +29,7 @@ class AvlGeneralTest { val expectedSize = 5 val actualSize = avlTree.size assertEquals(expectedSize, actualSize, "Size the tree must correspond to the number key-value pairs") - checkTreeInvariant(avlTree.getRootAvl()) + checkTreeInvariant(avlTree.root) } @Test @@ -48,7 +48,7 @@ class AvlGeneralTest { actualSize, "Size of the tree must not change after overwriting an existing key", ) - checkTreeInvariant(avlTree.getRootAvl()) + checkTreeInvariant(avlTree.root) } @Test @@ -67,7 +67,7 @@ class AvlGeneralTest { actualSize, "Size of the tree must not change after overwriting an existing key", ) - checkTreeInvariant(avlTree.getRootAvl()) + checkTreeInvariant(avlTree.root) } @Test @@ -131,7 +131,7 @@ class AvlGeneralTest { actualResult, "Tree must save all other vertices after remove vertex with existing left vertex", ) - checkTreeInvariant(avlTree.getRootAvl()) + checkTreeInvariant(avlTree.root) } @Test @@ -147,7 +147,7 @@ class AvlGeneralTest { actualResult, "Tree must save all other vertices after remove root of right subtree with existing left vertex", ) - checkTreeInvariant(avlTree.getRootAvl()) + checkTreeInvariant(avlTree.root) } @Test @@ -163,7 +163,7 @@ class AvlGeneralTest { actualResult, "Tree must save all other vertices after remove vertex with right subtree of height 1", ) - checkTreeInvariant(avlTree.getRootAvl()) + checkTreeInvariant(avlTree.root) } @Test @@ -179,9 +179,9 @@ class AvlGeneralTest { actualResult, "Tree must save all other vertices after remove vertex with right subtree of height >1", ) - checkTreeInvariant(avlTree.getRootAvl()) + checkTreeInvariant(avlTree.root) avlTree[5] = 5 - checkTreeInvariant(avlTree.getRootAvl()) + checkTreeInvariant(avlTree.root) } @Test @@ -196,7 +196,7 @@ class AvlGeneralTest { val iterator = avlTree.iterator() val actualResult: Array = Array(7, { iterator.next().second }) assertContentEquals(expectedResult, actualResult, "Iterator must return vertices in keys order") - checkTreeInvariant(avlTree.getRootAvl()) + checkTreeInvariant(avlTree.root) } @Test @@ -223,7 +223,7 @@ class AvlGeneralTest { avlTree.clear() assertEquals(avlTree.size, 0, "Size of the tree must be 0 after clear") - assertEquals(avlTree.getRootAvl(), null, "Root of the tree must be null after clear") + assertEquals(avlTree.root, null, "Root of the tree must be null after clear") } @Test @@ -284,7 +284,7 @@ class AvlGeneralTest { val actualResult = avlTree.max() assertEquals(expectedResult, actualResult, "Max must return Pairs by max key in the tree") - checkTreeInvariant(avlTree.getRootAvl()) + checkTreeInvariant(avlTree.root) } @@ -298,7 +298,7 @@ class AvlGeneralTest { val actualResult = avlTree.max() assertEquals(expectedResult, actualResult, "Max must return Pair by max key in the tree") - checkTreeInvariant(avlTree.getRootAvl()) + checkTreeInvariant(avlTree.root) } @Test @@ -310,7 +310,7 @@ class AvlGeneralTest { val expectedResult = Pair(-46, -46) val actualResult = avlTree.min() assertEquals(expectedResult, actualResult, "Min must return Pair by min key in the tree") - checkTreeInvariant(avlTree.getRootAvl()) + checkTreeInvariant(avlTree.root) } @@ -325,7 +325,7 @@ class AvlGeneralTest { val actualResult = avlTree.min() assertEquals(expectedResult, actualResult, "Min must return Pair by min key in the tree") - checkTreeInvariant(avlTree.getRootAvl()) + checkTreeInvariant(avlTree.root) } @Test diff --git a/lib/src/test/kotlin/trees/avltest/AvlSpecificTest.kt b/lib/src/test/kotlin/trees/avltest/AvlSpecificTest.kt index 7153079..7408070 100644 --- a/lib/src/test/kotlin/trees/avltest/AvlSpecificTest.kt +++ b/lib/src/test/kotlin/trees/avltest/AvlSpecificTest.kt @@ -9,7 +9,7 @@ import kotlin.test.assertContentEquals import kotlin.test.assertEquals class AvlSpecificTest { - private lateinit var avlTree: AvlTestTree + private lateinit var avlTree: AvlTree companion object { /** @@ -38,7 +38,7 @@ class AvlSpecificTest { @BeforeEach fun setup() { - avlTree = AvlTestTree() + avlTree = AvlTree() } @Test @@ -54,7 +54,7 @@ class AvlSpecificTest { actualResult, "Tree must save all other vertices after remove that creates unbalance situation", ) - checkTreeInvariant(avlTree.getRootAvl()) + checkTreeInvariant(avlTree.root) } @Test @@ -63,7 +63,7 @@ class AvlSpecificTest { for (key in keys) avlTree[key] = key avlTree.remove(4) - assertTrue(avlTree.getRootAvl() != null) + assertTrue(avlTree.root != null) val expectedResult = arrayOf(null, 1, 6, 0, 3, 5, 2) val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) assertContentEquals( @@ -71,7 +71,7 @@ class AvlSpecificTest { actualResult, "Tree must save all other vertices after root remove", ) - checkTreeInvariant(avlTree.getRootAvl()) + checkTreeInvariant(avlTree.root) } @Test @@ -86,7 +86,7 @@ class AvlSpecificTest { actualResult, "Get must return corresponding values after left rotate ( right.diffHeight = -1)", ) - checkTreeInvariant(avlTree.getRootAvl()) + checkTreeInvariant(avlTree.root) // 0 0 2 // / \ / \ / \ @@ -110,7 +110,7 @@ class AvlSpecificTest { actualResult, "Get must return corresponding values after left rotate (right.diffHeight = 0)", ) - checkTreeInvariant(avlTree.getRootAvl()) + checkTreeInvariant(avlTree.root) // 0 0 4 // / \ / \ / \ // -1 4 -1 4 0 6 @@ -132,7 +132,7 @@ class AvlSpecificTest { actualResult, "Get must return corresponding values after right rotate (left.diffHeight = 1)", ) - checkTreeInvariant(avlTree.getRootAvl()) + checkTreeInvariant(avlTree.root) // 0 0 -1 // / \ / \ / \ @@ -156,7 +156,7 @@ class AvlSpecificTest { actualResult, "Get must return corresponding values after right rotate (left.diffHeight = 0)", ) - checkTreeInvariant(avlTree.getRootAvl()) + checkTreeInvariant(avlTree.root) // 7 7 3 // / \ / \ / \ @@ -179,7 +179,7 @@ class AvlSpecificTest { actualResult, "Get must return corresponding values after right-left rotate with right.left.diffHeight = 1", ) - checkTreeInvariant(avlTree.getRootAvl()) + checkTreeInvariant(avlTree.root) // 1 1 3 // / \ / \ / \ @@ -203,7 +203,7 @@ class AvlSpecificTest { actualResult, "Get must return corresponding values after right-left rotate with right.left.diffHeight = 0", ) - checkTreeInvariant(avlTree.getRootAvl()) + checkTreeInvariant(avlTree.root) } @Test @@ -218,7 +218,7 @@ class AvlSpecificTest { actualResult, "Get must return corresponding values after right-left rotate with right.left.diffHeight = -1", ) - checkTreeInvariant(avlTree.getRootAvl()) + checkTreeInvariant(avlTree.root) } @Test @@ -233,7 +233,7 @@ class AvlSpecificTest { actualResult, "Get must return corresponding values after left-right rotate with left.right.diffHeight = -1", ) - checkTreeInvariant(avlTree.getRootAvl()) + checkTreeInvariant(avlTree.root) } @Test @@ -249,7 +249,7 @@ class AvlSpecificTest { actualResult, "Get must return corresponding values after left-right rotate with left.right.diffHeight = 0", ) - checkTreeInvariant(avlTree.getRootAvl()) + checkTreeInvariant(avlTree.root) } @Test @@ -264,6 +264,6 @@ class AvlSpecificTest { actualResult, "Get must return corresponding values after left-right rotate with left.right.diffHeight = 1", ) - checkTreeInvariant(avlTree.getRootAvl()) + checkTreeInvariant(avlTree.root) } } diff --git a/lib/src/test/kotlin/trees/avltest/AvlTestTree.kt b/lib/src/test/kotlin/trees/avltest/AvlTestTree.kt deleted file mode 100644 index 272035f..0000000 --- a/lib/src/test/kotlin/trees/avltest/AvlTestTree.kt +++ /dev/null @@ -1,10 +0,0 @@ -package trees.avltest - -import trees.implementations.AVLVertex -import trees.implementations.AvlTree - -class AvlTestTree, V> : AvlTree() { - fun getRootAvl(): AVLVertex? { - return this.root - } -} \ No newline at end of file diff --git a/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt b/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt index 8f29970..e4b5da5 100644 --- a/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt +++ b/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt @@ -3,20 +3,21 @@ package trees.bstest import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test +import trees.implementations.SimpleTree import kotlin.test.assertContentEquals import kotlin.test.assertEquals class BSTreeTest { - private lateinit var simpleTree: SimpleTestTree + private lateinit var simpleTree: SimpleTree @BeforeEach fun setup() { - simpleTree = SimpleTestTree() + simpleTree = SimpleTree() } @Test fun `check empty tree`() { - assertNull(simpleTree.getRootSimple()) + assertNull(simpleTree.root) assertEquals(0, simpleTree.size) } diff --git a/lib/src/test/kotlin/trees/bstest/SimpleTestTree.kt b/lib/src/test/kotlin/trees/bstest/SimpleTestTree.kt deleted file mode 100644 index e9828f0..0000000 --- a/lib/src/test/kotlin/trees/bstest/SimpleTestTree.kt +++ /dev/null @@ -1,10 +0,0 @@ -package trees.bstest - -import trees.implementations.SimpleTree -import trees.implementations.SimpleVertex - -class SimpleTestTree, V> : SimpleTree() { - fun getRootSimple(): SimpleVertex? { - return this.root - } -} \ No newline at end of file diff --git a/lib/src/test/kotlin/trees/rbtest/RBTest.kt b/lib/src/test/kotlin/trees/rbtest/RBTest.kt index b7913d9..80d7549 100644 --- a/lib/src/test/kotlin/trees/rbtest/RBTest.kt +++ b/lib/src/test/kotlin/trees/rbtest/RBTest.kt @@ -8,11 +8,11 @@ import kotlin.test.assertContentEquals import kotlin.test.assertEquals class RBTest { - private lateinit var rbTree: RBTestTree + private lateinit var rbTree: RBTree @BeforeEach fun setup() { - rbTree = RBTestTree() + rbTree = RBTree() } @Test @@ -178,7 +178,7 @@ class RBTest { val keys = intArrayOf(4, 1, 6, 0, 3, 5, 2) for (key in keys) rbTree[key] = key rbTree.remove(4) - Assertions.assertTrue(rbTree.getRootRB() != null) + Assertions.assertTrue(rbTree.root != null) val expectedResult = arrayOf(null, 1, 6, 0, 3, 5, 2) val actualResult = Array(keys.size) { i -> rbTree[keys[i]] } assertContentEquals( diff --git a/lib/src/test/kotlin/trees/rbtest/RBTestTree.kt b/lib/src/test/kotlin/trees/rbtest/RBTestTree.kt deleted file mode 100644 index a88a28e..0000000 --- a/lib/src/test/kotlin/trees/rbtest/RBTestTree.kt +++ /dev/null @@ -1,12 +0,0 @@ -package trees.rbtest - -import trees.implementations.AVLVertex -import trees.implementations.AvlTree -import trees.implementations.RBTree -import trees.implementations.RBVertex - -class RBTestTree, V> : RBTree() { - fun getRootRB(): RBVertex? { - return this.root - } -} \ No newline at end of file From 8ecbf95c83a908294969dacd5323b21d20fb1af4 Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Fri, 12 Apr 2024 08:04:46 +0300 Subject: [PATCH 099/108] Refactor: fix warnings --- .../kotlin/trees/implementations/AvlTree.kt | 3 +- .../kotlin/trees/implementations/RBTree.kt | 10 +++--- .../kotlin/trees/templates/BSTreeTemplate.kt | 2 +- .../kotlin/trees/avltest/AvlGeneralTest.kt | 14 ++++---- .../kotlin/trees/avltest/AvlSpecificTest.kt | 36 +++++++++---------- 5 files changed, 31 insertions(+), 34 deletions(-) diff --git a/lib/src/main/kotlin/trees/implementations/AvlTree.kt b/lib/src/main/kotlin/trees/implementations/AvlTree.kt index 5aa8f3c..82b86b0 100644 --- a/lib/src/main/kotlin/trees/implementations/AvlTree.kt +++ b/lib/src/main/kotlin/trees/implementations/AvlTree.kt @@ -22,9 +22,8 @@ class AvlTree, V> : BalanceBSTreeTemplate) { var cur = vertex - var prevKey = cur.key while (cur.parent != null) { - prevKey = cur.key + val prevKey = cur.key cur = cur.parent ?: throw IllegalStateException("Parent can't be null due to while condition") if (prevKey == cur.left?.key) { cur.diffHeight += 1 diff --git a/lib/src/main/kotlin/trees/implementations/RBTree.kt b/lib/src/main/kotlin/trees/implementations/RBTree.kt index ed17a5f..7cf2423 100644 --- a/lib/src/main/kotlin/trees/implementations/RBTree.kt +++ b/lib/src/main/kotlin/trees/implementations/RBTree.kt @@ -157,12 +157,10 @@ class RBTree, V> : BalanceBSTreeTemplate> private fun getBrother(vertex: RBVertex?): RBVertex? { val parent = vertex?.parent - return if (vertex == parent?.left) { - parent?.right - } else if (vertex == parent?.right) { - parent?.left - } else { - throw IllegalStateException() + return when (vertex) { + parent?.left -> parent?.right + parent?.right -> parent?.left + else -> throw IllegalStateException() } } diff --git a/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt b/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt index acf3592..8135856 100644 --- a/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt +++ b/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt @@ -20,7 +20,7 @@ abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate = Array(5, { i -> -i }) - val actualGet: Array = Array(5, { i -> avlTree[i] }) + val expectedGet: Array = Array(5) { i -> -i } + val actualGet: Array = Array(5) { i -> avlTree[i] } assertContentEquals(expectedGet, actualGet, "Get method must return the value associated with the key") val expectedSize = 5 val actualSize = avlTree.size @@ -125,7 +125,7 @@ class AvlGeneralTest { avlTree.remove(-1) val expectedResult = arrayOf(0, null, 1, -2) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val actualResult = Array(keys.size) { i -> avlTree[keys[i]] } assertContentEquals( expectedResult, actualResult, @@ -141,7 +141,7 @@ class AvlGeneralTest { avlTree.remove(2) val expectedResult = arrayOf(0, -1, null, 1) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val actualResult = Array(keys.size) { i -> avlTree[keys[i]] } assertContentEquals( expectedResult, actualResult, @@ -157,7 +157,7 @@ class AvlGeneralTest { avlTree.remove(3) val expectedResult = arrayOf(0, -1, null, 1, 2) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val actualResult = Array(keys.size) { i -> avlTree[keys[i]] } assertContentEquals( expectedResult, actualResult, @@ -173,7 +173,7 @@ class AvlGeneralTest { avlTree.remove(3) val expectedResult = arrayOf(0, -1, null, -2, 1, 6, 4, 7) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val actualResult = Array(keys.size) { i -> avlTree[keys[i]] } assertContentEquals( expectedResult, actualResult, @@ -194,7 +194,7 @@ class AvlGeneralTest { val expectedResult: Array = arrayOf(-34, 19, 12, 0, 31, 14, 17) val iterator = avlTree.iterator() - val actualResult: Array = Array(7, { iterator.next().second }) + val actualResult: Array = Array(7) { iterator.next().second } assertContentEquals(expectedResult, actualResult, "Iterator must return vertices in keys order") checkTreeInvariant(avlTree.root) } diff --git a/lib/src/test/kotlin/trees/avltest/AvlSpecificTest.kt b/lib/src/test/kotlin/trees/avltest/AvlSpecificTest.kt index 7408070..46330c0 100644 --- a/lib/src/test/kotlin/trees/avltest/AvlSpecificTest.kt +++ b/lib/src/test/kotlin/trees/avltest/AvlSpecificTest.kt @@ -48,7 +48,7 @@ class AvlSpecificTest { avlTree.remove(7) val expectedResult = arrayOf(5, 0, null, -1, 2, 6, 9, -2, 1, 3, 8, 4) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val actualResult = Array(keys.size) { i -> avlTree[keys[i]] } assertContentEquals( expectedResult, actualResult, @@ -65,7 +65,7 @@ class AvlSpecificTest { assertTrue(avlTree.root != null) val expectedResult = arrayOf(null, 1, 6, 0, 3, 5, 2) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val actualResult = Array(keys.size) { i -> avlTree[keys[i]] } assertContentEquals( expectedResult, actualResult, @@ -79,8 +79,8 @@ class AvlSpecificTest { val keys = intArrayOf(0, -1, 2, 1, 3, 4) for (key in keys) avlTree[key] = key - val expectedResult = Array(keys.size, { i -> keys[i] }) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val expectedResult = Array(keys.size) { i -> keys[i] } + val actualResult = Array(keys.size) { i -> avlTree[keys[i]] } assertContentEquals( expectedResult, actualResult, @@ -104,7 +104,7 @@ class AvlSpecificTest { avlTree.remove(-2) val expectedResult = arrayOf(0, -1, 4, 2, 6, null, 1, 3, 5, 7) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val actualResult = Array(keys.size) { i -> avlTree[keys[i]] } assertContentEquals( expectedResult, actualResult, @@ -125,8 +125,8 @@ class AvlSpecificTest { val keys = intArrayOf(0, 1, -1, -3, -2, -4) for (key in keys) avlTree[key] = key - val expectedResult = Array(keys.size, { i -> keys[i] }) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val expectedResult = Array(keys.size) { i -> keys[i] } + val actualResult = Array(keys.size) { i -> avlTree[keys[i]] } assertContentEquals( expectedResult, actualResult, @@ -150,7 +150,7 @@ class AvlSpecificTest { avlTree.remove(9) val expectedResult = arrayOf(7, 3, 8, null, 1, 5, 0, 2, 4, 6) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val actualResult = Array(keys.size) { i -> avlTree[keys[i]] } assertContentEquals( expectedResult, actualResult, @@ -172,8 +172,8 @@ class AvlSpecificTest { val keys = intArrayOf(1, 0, 4, 3, 5, 2) for (key in keys) avlTree[key] = key - val expectedResult = Array(keys.size, { i -> keys[i] }) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val expectedResult = Array(keys.size) { i -> keys[i] } + val actualResult = Array(keys.size) { i -> avlTree[keys[i]] } assertContentEquals( expectedResult, actualResult, @@ -197,7 +197,7 @@ class AvlSpecificTest { avlTree.remove(0) val expectedResult: Array = arrayOf(2, 1, 6, null, 4, 7, 3, 5) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val actualResult = Array(keys.size) { i -> avlTree[keys[i]] } assertContentEquals( expectedResult, actualResult, @@ -211,8 +211,8 @@ class AvlSpecificTest { val keys = intArrayOf(1, 0, 4, 2, 5, 3) for (key in keys) avlTree[key] = key - val expectedResult = Array(keys.size, { i -> keys[i] }) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val expectedResult = Array(keys.size) { i -> keys[i] } + val actualResult = Array(keys.size) { i -> avlTree[keys[i]] } assertContentEquals( expectedResult, actualResult, @@ -226,8 +226,8 @@ class AvlSpecificTest { val keys = intArrayOf(4, 1, 5, 0, 2, 3) for (key in keys) avlTree[key] = key - val expectedResult = Array(keys.size, { i -> keys[i] }) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val expectedResult = Array(keys.size) { i -> keys[i] } + val actualResult = Array(keys.size) { i -> avlTree[keys[i]] } assertContentEquals( expectedResult, actualResult, @@ -243,7 +243,7 @@ class AvlSpecificTest { avlTree.remove(7) val expectedResult = arrayOf(5, 1, 6, 0, 3, null, 2, 4) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val actualResult = Array(keys.size) { i -> avlTree[keys[i]] } assertContentEquals( expectedResult, actualResult, @@ -257,8 +257,8 @@ class AvlSpecificTest { val keys = intArrayOf(4, 1, 5, 0, 3, 2) for (key in keys) avlTree[key] = key - val expectedResult = Array(keys.size, { i -> keys[i] }) - val actualResult = Array(keys.size, { i -> avlTree[keys[i]] }) + val expectedResult = Array(keys.size) { i -> keys[i] } + val actualResult = Array(keys.size) { i -> avlTree[keys[i]] } assertContentEquals( expectedResult, actualResult, From b4bc994171c36014a901cd40b3fa15923405da92 Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Fri, 12 Apr 2024 08:08:47 +0300 Subject: [PATCH 100/108] Refactor: rename template classes and package -remove template word from the class names -rename templates package to abstracts --- .../{templates/BSTreeTemplate.kt => abstracts/BSTree.kt} | 4 ++-- lib/src/main/kotlin/trees/abstracts/BalanceBSTree.kt | 4 ++++ .../{templates/VertexTemplate.kt => abstracts/Vertex.kt} | 6 +++--- lib/src/main/kotlin/trees/implementations/AvlTree.kt | 4 ++-- lib/src/main/kotlin/trees/implementations/RBTree.kt | 4 ++-- lib/src/main/kotlin/trees/implementations/SimpleTree.kt | 4 ++-- lib/src/main/kotlin/trees/implementations/Vertices.kt | 8 ++++---- .../main/kotlin/trees/templates/BalanceBSTreeTemplate.kt | 4 ---- 8 files changed, 19 insertions(+), 19 deletions(-) rename lib/src/main/kotlin/trees/{templates/BSTreeTemplate.kt => abstracts/BSTree.kt} (97%) create mode 100644 lib/src/main/kotlin/trees/abstracts/BalanceBSTree.kt rename lib/src/main/kotlin/trees/{templates/VertexTemplate.kt => abstracts/Vertex.kt} (63%) delete mode 100644 lib/src/main/kotlin/trees/templates/BalanceBSTreeTemplate.kt diff --git a/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt b/lib/src/main/kotlin/trees/abstracts/BSTree.kt similarity index 97% rename from lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt rename to lib/src/main/kotlin/trees/abstracts/BSTree.kt index 8135856..23f384f 100644 --- a/lib/src/main/kotlin/trees/templates/BSTreeTemplate.kt +++ b/lib/src/main/kotlin/trees/abstracts/BSTree.kt @@ -1,8 +1,8 @@ -package trees.templates +package trees.abstracts import java.util.Stack -abstract class BSTreeTemplate, V, Vertex_t : VertexTemplate> { +abstract class BSTree, V, Vertex_t : Vertex> { internal var root: Vertex_t? = null var size: Int = 0 protected set(value) { diff --git a/lib/src/main/kotlin/trees/abstracts/BalanceBSTree.kt b/lib/src/main/kotlin/trees/abstracts/BalanceBSTree.kt new file mode 100644 index 0000000..fcb7404 --- /dev/null +++ b/lib/src/main/kotlin/trees/abstracts/BalanceBSTree.kt @@ -0,0 +1,4 @@ +package trees.abstracts + +abstract class BalanceBSTree, V, Vertex_t : Vertex> : + BSTree() diff --git a/lib/src/main/kotlin/trees/templates/VertexTemplate.kt b/lib/src/main/kotlin/trees/abstracts/Vertex.kt similarity index 63% rename from lib/src/main/kotlin/trees/templates/VertexTemplate.kt rename to lib/src/main/kotlin/trees/abstracts/Vertex.kt index cbf7c0d..0417f41 100644 --- a/lib/src/main/kotlin/trees/templates/VertexTemplate.kt +++ b/lib/src/main/kotlin/trees/abstracts/Vertex.kt @@ -1,6 +1,6 @@ -package trees.templates +package trees.abstracts -abstract class VertexTemplate, V, Vertex_t : VertexTemplate>(key: K, value: V) { +abstract class Vertex, V, Vertex_t : Vertex>(key: K, value: V) { var key = key internal set var value = value @@ -12,7 +12,7 @@ abstract class VertexTemplate, V, Vertex_t : VertexTemplate): Int { + operator fun compareTo(other: Vertex): Int { return key.compareTo(other.key) } diff --git a/lib/src/main/kotlin/trees/implementations/AvlTree.kt b/lib/src/main/kotlin/trees/implementations/AvlTree.kt index 82b86b0..d8c1b97 100644 --- a/lib/src/main/kotlin/trees/implementations/AvlTree.kt +++ b/lib/src/main/kotlin/trees/implementations/AvlTree.kt @@ -1,8 +1,8 @@ package trees.implementations -import trees.templates.BalanceBSTreeTemplate +import trees.abstracts.BalanceBSTree -class AvlTree, V> : BalanceBSTreeTemplate>() { +class AvlTree, V> : BalanceBSTree>() { override operator fun set(key: K, value: V): V? { val (currentVert, oldValue) = setWithoutBalance(key, value) if (oldValue == null) { diff --git a/lib/src/main/kotlin/trees/implementations/RBTree.kt b/lib/src/main/kotlin/trees/implementations/RBTree.kt index 7cf2423..5ac1956 100644 --- a/lib/src/main/kotlin/trees/implementations/RBTree.kt +++ b/lib/src/main/kotlin/trees/implementations/RBTree.kt @@ -1,8 +1,8 @@ package trees.implementations -import trees.templates.BalanceBSTreeTemplate +import trees.abstracts.BalanceBSTree -class RBTree, V> : BalanceBSTreeTemplate>() { +class RBTree, V> : BalanceBSTree>() { override fun createVertex(key: K, value: V): RBVertex { return RBVertex(key, value) diff --git a/lib/src/main/kotlin/trees/implementations/SimpleTree.kt b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt index 20533fc..1e283c1 100644 --- a/lib/src/main/kotlin/trees/implementations/SimpleTree.kt +++ b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt @@ -1,8 +1,8 @@ package trees.implementations -import trees.templates.BSTreeTemplate +import trees.abstracts.BSTree -class SimpleTree, V> : BSTreeTemplate>() { +class SimpleTree, V> : BSTree>() { override fun createVertex(key: K, value: V): SimpleVertex { return SimpleVertex(key, value) diff --git a/lib/src/main/kotlin/trees/implementations/Vertices.kt b/lib/src/main/kotlin/trees/implementations/Vertices.kt index c79bcdf..e2bb48f 100644 --- a/lib/src/main/kotlin/trees/implementations/Vertices.kt +++ b/lib/src/main/kotlin/trees/implementations/Vertices.kt @@ -1,10 +1,10 @@ package trees.implementations -import trees.templates.VertexTemplate +import trees.abstracts.Vertex -class SimpleVertex, V>(key: K, value: V) : VertexTemplate>(key, value) +class SimpleVertex, V>(key: K, value: V) : Vertex>(key, value) -class AVLVertex, V>(key: K, value: V) : VertexTemplate>(key, value) { +class AVLVertex, V>(key: K, value: V) : Vertex>(key, value) { var diffHeight: Int = 0 internal set(value) { if (value !in -2..2) { @@ -14,7 +14,7 @@ class AVLVertex, V>(key: K, value: V) : VertexTemplate, V>(key: K, value: V) : VertexTemplate>(key, value) { +class RBVertex, V>(key: K, value: V) : Vertex>(key, value) { var color: Color = Color.RED var additionalType = false diff --git a/lib/src/main/kotlin/trees/templates/BalanceBSTreeTemplate.kt b/lib/src/main/kotlin/trees/templates/BalanceBSTreeTemplate.kt deleted file mode 100644 index 1380293..0000000 --- a/lib/src/main/kotlin/trees/templates/BalanceBSTreeTemplate.kt +++ /dev/null @@ -1,4 +0,0 @@ -package trees.templates - -abstract class BalanceBSTreeTemplate, V, Vertex_t : VertexTemplate> : - BSTreeTemplate() From 10c45ad620123dc9a071dafb951367c7c9db493d Mon Sep 17 00:00:00 2001 From: Ycyken Date: Fri, 12 Apr 2024 05:31:58 +0000 Subject: [PATCH 101/108] [MegaLinter] Apply linters fixes --- .../kotlin/trees/implementations/RBTree.kt | 3 - .../trees/implementations/SimpleTree.kt | 4 +- .../kotlin/trees/avltest/AvlGeneralTest.kt | 71 ++++++++++--------- .../kotlin/trees/avltest/AvlSpecificTest.kt | 4 +- .../test/kotlin/trees/bstest/BSTreeTest.kt | 19 ----- lib/src/test/kotlin/trees/rbtest/RBTest.kt | 1 - 6 files changed, 44 insertions(+), 58 deletions(-) diff --git a/lib/src/main/kotlin/trees/implementations/RBTree.kt b/lib/src/main/kotlin/trees/implementations/RBTree.kt index 5ac1956..c99a739 100644 --- a/lib/src/main/kotlin/trees/implementations/RBTree.kt +++ b/lib/src/main/kotlin/trees/implementations/RBTree.kt @@ -121,7 +121,6 @@ class RBTree, V> : BalanceBSTree>() { vertex.key = mVertex.key replacedVertex = deleteNullChild(mVertex) deletedVertexColor = mVertex.color - } if (deletedVertexColor == black) { @@ -172,7 +171,6 @@ class RBTree, V> : BalanceBSTree>() { brother.color = red rotateLeft(brother) brother = vertex?.parent?.right - } else if (!isParent && brother?.left?.color == black) { brother.right?.color = black brother.color = red @@ -229,7 +227,6 @@ class RBTree, V> : BalanceBSTree>() { } } - private fun getVertexUncle(parent: RBVertex): RBVertex? { val grandparent = parent.parent return if (grandparent?.left == parent) { diff --git a/lib/src/main/kotlin/trees/implementations/SimpleTree.kt b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt index 1e283c1..ea397fe 100644 --- a/lib/src/main/kotlin/trees/implementations/SimpleTree.kt +++ b/lib/src/main/kotlin/trees/implementations/SimpleTree.kt @@ -21,7 +21,9 @@ class SimpleTree, V> : BSTree>() { } else { val successor = if (vertex.right == null) { maxVertex(vertex.left) - } else minVertex(vertex.right) + } else { + minVertex(vertex.right) + } val successorParent = successor?.parent successor?.let { vertex.key = it.key diff --git a/lib/src/test/kotlin/trees/avltest/AvlGeneralTest.kt b/lib/src/test/kotlin/trees/avltest/AvlGeneralTest.kt index 9dfa936..4501ea3 100644 --- a/lib/src/test/kotlin/trees/avltest/AvlGeneralTest.kt +++ b/lib/src/test/kotlin/trees/avltest/AvlGeneralTest.kt @@ -3,14 +3,14 @@ package trees.avltest import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows +import trees.avltest.AvlSpecificTest.Companion.checkTreeInvariant import trees.implementations.AvlTree import kotlin.test.assertContentEquals import kotlin.test.assertEquals -import trees.avltest.AvlSpecificTest.Companion.checkTreeInvariant import kotlin.test.assertIs class AvlGeneralTest { - private lateinit var avlTree: AvlTree + private lateinit var avlTree: AvlTree @BeforeEach fun setup() { @@ -73,13 +73,15 @@ class AvlGeneralTest { @Test fun `set return`() { assertEquals( - avlTree.set(44, -37), null, - "Set must return null if set key was not present in the tree" + avlTree.set(44, -37), + null, + "Set must return null if set key was not present in the tree", ) assertEquals( - avlTree.set(44, 152), -37, - "Set must return previous value associated with the key" + avlTree.set(44, 152), + -37, + "Set must return previous value associated with the key", ) } @@ -206,11 +208,12 @@ class AvlGeneralTest { val iterator = avlTree.iterator() for (key in keys) { assertIs>( - iterator.next(), "iterator.next() must return Pair while all keys is not bypassed" + iterator.next(), + "iterator.next() must return Pair while all keys is not bypassed", ) } assertThrows( - "Iterator must throw IndexOutOfBondsException after next() if all keys is bypassed" + "Iterator must throw IndexOutOfBondsException after next() if all keys is bypassed", ) { iterator.next() } @@ -233,16 +236,18 @@ class AvlGeneralTest { for (key in keys) { assertEquals( - avlTree.containsKey(key), true, - "containsKey must return true for keys existing in the tree" + avlTree.containsKey(key), + true, + "containsKey must return true for keys existing in the tree", ) } avlTree.remove(-34) val keysNotInTheTree = intArrayOf(102, 57, -22, -34) for (key in keysNotInTheTree) { assertEquals( - avlTree.containsKey(key), false, - "containsKey must return false for keys not existing in the tree" + avlTree.containsKey(key), + false, + "containsKey must return false for keys not existing in the tree", ) } } @@ -259,7 +264,6 @@ class AvlGeneralTest { avlTree.clear() assertEquals(avlTree.isNotEmpty(), false, "isNotEmpty must return false if tree is empty") - } @Test @@ -285,7 +289,6 @@ class AvlGeneralTest { assertEquals(expectedResult, actualResult, "Max must return Pairs by max key in the tree") checkTreeInvariant(avlTree.root) - } @Test @@ -306,13 +309,10 @@ class AvlGeneralTest { val keys = intArrayOf(54, 88, 4332, -46, -2) for (key in keys) avlTree[key] = key - val expectedResult = Pair(-46, -46) val actualResult = avlTree.min() assertEquals(expectedResult, actualResult, "Min must return Pair by min key in the tree") checkTreeInvariant(avlTree.root) - - } @Test @@ -335,20 +335,23 @@ class AvlGeneralTest { val expectedResult = -48 val actualResult = avlTree.getOrSet(25, 90) assertEquals( - expectedResult, actualResult, - "getOrSet must return value corresponding to the specified key if it's presented in the tree" + expectedResult, + actualResult, + "getOrSet must return value corresponding to the specified key if it's presented in the tree", ) } @Test fun `getOrSet with non existing key`() { assertEquals( - avlTree.getOrSet(0, -10500), null, - "getOrSet must return null if key is not presented in the tree" + avlTree.getOrSet(0, -10500), + null, + "getOrSet must return null if key is not presented in the tree", ) assertEquals( - avlTree[0], -10500, - "getOrSet must set specified key-value if key was not presented in the tree" + avlTree[0], + -10500, + "getOrSet must set specified key-value if key was not presented in the tree", ) } @@ -359,8 +362,9 @@ class AvlGeneralTest { val expectedResult = 45 val actualResult = avlTree.getOrDefault(45, "Default") assertEquals( - expectedResult, actualResult, - "getOrDefault must return value corresponding to the specified key if it's presented in the tree" + expectedResult, + actualResult, + "getOrDefault must return value corresponding to the specified key if it's presented in the tree", ) } @@ -369,8 +373,9 @@ class AvlGeneralTest { val expectedResult = "Default" val actualResult = avlTree.getOrDefault(100, "Default") assertEquals( - expectedResult, actualResult, - "getOrDefault must return defaultValue if key is not presented in the tree" + expectedResult, + actualResult, + "getOrDefault must return defaultValue if key is not presented in the tree", ) } @@ -382,8 +387,9 @@ class AvlGeneralTest { val expectedResult = 520 val actualResult = avlTree[520] assertEquals( - expectedResult, actualResult, - "setIfAbsent must not change value if key is presented in the tree" + expectedResult, + actualResult, + "setIfAbsent must not change value if key is presented in the tree", ) } @@ -394,8 +400,9 @@ class AvlGeneralTest { val expectedResult = 250 val actualResult = avlTree[-100] assertEquals( - expectedResult, actualResult, - "setIfAbsent must set specified value under specified key if key was not presented in the tree" + expectedResult, + actualResult, + "setIfAbsent must set specified value under specified key if key was not presented in the tree", ) } -} \ No newline at end of file +} diff --git a/lib/src/test/kotlin/trees/avltest/AvlSpecificTest.kt b/lib/src/test/kotlin/trees/avltest/AvlSpecificTest.kt index 46330c0..04d592d 100644 --- a/lib/src/test/kotlin/trees/avltest/AvlSpecificTest.kt +++ b/lib/src/test/kotlin/trees/avltest/AvlSpecificTest.kt @@ -1,10 +1,10 @@ package trees.avltest -import trees.implementations.AvlTree -import trees.implementations.AVLVertex import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test +import trees.implementations.AVLVertex +import trees.implementations.AvlTree import kotlin.test.assertContentEquals import kotlin.test.assertEquals diff --git a/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt b/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt index e4b5da5..f8466fa 100644 --- a/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt +++ b/lib/src/test/kotlin/trees/bstest/BSTreeTest.kt @@ -139,22 +139,3 @@ class BSTreeTest { assertContentEquals(expectedResult, actualResult) } } - - - - - - - - - - - - - - - - - - - diff --git a/lib/src/test/kotlin/trees/rbtest/RBTest.kt b/lib/src/test/kotlin/trees/rbtest/RBTest.kt index 80d7549..ec695bf 100644 --- a/lib/src/test/kotlin/trees/rbtest/RBTest.kt +++ b/lib/src/test/kotlin/trees/rbtest/RBTest.kt @@ -107,7 +107,6 @@ class RBTest { @Test fun `not simple array set remove test`() { - for (i in 19 downTo 0) { rbTree[19 - i] = i } From 079373343edba3e85720064a02b44522270316c9 Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Fri, 12 Apr 2024 20:34:47 +0300 Subject: [PATCH 102/108] Chage: Revised CI after Revoy 1. The launch is removed simultaneously immediately on PUSH and PR 2. CITEST is now launched on different operating systems 3. An extra Build team has been removed --- .github/workflows/CITest.yml | 24 ++++++++++++++ .github/workflows/CI_Test.yml | 31 ------------------- .../workflows/{coverage.yml => Coverage.yml} | 4 --- .github/workflows/MegaLinter.yml | 1 - 4 files changed, 24 insertions(+), 36 deletions(-) create mode 100644 .github/workflows/CITest.yml delete mode 100644 .github/workflows/CI_Test.yml rename .github/workflows/{coverage.yml => Coverage.yml} (96%) diff --git a/.github/workflows/CITest.yml b/.github/workflows/CITest.yml new file mode 100644 index 0000000..264cf5e --- /dev/null +++ b/.github/workflows/CITest.yml @@ -0,0 +1,24 @@ +name: CITest + +on: + push: +jobs: + CITest: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + distribution: "oracle" + java-version: '17' + + - name: Build and Test + run: | + ./gradlew clean build + IF EXIST gradlew.bat (gradlew.bat build) \ No newline at end of file diff --git a/.github/workflows/CI_Test.yml b/.github/workflows/CI_Test.yml deleted file mode 100644 index f643467..0000000 --- a/.github/workflows/CI_Test.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: CI_Test - -on: - push: - pull_request: - branches: - - main - -jobs: - CI_Test: - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Set up JDK 17 - uses: actions/setup-java@v4 - with: - distribution: "oracle" - java-version: '17' - - - name: Grant execute permission for gradlew - run: chmod +x ./gradlew - - - name: Check code cleanliness - run: ./gradlew clean build - continue-on-error: true - - - name: Run tests - run: ./gradlew test diff --git a/.github/workflows/coverage.yml b/.github/workflows/Coverage.yml similarity index 96% rename from .github/workflows/coverage.yml rename to .github/workflows/Coverage.yml index d8cb6c9..140342b 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/Coverage.yml @@ -2,10 +2,6 @@ name: Coverage Test on: push: - pull_request: - branches: - - main - jobs: Coverage: runs-on: ubuntu-latest diff --git a/.github/workflows/MegaLinter.yml b/.github/workflows/MegaLinter.yml index 3767aa7..2788311 100644 --- a/.github/workflows/MegaLinter.yml +++ b/.github/workflows/MegaLinter.yml @@ -5,7 +5,6 @@ name: MegaLinter on: # Trigger mega-linter at every push. Action will also be visible from Pull Requests to main - push: # Comment this line to trigger action only on pull-requests (not recommended if you don't pay for GH Actions) pull_request: branches: [master, main] From 0a461f4f5d12d26a0730732048d60c4f9f36b0bc Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Fri, 12 Apr 2024 20:40:06 +0300 Subject: [PATCH 103/108] Change: Delete run on windows(feature on future) --- .github/workflows/CITest.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/CITest.yml b/.github/workflows/CITest.yml index 264cf5e..b789d56 100644 --- a/.github/workflows/CITest.yml +++ b/.github/workflows/CITest.yml @@ -7,7 +7,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-latest, macos-latest, windows-latest] + os: [ubuntu-latest, macos-latest] steps: - name: Checkout repository uses: actions/checkout@v4 @@ -18,7 +18,5 @@ jobs: distribution: "oracle" java-version: '17' - - name: Build and Test - run: | - ./gradlew clean build - IF EXIST gradlew.bat (gradlew.bat build) \ No newline at end of file + - name: Clean, Build and Test + run: ./gradlew clean build \ No newline at end of file From 6a138cd5677a5cb1cebe3bf155748ab568a471b0 Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Fri, 12 Apr 2024 20:55:50 +0300 Subject: [PATCH 104/108] Change: MegaLinter run only on push --- .github/workflows/Coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Coverage.yml b/.github/workflows/Coverage.yml index 140342b..6f3fa5d 100644 --- a/.github/workflows/Coverage.yml +++ b/.github/workflows/Coverage.yml @@ -14,7 +14,7 @@ jobs: uses: actions/setup-java@v4 with: java-version: '17' - distribution: 'temurin' + distribution: 'oracle' - name: Setup Gradle uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 From 213484817b6e539b1e9475a5076c8febb1032b71 Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Fri, 12 Apr 2024 21:03:19 +0300 Subject: [PATCH 105/108] Change: Download oracle jdk instead temurin --- .github/workflows/MegaLinter.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/MegaLinter.yml b/.github/workflows/MegaLinter.yml index 2788311..685c55a 100644 --- a/.github/workflows/MegaLinter.yml +++ b/.github/workflows/MegaLinter.yml @@ -5,8 +5,7 @@ name: MegaLinter on: # Trigger mega-linter at every push. Action will also be visible from Pull Requests to main - pull_request: - branches: [master, main] + push: # Comment this line to trigger action only on pull-requests (not recommended if you don't pay for GH Actions) env: # Comment env block if you don't want to apply fixes # Apply linter fixes configuration From c982792284b1c99d416ffc1c455e7073f0177aa5 Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Sat, 13 Apr 2024 08:33:58 +0300 Subject: [PATCH 106/108] Refactor: rename workflows files, rename gradle build workflow --- .github/workflows/{Coverage.yml => coverage.yml} | 0 .github/workflows/{CITest.yml => gradle-build.yml} | 2 +- .github/workflows/{MegaLinter.yml => megalinter.yml} | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename .github/workflows/{Coverage.yml => coverage.yml} (100%) rename .github/workflows/{CITest.yml => gradle-build.yml} (95%) rename .github/workflows/{MegaLinter.yml => megalinter.yml} (100%) diff --git a/.github/workflows/Coverage.yml b/.github/workflows/coverage.yml similarity index 100% rename from .github/workflows/Coverage.yml rename to .github/workflows/coverage.yml diff --git a/.github/workflows/CITest.yml b/.github/workflows/gradle-build.yml similarity index 95% rename from .github/workflows/CITest.yml rename to .github/workflows/gradle-build.yml index b789d56..a419a19 100644 --- a/.github/workflows/CITest.yml +++ b/.github/workflows/gradle-build.yml @@ -1,4 +1,4 @@ -name: CITest +name: Build & Test on: push: diff --git a/.github/workflows/MegaLinter.yml b/.github/workflows/megalinter.yml similarity index 100% rename from .github/workflows/MegaLinter.yml rename to .github/workflows/megalinter.yml From 04523dbe303b58363b6da8c83e46e12200939983 Mon Sep 17 00:00:00 2001 From: Gleb Nasretdinov Date: Sat, 13 Apr 2024 08:44:20 +0300 Subject: [PATCH 107/108] Refactor: rename job in gradle-build workflow --- .github/workflows/gradle-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle-build.yml b/.github/workflows/gradle-build.yml index a419a19..d01a63a 100644 --- a/.github/workflows/gradle-build.yml +++ b/.github/workflows/gradle-build.yml @@ -3,7 +3,7 @@ name: Build & Test on: push: jobs: - CITest: + build: runs-on: ${{ matrix.os }} strategy: matrix: From db033c4069dd8e09ba27df2a3ab1a0095dbeb4d6 Mon Sep 17 00:00:00 2001 From: odiumuniverse Date: Sat, 13 Apr 2024 09:49:45 +0300 Subject: [PATCH 108/108] Refactor: Delete .keep The .keep folder was removed because it was only needed to send an empty directory --- .github/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .github/.keep diff --git a/.github/.keep b/.github/.keep deleted file mode 100644 index e69de29..0000000