{"id":15679358,"url":"https://github.com/penemue/keap","last_synced_at":"2025-05-07T10:37:15.944Z","repository":{"id":57727909,"uuid":"74784525","full_name":"penemue/keap","owner":"penemue","description":"Keap is a heap data structure presenting stable PriorityQueue and stable Keapsort sorting algorithm","archived":false,"fork":false,"pushed_at":"2024-01-30T15:33:40.000Z","size":336,"stargazers_count":12,"open_issues_count":4,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-19T21:24:20.953Z","etag":null,"topics":["data-structures","heapsort","kotlin","priority-queue","priorityqueue","queue","sorting-algorithms","stable-priority-queue","stablesort"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/penemue.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"license.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2016-11-25T19:49:49.000Z","updated_at":"2025-01-09T22:52:40.000Z","dependencies_parsed_at":"2025-04-20T15:15:17.647Z","dependency_job_id":null,"html_url":"https://github.com/penemue/keap","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/penemue%2Fkeap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/penemue%2Fkeap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/penemue%2Fkeap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/penemue%2Fkeap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/penemue","download_url":"https://codeload.github.com/penemue/keap/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252860734,"owners_count":21815559,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["data-structures","heapsort","kotlin","priority-queue","priorityqueue","queue","sorting-algorithms","stable-priority-queue","stablesort"],"created_at":"2024-10-03T16:29:36.125Z","updated_at":"2025-05-07T10:37:15.912Z","avatar_url":"https://github.com/penemue.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Keap\n\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.penemue/keap/badge.svg)](http://search.maven.org/#search%7Cga%7C1%7Ccom.github.penemue.keap)\n[![Maintainability](https://api.codeclimate.com/v1/badges/4161941d1fdf6859d61f/maintainability)](https://codeclimate.com/github/penemue/keap/maintainability)\n[![Apache License 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0.html)\n[![Pure Kotlin](https://img.shields.io/badge/100%25-kotlin-orange.svg)](https://kotlinlang.org)\n\nKeap is a heap data structure written in [Kotlin](http://kotlinlang.org) similar to\n[binary heap](https://en.wikipedia.org/wiki/Binary_heap). It maintains separately the queue of elements and the\n[tournament tree](http://www.geeksforgeeks.org/tournament-tree-and-binary-heap) atop the queue. \n\nKeap is stable, that is, it keeps initial order of equal elements.\n\nIt's faster than binary heap in terms of number of comparisons. For any kind of input (random or ordered) of size `n`,\nthe *heapify* procedure requires exactly `n - 1` comparisons. Binary heap reaches this number of comparisons\nonly for ordered input. For random input, keap compared to binary heap does approximately 1.9 times less comparisons\nto *heapify*, 2.7 times less comparisons to *offer*, and 3.5 times less comparisons to *poll*.\nThough, array-backed keap on the average consumes 1.5 times more memory than array-backed binary heap.\n\nPerformance summary of keap and binary heap (both array-backed) is as follows:\n\u003ctable\u003e\n\u003ctr\u003e\n\u003cth\u003e\u003c/th\u003e\n\u003cth\u003eKeap average\u003c/th\u003e\n\u003cth\u003eKeap worst case\u003c/th\u003e\n\u003cth\u003eBinary heap average\u003c/th\u003e\n\u003cth\u003eBinary heap worst case\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eHeapify\u003c/td\u003e\n\u003ctd\u003eexactly \u003ci\u003en - 1\u003c/i\u003e\u003c/td\u003e\n\u003ctd\u003eexactly \u003ci\u003en - 1\u003c/i\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ci\u003eΘ\u003c/i\u003e(\u003ci\u003en\u003c/i\u003e)\u003c/td\u003e\n\u003ctd\u003e\u003ci\u003eΘ\u003c/i\u003e(\u003ci\u003en\u003c/i\u003e)\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePeek\u003c/td\u003e\n\u003ctd\u003e\u003ci\u003eΘ\u003c/i\u003e(1)\u003c/td\u003e\n\u003ctd\u003e\u003ci\u003eΘ\u003c/i\u003e(1)\u003c/td\u003e\n\u003ctd\u003e\u003ci\u003eΘ\u003c/i\u003e(1)\u003c/td\u003e\n\u003ctd\u003e\u003ci\u003eΘ\u003c/i\u003e(1)\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePoll\u003c/td\u003e\n\u003ctd\u003e\u003ci\u003eΘ\u003c/i\u003e(log \u003ci\u003en\u003c/i\u003e)\u003c/td\u003e\n\u003ctd\u003e\u003ci\u003eΘ\u003c/i\u003e(log \u003ci\u003en\u003c/i\u003e)\u003c/td\u003e\n\u003ctd\u003e\u003ci\u003eΘ\u003c/i\u003e(log \u003ci\u003en\u003c/i\u003e)\u003c/td\u003e\n\u003ctd\u003e\u003ci\u003eΘ\u003c/i\u003e(log \u003ci\u003en\u003c/i\u003e)\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eOffer\u003c/td\u003e\n\u003ctd\u003e\u003ci\u003eΘ\u003c/i\u003e(1)\u003c/td\u003e\n\u003ctd\u003e\u003ci\u003eΘ\u003c/i\u003e(log \u003ci\u003en\u003c/i\u003e)\u003c/td\u003e\n\u003ctd\u003e\u003ci\u003eΘ\u003c/i\u003e(1)\u003c/td\u003e\n\u003ctd\u003e\u003ci\u003eΘ\u003c/i\u003e(log \u003ci\u003en\u003c/i\u003e)\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eMemory used\u003c/td\u003e\n\u003ctd\u003e\u003ci\u003eΘ\u003c/i\u003e(\u003ci\u003en\u003c/i\u003e)\u003c/td\u003e\n\u003ctd\u003e\u003ci\u003eΘ(\u003ci\u003en\u003c/i\u003e)\u003c/i\u003e\u003c/td\u003e\n\u003ctd\u003eexactly \u003ci\u003en\u003c/i\u003e\u003c/td\u003e\n\u003ctd\u003eexactly \u003ci\u003en\u003c/i\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\nHere are two applications: keap-based `PriorityQueue` as a replacement of `java.util.PriorityQueue` and *Keapsort*\nsorting algorithm. Both might be useful in two cases:\n\n1. stability is a must;\n1. comparing elements is rather heavyweight operation (e.g., it requires a database access).\n\n## PriorityQueue\nPriorityQueue is a keap-based stable replacement of `java.util.PriorityQueue`.\n\n## Keapsort\nKeapsort is a [Heapsort](https://en.wikipedia.org/wiki/Heapsort) with keap used instead of binary heap. Keapsort is a\ncomparison-based sorting algorithm with a worst-case [O](https://en.wikipedia.org/wiki/Big_O_notation)(*n* log *n*)\nruntime. As keap is a stable priority queue, Keapsort is stable. Unlike Heapsort, Keapsort doesn't have an in-place\nversion.\n\nLike Heapsort, Keapsort produces first output after [Θ](https://en.wikipedia.org/wiki/Big_O_notation)(*n*) comparisons.\nFor Keapsort, this Θ(n) estimate is just equal to `n - 1`. To sort random input completely, Keapsort does almost\ntwo times less comparisons than Heapsort, nearly 1% less comparisons than\n[Mergesort](https://en.wikipedia.org/wiki/Merge_sort) and 1-2% more comparisons than\n[Timsort](https://en.wikipedia.org/wiki/Timsort).\n\nLike Heapsort, Keapsort is not a modern CPU-friendly algorithm since it has poor data cache performance.\n\nLike Heapsort, Keapsort doesn't seem to parallelize well.\n\n\n## Benchmarks\n[JMH Gradle Plugin](https://github.com/melix/jmh-gradle-plugin) is used to build and run benchmarks.\nBenchmark results are obtained on a PC running under Windows 7 with Intel(R) Core(TM) i7-3770 3.4 GHz CPU\nand 64-bit JRE build 1.8.0_112-b15 with the following java parameters: `-Xms1g -Xmx1g`. To get results in your\nenvironment, run:\n\n    ./gradlew clean jar jmh\n\nFor both `java.util.PriorityQueue` and keap-based PriorityQueue, there are two types of benchmarks:\n\n 1. Benchmarks examining operations with random elements: *heapify* (building the queue from a collection), *offer*,\n *peek*, and *poll*. The queue elements are random strings of length ~30 characters with constant 10-characters prefix.\n Queue size is 10000.\n 1. Benchmarks examining offering ordered elements: *offerIncreasing* (successively increasing elements) and\n *offerDecreasing* (successively decreasing elements). The queue elements are strings of length ~30\n characters with constant 10-characters prefix. Queue size is 10000.\n\nCurrent results grouped for easy review are as follows. Building the queue from collections of random elements:\n```\nBenchmark                                   Mode  Cnt   Score   Error   Units\nJavaQueueRandomBenchmark.heapify           thrpt   20   1.810 ± 0.039  ops/ms\nKeapQueueRandomBenchmark.heapify           thrpt   20   3.487 ± 0.013  ops/ms\n```\nBasic queue operations with random elements:\n```\nBenchmark                                   Mode  Cnt   Score   Error   Units\nJavaQueueRandomBenchmark.offer             thrpt   20   3.649 ± 0.041  ops/us\nJavaQueueRandomBenchmark.peek              thrpt   20  79.458 ± 0.626  ops/us\nJavaQueueRandomBenchmark.poll              thrpt   20   4.250 ± 0.070  ops/us\nKeapQueueRandomBenchmark.offer             thrpt   20   3.727 ± 0.073  ops/us\nKeapQueueRandomBenchmark.peek              thrpt   20  84.371 ± 0.499  ops/us\nKeapQueueRandomBenchmark.poll              thrpt   20  11.993 ± 0.239  ops/us\n```\nOffering ordered elements:\n```\nBenchmark                                   Mode  Cnt   Score   Error   Units\nJavaQueueOrderedBenchmark.offerDecreasing  thrpt   20   5.432 ± 0.177  ops/us\nJavaQueueOrderedBenchmark.offerIncreasing  thrpt   20  30.795 ± 0.588  ops/us\nKeapQueueOrderedBenchmark.offerDecreasing  thrpt   20   7.959 ± 0.033  ops/us\nKeapQueueOrderedBenchmark.offerIncreasing  thrpt   20   8.860 ± 0.044  ops/us\n```\nThe scores above are numbers of operations per microsecond, for *heapify* - per millisecond. So the greater the score,\nthe better performance.\n\n## Download\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.penemue/keap/badge.svg)](http://search.maven.org/#search%7Cga%7C1%7Ccom.github.penemue.keap)\n```xml\n\u003c!-- in Maven project --\u003e\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.github.penemue\u003c/groupId\u003e\n    \u003cartifactId\u003ekeap\u003c/artifactId\u003e\n    \u003cversion\u003e0.3.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n```groovy\n// in Gradle project\ndependencies {\n    compile 'com.github.penemue:keap:0.3.0'\n}\n```\n\n## Building from Source\n[Gradle](http://www.gradle.org) is used to build, test, and run benchmarks. JDK 1.8 and [Kotlin](http://kotlinlang.org)\n1.3.10 are required. To build the project, run:\n\n    ./gradlew\n\n## ToDo\n\n- Compare Keapsort to [Quicksort](https://en.wikipedia.org/wiki/Quicksort).\n\n- Looks like a tree-backed version of keap could be exposed as an immutable/persistent/lock-free heap data structure.\nIn addition, it could support heap merge operation in\n[Θ](https://en.wikipedia.org/wiki/Big_O_notation)(*1*) time.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpenemue%2Fkeap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpenemue%2Fkeap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpenemue%2Fkeap/lists"}