[perf] renamed tree-multiset to tree-multimap

This commit is contained in:
Revone 2023-11-08 09:26:43 +08:00
parent c509a2d640
commit 50d1a168e7
15 changed files with 231 additions and 231 deletions

View file

@ -2,4 +2,4 @@ src/types/data-structures/binary-tree/binary-tree.ts
src/types/data-structures/binary-tree/bst.ts
src/types/data-structures/binary-tree/avl-tree.ts
src/types/data-structures/binary-tree/rb-tree.ts
src/types/data-structures/binary-tree/tree-multiset.ts
src/types/data-structures/binary-tree/tree-multimap.ts

View file

@ -8,7 +8,7 @@ All notable changes to this project will be documented in this file.
- [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
- [`auto-changelog`](https://github.com/CookPete/auto-changelog)
## [v1.42.3](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming)
## [v1.42.4](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming)
### Changes

View file

@ -47,7 +47,7 @@ yarn add data-structure-typed
```js
import {
BinaryTree, Graph, Queue, Stack, PriorityQueue, BST, Trie, DoublyLinkedList,
AVLTree, MinHeap, SinglyLinkedList, DirectedGraph, TreeMultiset,
AVLTree, MinHeap, SinglyLinkedList, DirectedGraph, TreeMultimap,
DirectedVertex, AVLTreeNode
} from 'data-structure-typed';
```
@ -63,7 +63,7 @@ import {
const {Heap} = dataStructureTyped;
const {
BinaryTree, Graph, Queue, Stack, PriorityQueue, BST, Trie, DoublyLinkedList,
AVLTree, MinHeap, SinglyLinkedList, DirectedGraph, TreeMultiset,
AVLTree, MinHeap, SinglyLinkedList, DirectedGraph, TreeMultimap,
DirectedVertex, AVLTreeNode
} = dataStructureTyped;
```
@ -71,7 +71,7 @@ const {
![](https://raw.githubusercontent.com/zrwusa/assets/master/images/data-structure-typed/examples/videos/webp_output/binary-tree-array-to-binary-tree.webp)
![](https://raw.githubusercontent.com/zrwusa/assets/master/images/data-structure-typed/examples/videos/webp_output/binary-tree-dfs-in-order.webp)
![](https://raw.githubusercontent.com/zrwusa/assets/master/images/data-structure-typed/examples/videos/webp_output/avl-tree-test.webp)
![](https://raw.githubusercontent.com/zrwusa/assets/master/images/data-structure-typed/examples/videos/webp_output/tree-multiset-test.webp)
![](https://raw.githubusercontent.com/zrwusa/assets/master/images/data-structure-typed/examples/videos/webp_output/tree-multimap-test.webp)
![](https://raw.githubusercontent.com/zrwusa/assets/master/images/data-structure-typed/examples/videos/webp_output/matrix-cut-off-tree-for-golf.webp)
![](https://raw.githubusercontent.com/zrwusa/assets/master/images/data-structure-typed/examples/videos/webp_output/directed-graph-test.webp)
![](https://raw.githubusercontent.com/zrwusa/assets/master/images/data-structure-typed/examples/videos/webp_output/map-graph-test.webp)
@ -290,7 +290,7 @@ Array.from(dijkstraResult?.seen ?? []).map(vertex => vertex.id) // ['A', 'B', 'D
<td>Tree Multiset</td>
<td><img src="https://raw.githubusercontent.com/zrwusa/assets/master/images/data-structure-typed/assets/tick.svg" alt=""></td>
<td><img src="https://raw.githubusercontent.com/zrwusa/assets/master/images/data-structure-typed/assets/tick.svg" alt=""></td>
<td><a href="https://data-structure-typed-docs.vercel.app/classes/TreeMultiset.html"><span>TreeMultiset</span></a></td>
<td><a href="https://data-structure-typed-docs.vercel.app/classes/TreeMultimap.html"><span>TreeMultimap</span></a></td>
<td><img src="https://raw.githubusercontent.com/zrwusa/assets/master/images/data-structure-typed/assets/tick.svg" alt=""></td>
</tr>
<tr>
@ -627,7 +627,7 @@ Opt for concise and clear method names, avoiding excessive length while ensuring
### Object-oriented programming(OOP)
By strictly adhering to object-oriented design (BinaryTree -> BST -> AVLTree -> TreeMultiset), you can seamlessly
By strictly adhering to object-oriented design (BinaryTree -> BST -> AVLTree -> TreeMultimap), you can seamlessly
inherit the existing data structures to implement the customized ones you need. Object-oriented design stands as the
optimal approach to data structure design.
@ -636,40 +636,40 @@ optimal approach to data structure design.
[//]: # (Start of Replace Section)
<div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>avl-tree</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 add randomly</td><td>30.33</td><td>32.97</td><td>3.56e-4</td></tr><tr><td>10,000 add & delete randomly</td><td>66.10</td><td>15.13</td><td>0.00</td></tr><tr><td>10,000 addMany</td><td>39.44</td><td>25.35</td><td>3.62e-4</td></tr><tr><td>10,000 get</td><td>27.06</td><td>36.96</td><td>2.52e-4</td></tr></table></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 add randomly</td><td>30.52</td><td>32.76</td><td>3.28e-4</td></tr><tr><td>10,000 add & delete randomly</td><td>66.96</td><td>14.94</td><td>0.00</td></tr><tr><td>10,000 addMany</td><td>39.78</td><td>25.14</td><td>3.67e-4</td></tr><tr><td>10,000 get</td><td>27.38</td><td>36.52</td><td>0.00</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>binary-tree</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000 add randomly</td><td>12.90</td><td>77.52</td><td>1.09e-4</td></tr><tr><td>1,000 add & delete randomly</td><td>16.13</td><td>61.99</td><td>1.61e-4</td></tr><tr><td>1,000 addMany</td><td>10.74</td><td>93.09</td><td>1.00e-4</td></tr><tr><td>1,000 get</td><td>18.09</td><td>55.28</td><td>1.90e-4</td></tr><tr><td>1,000 dfs</td><td>71.12</td><td>14.06</td><td>7.83e-4</td></tr><tr><td>1,000 bfs</td><td>57.24</td><td>17.47</td><td>4.17e-4</td></tr><tr><td>1,000 morris</td><td>37.29</td><td>26.81</td><td>3.77e-4</td></tr></table></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000 add randomly</td><td>10.50</td><td>95.20</td><td>2.30e-4</td></tr><tr><td>1,000 add & delete randomly</td><td>16.18</td><td>61.81</td><td>2.48e-4</td></tr><tr><td>1,000 addMany</td><td>10.80</td><td>92.62</td><td>1.83e-4</td></tr><tr><td>1,000 get</td><td>18.03</td><td>55.45</td><td>1.41e-4</td></tr><tr><td>1,000 dfs</td><td>157.86</td><td>6.33</td><td>0.00</td></tr><tr><td>1,000 bfs</td><td>56.68</td><td>17.64</td><td>0.00</td></tr><tr><td>1,000 morris</td><td>37.21</td><td>26.88</td><td>2.79e-4</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>bst</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 add randomly</td><td>31.58</td><td>31.67</td><td>0.00</td></tr><tr><td>10,000 add & delete randomly</td><td>71.09</td><td>14.07</td><td>8.99e-4</td></tr><tr><td>10,000 addMany</td><td>29.68</td><td>33.69</td><td>0.00</td></tr><tr><td>10,000 get</td><td>28.55</td><td>35.03</td><td>0.00</td></tr></table></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 add randomly</td><td>27.61</td><td>36.21</td><td>4.73e-4</td></tr><tr><td>10,000 add & delete randomly</td><td>62.93</td><td>15.89</td><td>5.86e-4</td></tr><tr><td>10,000 addMany</td><td>28.70</td><td>34.84</td><td>0.00</td></tr><tr><td>10,000 get</td><td>27.67</td><td>36.14</td><td>2.92e-4</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>rb-tree</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 add randomly</td><td>84.64</td><td>11.82</td><td>0.01</td></tr><tr><td>100,000 add & 1000 delete randomly</td><td>81.32</td><td>12.30</td><td>0.01</td></tr><tr><td>100,000 getNode</td><td>61.18</td><td>16.35</td><td>0.00</td></tr></table></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 add randomly</td><td>87.51</td><td>11.43</td><td>0.01</td></tr><tr><td>100,000 add & delete randomly</td><td>189.06</td><td>5.29</td><td>0.01</td></tr><tr><td>100,000 getNode</td><td>35.33</td><td>28.31</td><td>8.93e-4</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>directed-graph</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000 addVertex</td><td>0.10</td><td>9637.47</td><td>3.79e-6</td></tr><tr><td>1,000 addEdge</td><td>6.09</td><td>164.18</td><td>1.31e-4</td></tr><tr><td>1,000 getVertex</td><td>0.05</td><td>2.14e+4</td><td>1.35e-6</td></tr><tr><td>1,000 getEdge</td><td>23.91</td><td>41.82</td><td>0.01</td></tr><tr><td>tarjan</td><td>218.65</td><td>4.57</td><td>0.01</td></tr><tr><td>tarjan all</td><td>221.67</td><td>4.51</td><td>0.00</td></tr><tr><td>topologicalSort</td><td>184.34</td><td>5.42</td><td>0.02</td></tr></table></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000 addVertex</td><td>0.10</td><td>9899.91</td><td>8.58e-7</td></tr><tr><td>1,000 addEdge</td><td>6.06</td><td>165.02</td><td>1.68e-4</td></tr><tr><td>1,000 getVertex</td><td>0.05</td><td>2.17e+4</td><td>4.22e-7</td></tr><tr><td>1,000 getEdge</td><td>23.05</td><td>43.38</td><td>0.00</td></tr><tr><td>tarjan</td><td>222.59</td><td>4.49</td><td>0.01</td></tr><tr><td>tarjan all</td><td>226.89</td><td>4.41</td><td>0.01</td></tr><tr><td>topologicalSort</td><td>187.34</td><td>5.34</td><td>0.01</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>heap</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 add & pop</td><td>4.63</td><td>215.77</td><td>4.49e-5</td></tr><tr><td>10,000 fib add & pop</td><td>355.19</td><td>2.82</td><td>0.00</td></tr></table></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 add & pop</td><td>4.66</td><td>214.54</td><td>9.38e-5</td></tr><tr><td>10,000 fib add & pop</td><td>364.30</td><td>2.74</td><td>0.01</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>doubly-linked-list</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 unshift</td><td>213.53</td><td>4.68</td><td>0.02</td></tr><tr><td>1,000,000 unshift & shift</td><td>162.97</td><td>6.14</td><td>0.02</td></tr><tr><td>1,000,000 insertBefore</td><td>335.19</td><td>2.98</td><td>0.09</td></tr></table></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 unshift</td><td>243.61</td><td>4.10</td><td>0.07</td></tr><tr><td>1,000,000 unshift & shift</td><td>173.32</td><td>5.77</td><td>0.03</td></tr><tr><td>1,000,000 insertBefore</td><td>315.86</td><td>3.17</td><td>0.04</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>singly-linked-list</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 push & pop</td><td>231.35</td><td>4.32</td><td>0.02</td></tr><tr><td>10,000 insertBefore</td><td>251.49</td><td>3.98</td><td>0.01</td></tr></table></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 push & pop</td><td>228.06</td><td>4.38</td><td>0.03</td></tr><tr><td>10,000 insertBefore</td><td>252.07</td><td>3.97</td><td>0.01</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>max-priority-queue</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 refill & poll</td><td>11.48</td><td>87.14</td><td>1.91e-4</td></tr></table></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>10,000 refill & poll</td><td>11.53</td><td>86.71</td><td>2.27e-4</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>deque</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>215.14</td><td>4.65</td><td>0.05</td></tr><tr><td>1,000,000 shift</td><td>25.15</td><td>39.76</td><td>0.00</td></tr></table></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>227.24</td><td>4.40</td><td>0.07</td></tr><tr><td>1,000,000 shift</td><td>25.60</td><td>39.07</td><td>0.00</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>queue</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>44.15</td><td>22.65</td><td>0.01</td></tr><tr><td>1,000,000 push & shift</td><td>80.87</td><td>12.37</td><td>0.00</td></tr></table></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>1,000,000 push</td><td>45.98</td><td>21.75</td><td>0.01</td></tr><tr><td>1,000,000 push & shift</td><td>81.12</td><td>12.33</td><td>0.00</td></tr></table></div>
</div><div class="json-to-html-collapse clearfix 0">
<div class='collapsible level0' ><span class='json-to-html-label'>trie</span></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 push</td><td>61.38</td><td>16.29</td><td>0.01</td></tr><tr><td>100,000 getWords</td><td>104.27</td><td>9.59</td><td>0.02</td></tr></table></div>
<div class="content"><table style="display: table; width:100%; table-layout: fixed;"><tr><th>test name</th><th>time taken (ms)</th><th>executions per sec</th><th>sample deviation</th></tr><tr><td>100,000 push</td><td>59.40</td><td>16.83</td><td>0.01</td></tr><tr><td>100,000 getWords</td><td>90.07</td><td>11.10</td><td>0.00</td></tr></table></div>
</div>
[//]: # (End of Replace Section)

View file

@ -1,6 +1,6 @@
{
"name": "data-structure-typed",
"version": "1.42.4",
"version": "1.42.5",
"description": "Data Structures of Javascript & TypeScript. Binary Tree, BST, Graph, Heap, Priority Queue, Linked List, Queue, Deque, Stack, AVL Tree, Tree Multiset, Trie, Directed Graph, Undirected Graph, Singly Linked List, Doubly Linked List, Max Heap, Max Priority Queue, Min Heap, Min Priority Queue.",
"main": "dist/cjs/src/index.js",
"module": "dist/mjs/src/index.js",
@ -30,7 +30,7 @@
"reformat:test": "npm run lint:test && npm run format:test",
"reformat": "npm run reformat:src && npm run reformat:test",
"update:subs": "npm i avl-tree-typed binary-tree-typed bst-typed heap-typed --save-dev",
"install:all-subs": "npm i avl-tree-typed binary-tree-typed bst-typed deque-typed directed-graph-typed doubly-linked-list-typed graph-typed heap-typed linked-list-typed max-heap-typed max-priority-queue-typed min-heap-typed min-priority-queue-typed priority-queue-typed singly-linked-list-typed stack-typed tree-multiset-typed trie-typed undirected-graph-typed queue-typed --save-dev",
"install:all-subs": "npm i avl-tree-typed binary-tree-typed bst-typed deque-typed directed-graph-typed doubly-linked-list-typed graph-typed heap-typed linked-list-typed max-heap-typed max-priority-queue-typed min-heap-typed min-priority-queue-typed priority-queue-typed singly-linked-list-typed stack-typed tree-multimap-typed trie-typed undirected-graph-typed queue-typed --save-dev",
"test": "jest --runInBand",
"test:integration": "npm run update:subs && jest --config jest.integration.config.js",
"benchmark": "ts-node test/performance/reportor.ts",
@ -161,7 +161,7 @@
"avl-tree",
"tree multiset",
"treemultiset",
"tree-multiset",
"tree-multimap",
"binary indexed tree",
"binaryindexedtree",
"binary-indexed-tree",

View file

@ -28,7 +28,7 @@ directories=(
"singly-linked-list-typed"
"queue-typed"
"stack-typed"
"tree-multiset-typed"
"tree-multimap-typed"
"trie-typed"
"undirected-graph-typed"
)

View file

@ -46,7 +46,7 @@ directories=(
"singly-linked-list-typed"
"queue-typed"
"stack-typed"
"tree-multiset-typed"
"tree-multimap-typed"
"trie-typed"
"undirected-graph-typed"
)

View file

@ -42,7 +42,7 @@ directories=(
"singly-linked-list-typed"
"queue-typed"
"stack-typed"
"tree-multiset-typed"
"tree-multimap-typed"
"trie-typed"
"undirected-graph-typed"
)

View file

@ -4,4 +4,4 @@ export * from './binary-indexed-tree';
export * from './segment-tree';
export * from './avl-tree';
export * from './rb-tree';
export * from './tree-multiset';
export * from './tree-multimap';

View file

@ -5,14 +5,14 @@
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
* @license MIT License
*/
import type {BTNKey, TreeMultisetNodeNested, TreeMultisetOptions} from '../../types';
import type {BTNKey, TreeMultimapNodeNested, TreeMultimapOptions} from '../../types';
import {BinaryTreeDeletedResult, BTNCallback, CP, FamilyPosition, IterationType} from '../../types';
import {IBinaryTree} from '../../interfaces';
import {AVLTree, AVLTreeNode} from './avl-tree';
export class TreeMultisetNode<
export class TreeMultimapNode<
V = any,
N extends TreeMultisetNode<V, N> = TreeMultisetNodeNested<V>
N extends TreeMultimapNode<V, N> = TreeMultimapNodeNested<V>
> extends AVLTreeNode<V, N> {
count: number;
@ -33,19 +33,19 @@ export class TreeMultisetNode<
}
/**
* The only distinction between a TreeMultiset and a AVLTree lies in the ability of the former to store duplicate nodes through the utilization of counters.
* The only distinction between a TreeMultimap and a AVLTree lies in the ability of the former to store duplicate nodes through the utilization of counters.
*/
export class TreeMultiset<V = any, N extends TreeMultisetNode<V, N> = TreeMultisetNode<V, TreeMultisetNodeNested<V>>>
export class TreeMultimap<V = any, N extends TreeMultimapNode<V, N> = TreeMultimapNode<V, TreeMultimapNodeNested<V>>>
extends AVLTree<V, N>
implements IBinaryTree<V, N>
{
/**
* The constructor function for a TreeMultiset class in TypeScript, which extends another class and sets an option to
* The constructor function for a TreeMultimap class in TypeScript, which extends another class and sets an option to
* merge duplicated values.
* @param {TreeMultisetOptions} [options] - An optional object that contains additional configuration options for the
* TreeMultiset.
* @param {TreeMultimapOptions} [options] - An optional object that contains additional configuration options for the
* TreeMultimap.
*/
constructor(options?: TreeMultisetOptions) {
constructor(options?: TreeMultimapOptions) {
super(options);
}
@ -65,7 +65,7 @@ export class TreeMultiset<V = any, N extends TreeMultisetNode<V, N> = TreeMultis
* @returns A new instance of the BSTNode class with the specified key, value, and count (if provided).
*/
override createNode(key: BTNKey, value?: V, count?: number): N {
return new TreeMultisetNode(key, value, count) as N;
return new TreeMultimapNode(key, value, count) as N;
}
/**
@ -85,7 +85,7 @@ export class TreeMultiset<V = any, N extends TreeMultisetNode<V, N> = TreeMultis
if(keyOrNode === null) return undefined;
let inserted: N | undefined = undefined,
newNode: N | undefined;
if (keyOrNode instanceof TreeMultisetNode) {
if (keyOrNode instanceof TreeMultimapNode) {
newNode = this.createNode(keyOrNode.key, keyOrNode.value, keyOrNode.count);
} else if (keyOrNode === undefined) {
newNode = undefined;
@ -184,10 +184,10 @@ export class TreeMultiset<V = any, N extends TreeMultisetNode<V, N> = TreeMultis
}
/**
* The `addMany` function adds multiple keys or nodes to a TreeMultiset and returns an array of the
* The `addMany` function adds multiple keys or nodes to a TreeMultimap and returns an array of the
* inserted nodes.
* @param {(BTNKey | undefined)[] | (N | undefined)[]} keysOrNodes - An array of keys or nodes to be
* added to the multiset. Each element can be either a BTNKey or a TreeMultisetNode.
* added to the multiset. Each element can be either a BTNKey or a TreeMultimapNode.
* @param {V[]} [data] - The `data` parameter is an optional array of values that correspond
* to the keys or nodes being added to the multiset. It is used to associate additional data with
* each key or node.
@ -199,7 +199,7 @@ export class TreeMultiset<V = any, N extends TreeMultisetNode<V, N> = TreeMultis
for (let i = 0; i < keysOrNodes.length; i++) {
const keyOrNode = keysOrNodes[i];
if (keyOrNode instanceof TreeMultisetNode) {
if (keyOrNode instanceof TreeMultimapNode) {
inserted.push(this.add(keyOrNode.key, keyOrNode.value, keyOrNode.count));
continue;
}

View file

@ -2,5 +2,5 @@ export * from './binary-tree';
export * from './bst';
export * from './avl-tree';
export * from './segment-tree';
export * from './tree-multiset';
export * from './tree-multimap';
export * from './rb-tree';

View file

@ -0,0 +1,6 @@
import {TreeMultimapNode} from '../../../data-structures';
import {AVLTreeOptions} from './avl-tree';
export type TreeMultimapNodeNested<T> = TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, TreeMultimapNode<T, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
export type TreeMultimapOptions = Omit<AVLTreeOptions, 'isMergeDuplicatedNodeByKey'> & {}

View file

@ -1,6 +0,0 @@
import {TreeMultisetNode} from '../../../data-structures';
import {AVLTreeOptions} from './avl-tree';
export type TreeMultisetNodeNested<T> = TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, TreeMultisetNode<T, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
export type TreeMultisetOptions = Omit<AVLTreeOptions, 'isMergeDuplicatedNodeByKey'> & {}

View file

@ -14,12 +14,12 @@ suite
rbTree.add(arr[i]);
}
})
.add(`${HUNDRED_THOUSAND.toLocaleString()} add & 1000 delete randomly`, () => {
.add(`${HUNDRED_THOUSAND.toLocaleString()} add & delete randomly`, () => {
rbTree.clear();
for (let i = 0; i < arr.length; i++) {
rbTree.add(arr[i]);
}
for (let i = 0; i < 1000; i++) {
for (let i = 0; i < arr.length; i++) {
rbTree.delete(arr[i]);
}
})

View file

@ -1,216 +1,216 @@
import {CP, IterationType, TreeMultiset, TreeMultisetNode} from '../../../../src';
import {CP, IterationType, TreeMultimap, TreeMultimapNode} from '../../../../src';
import {isDebugTest} from '../../../config';
const isDebug = isDebugTest;
describe('TreeMultiset operations test', () => {
describe('TreeMultimap operations test', () => {
it('should perform various operations on a Binary Search Tree with numeric values', () => {
const treeMultiset = new TreeMultiset();
const treeMultimap = new TreeMultimap();
expect(treeMultiset instanceof TreeMultiset);
treeMultiset.add(11, 11);
treeMultiset.add(3, 3);
expect(treeMultimap instanceof TreeMultimap);
treeMultimap.add(11, 11);
treeMultimap.add(3, 3);
const idAndValues = [11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5];
treeMultiset.addMany(idAndValues, idAndValues);
expect(treeMultiset.root instanceof TreeMultisetNode);
treeMultimap.addMany(idAndValues, idAndValues);
expect(treeMultimap.root instanceof TreeMultimapNode);
if (treeMultiset.root) expect(treeMultiset.root.key == 11);
if (treeMultimap.root) expect(treeMultimap.root.key == 11);
expect(treeMultiset.size).toBe(16);
expect(treeMultiset.count).toBe(18);
expect(treeMultimap.size).toBe(16);
expect(treeMultimap.count).toBe(18);
expect(treeMultiset.has(6));
expect(treeMultimap.has(6));
expect(treeMultiset.getHeight(6)).toBe(3);
expect(treeMultiset.getDepth(6)).toBe(1);
const nodeId10 = treeMultiset.getNode(10);
expect(treeMultimap.getHeight(6)).toBe(3);
expect(treeMultimap.getDepth(6)).toBe(1);
const nodeId10 = treeMultimap.getNode(10);
expect(nodeId10?.key).toBe(10);
const nodeVal9 = treeMultiset.getNode(9, node => node.value);
const nodeVal9 = treeMultimap.getNode(9, node => node.value);
expect(nodeVal9?.key).toBe(9);
const nodesByCount1 = treeMultiset.getNodes(1, node => node.count);
const nodesByCount1 = treeMultimap.getNodes(1, node => node.count);
expect(nodesByCount1.length).toBe(14);
const nodesByCount2 = treeMultiset.getNodes(2, node => node.count);
const nodesByCount2 = treeMultimap.getNodes(2, node => node.count);
expect(nodesByCount2.length).toBe(2);
const leftMost = treeMultiset.getLeftMost();
const leftMost = treeMultimap.getLeftMost();
expect(leftMost?.key).toBe(1);
const node15 = treeMultiset.getNode(15);
const minNodeBySpecificNode = node15 && treeMultiset.getLeftMost(node15);
const node15 = treeMultimap.getNode(15);
const minNodeBySpecificNode = node15 && treeMultimap.getLeftMost(node15);
expect(minNodeBySpecificNode?.key).toBe(12);
let subTreeSum = 0;
node15 && treeMultiset.subTreeTraverse((node: TreeMultisetNode<number>) => (subTreeSum += node.key), 15);
node15 && treeMultimap.subTreeTraverse((node: TreeMultimapNode<number>) => (subTreeSum += node.key), 15);
expect(subTreeSum).toBe(70);
let lesserSum = 0;
treeMultiset.lesserOrGreaterTraverse((node: TreeMultisetNode<number>) => (lesserSum += node.key), CP.lt, 10);
treeMultimap.lesserOrGreaterTraverse((node: TreeMultimapNode<number>) => (lesserSum += node.key), CP.lt, 10);
expect(lesserSum).toBe(45);
expect(node15 instanceof TreeMultisetNode);
if (node15 instanceof TreeMultisetNode) {
const subTreeAdd = treeMultiset.subTreeTraverse((node: TreeMultisetNode<number>) => (node.count += 1), 15);
expect(node15 instanceof TreeMultimapNode);
if (node15 instanceof TreeMultimapNode) {
const subTreeAdd = treeMultimap.subTreeTraverse((node: TreeMultimapNode<number>) => (node.count += 1), 15);
expect(subTreeAdd);
}
const node11 = treeMultiset.getNode(11);
expect(node11 instanceof TreeMultisetNode);
if (node11 instanceof TreeMultisetNode) {
const allGreaterNodesAdded = treeMultiset.lesserOrGreaterTraverse(node => (node.count += 2), CP.gt, 11);
const node11 = treeMultimap.getNode(11);
expect(node11 instanceof TreeMultimapNode);
if (node11 instanceof TreeMultimapNode) {
const allGreaterNodesAdded = treeMultimap.lesserOrGreaterTraverse(node => (node.count += 2), CP.gt, 11);
expect(allGreaterNodesAdded);
}
const dfsInorderNodes = treeMultiset.dfs(node => node, 'in');
const dfsInorderNodes = treeMultimap.dfs(node => node, 'in');
expect(dfsInorderNodes[0].key).toBe(1);
expect(dfsInorderNodes[dfsInorderNodes.length - 1].key).toBe(16);
expect(treeMultiset.isPerfectlyBalanced()).toBe(false);
expect(treeMultimap.isPerfectlyBalanced()).toBe(false);
treeMultiset.perfectlyBalance();
treeMultimap.perfectlyBalance();
expect(treeMultiset.isPerfectlyBalanced()).toBe(true);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultimap.isPerfectlyBalanced()).toBe(true);
expect(treeMultimap.isAVLBalanced()).toBe(true);
const bfsNodesAfterBalanced = treeMultiset.bfs(node => node);
const bfsNodesAfterBalanced = treeMultimap.bfs(node => node);
expect(bfsNodesAfterBalanced[0].key).toBe(8);
expect(bfsNodesAfterBalanced[bfsNodesAfterBalanced.length - 1].key).toBe(16);
const removed11 = treeMultiset.delete(11, undefined, true);
const removed11 = treeMultimap.delete(11, undefined, true);
expect(removed11 instanceof Array);
expect(removed11[0]);
expect(removed11[0].deleted);
if (removed11[0].deleted) expect(removed11[0].deleted.key).toBe(11);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight(15)).toBe(1);
expect(treeMultimap.getHeight(15)).toBe(1);
const removed1 = treeMultiset.delete(1, undefined, true);
const removed1 = treeMultimap.delete(1, undefined, true);
expect(removed1 instanceof Array);
expect(removed1[0]);
expect(removed1[0].deleted);
if (removed1[0].deleted) expect(removed1[0].deleted.key).toBe(1);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight()).toBe(4);
expect(treeMultimap.getHeight()).toBe(4);
const removed4 = treeMultiset.delete(4, undefined, true);
const removed4 = treeMultimap.delete(4, undefined, true);
expect(removed4 instanceof Array);
expect(removed4[0]);
expect(removed4[0].deleted);
if (removed4[0].deleted) expect(removed4[0].deleted.key).toBe(4);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight()).toBe(4);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(4);
const removed10 = treeMultiset.delete(10, undefined, true);
const removed10 = treeMultimap.delete(10, undefined, true);
expect(removed10 instanceof Array);
expect(removed10[0]);
expect(removed10[0].deleted);
if (removed10[0].deleted) expect(removed10[0].deleted.key).toBe(10);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight()).toBe(3);
expect(treeMultimap.getHeight()).toBe(3);
const removed15 = treeMultiset.delete(15, undefined, true);
const removed15 = treeMultimap.delete(15, undefined, true);
expect(removed15 instanceof Array);
expect(removed15[0]);
expect(removed15[0].deleted);
if (removed15[0].deleted) expect(removed15[0].deleted.key).toBe(15);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight()).toBe(3);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(3);
const removed5 = treeMultiset.delete(5, undefined, true);
const removed5 = treeMultimap.delete(5, undefined, true);
expect(removed5 instanceof Array);
expect(removed5[0]);
expect(removed5[0].deleted);
if (removed5[0].deleted) expect(removed5[0].deleted.key).toBe(5);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight()).toBe(3);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(3);
const removed13 = treeMultiset.delete(13, undefined, true);
const removed13 = treeMultimap.delete(13, undefined, true);
expect(removed13 instanceof Array);
expect(removed13[0]);
expect(removed13[0].deleted);
if (removed13[0].deleted) expect(removed13[0].deleted.key).toBe(13);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight()).toBe(3);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(3);
const removed3 = treeMultiset.delete(3, undefined, true);
const removed3 = treeMultimap.delete(3, undefined, true);
expect(removed3 instanceof Array);
expect(removed3[0]);
expect(removed3[0].deleted);
if (removed3[0].deleted) expect(removed3[0].deleted.key).toBe(3);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight()).toBe(3);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(3);
const removed8 = treeMultiset.delete(8, undefined, true);
const removed8 = treeMultimap.delete(8, undefined, true);
expect(removed8 instanceof Array);
expect(removed8[0]);
expect(removed8[0].deleted);
if (removed8[0].deleted) expect(removed8[0].deleted.key).toBe(8);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight()).toBe(3);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(3);
const removed6 = treeMultiset.delete(6, undefined, true);
const removed6 = treeMultimap.delete(6, undefined, true);
expect(removed6 instanceof Array);
expect(removed6[0]);
expect(removed6[0].deleted);
if (removed6[0].deleted) expect(removed6[0].deleted.key).toBe(6);
expect(treeMultiset.delete(6, undefined, true).length).toBe(0);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultimap.delete(6, undefined, true).length).toBe(0);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight()).toBe(2);
expect(treeMultimap.getHeight()).toBe(2);
const removed7 = treeMultiset.delete(7, undefined, true);
const removed7 = treeMultimap.delete(7, undefined, true);
expect(removed7 instanceof Array);
expect(removed7[0]);
expect(removed7[0].deleted);
if (removed7[0].deleted) expect(removed7[0].deleted.key).toBe(7);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight()).toBe(2);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(2);
const removed9 = treeMultiset.delete(9, undefined, true);
const removed9 = treeMultimap.delete(9, undefined, true);
expect(removed9 instanceof Array);
expect(removed9[0]);
expect(removed9[0].deleted);
if (removed9[0].deleted) expect(removed9[0].deleted.key).toBe(9);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight()).toBe(2);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(2);
const removed14 = treeMultiset.delete(14, undefined, true);
const removed14 = treeMultimap.delete(14, undefined, true);
expect(removed14 instanceof Array);
expect(removed14[0]);
expect(removed14[0].deleted);
if (removed14[0].deleted) expect(removed14[0].deleted.key).toBe(14);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight()).toBe(1);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(1);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultimap.isAVLBalanced()).toBe(true);
const bfsIDs = treeMultiset.bfs(node => node.key);
const bfsIDs = treeMultimap.bfs(node => node.key);
expect(bfsIDs[0]).toBe(12);
expect(bfsIDs[1]).toBe(2);
expect(bfsIDs[2]).toBe(16);
const bfsNodes = treeMultiset.bfs(node => node);
const bfsNodes = treeMultimap.bfs(node => node);
expect(bfsNodes[0].key).toBe(12);
expect(bfsNodes[1].key).toBe(2);
expect(bfsNodes[2].key).toBe(16);
expect(treeMultiset.count).toBe(9);
expect(treeMultimap.count).toBe(9);
});
it('should perform various operations on a Binary Search Tree with object values', () => {
const objTreeMultiset = new TreeMultiset<{key: number; keyA: number}>();
expect(objTreeMultiset).toBeInstanceOf(TreeMultiset);
objTreeMultiset.add(11, {key: 11, keyA: 11});
objTreeMultiset.add(3, {key: 3, keyA: 3});
const objTreeMultimap = new TreeMultimap<{key: number; keyA: number}>();
expect(objTreeMultimap).toBeInstanceOf(TreeMultimap);
objTreeMultimap.add(11, {key: 11, keyA: 11});
objTreeMultimap.add(3, {key: 3, keyA: 3});
const values = [
{key: 15, keyA: 15},
{key: 1, keyA: 1},
@ -228,229 +228,229 @@ describe('TreeMultiset operations test', () => {
{key: 5, keyA: 5}
];
objTreeMultiset.addMany(
objTreeMultimap.addMany(
values.map(item => item.key),
values
);
expect(objTreeMultiset.root).toBeInstanceOf(TreeMultisetNode);
expect(objTreeMultimap.root).toBeInstanceOf(TreeMultimapNode);
if (objTreeMultiset.root) expect(objTreeMultiset.root.key).toBe(11);
if (objTreeMultimap.root) expect(objTreeMultimap.root.key).toBe(11);
expect(objTreeMultiset.count).toBe(16);
expect(objTreeMultimap.count).toBe(16);
expect(objTreeMultiset.has(6)).toBe(true);
expect(objTreeMultimap.has(6)).toBe(true);
});
});
describe('TreeMultiset operations test recursively', () => {
describe('TreeMultimap operations test recursively', () => {
it('should perform various operations on a Binary Search Tree with numeric values', () => {
const treeMultiset = new TreeMultiset({iterationType: IterationType.RECURSIVE});
const treeMultimap = new TreeMultimap({iterationType: IterationType.RECURSIVE});
expect(treeMultiset instanceof TreeMultiset);
treeMultiset.add(11, 11);
treeMultiset.add(3, 3);
expect(treeMultimap instanceof TreeMultimap);
treeMultimap.add(11, 11);
treeMultimap.add(3, 3);
const idAndValues = [11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5];
treeMultiset.addMany(idAndValues, idAndValues);
expect(treeMultiset.root instanceof TreeMultisetNode);
treeMultimap.addMany(idAndValues, idAndValues);
expect(treeMultimap.root instanceof TreeMultimapNode);
if (treeMultiset.root) expect(treeMultiset.root.key == 11);
if (treeMultimap.root) expect(treeMultimap.root.key == 11);
expect(treeMultiset.size).toBe(16);
expect(treeMultiset.count).toBe(18);
expect(treeMultimap.size).toBe(16);
expect(treeMultimap.count).toBe(18);
expect(treeMultiset.has(6));
expect(treeMultimap.has(6));
expect(treeMultiset.getHeight(6)).toBe(3);
expect(treeMultiset.getDepth(6)).toBe(1);
const nodeId10 = treeMultiset.getNode(10);
expect(treeMultimap.getHeight(6)).toBe(3);
expect(treeMultimap.getDepth(6)).toBe(1);
const nodeId10 = treeMultimap.getNode(10);
expect(nodeId10?.key).toBe(10);
const nodeVal9 = treeMultiset.getNode(9, node => node.value);
const nodeVal9 = treeMultimap.getNode(9, node => node.value);
expect(nodeVal9?.key).toBe(9);
const nodesByCount1 = treeMultiset.getNodes(1, node => node.count);
const nodesByCount1 = treeMultimap.getNodes(1, node => node.count);
expect(nodesByCount1.length).toBe(14);
const nodesByCount2 = treeMultiset.getNodes(2, node => node.count);
const nodesByCount2 = treeMultimap.getNodes(2, node => node.count);
expect(nodesByCount2.length).toBe(2);
const leftMost = treeMultiset.getLeftMost();
const leftMost = treeMultimap.getLeftMost();
expect(leftMost?.key).toBe(1);
const node15 = treeMultiset.getNode(15);
const minNodeBySpecificNode = node15 && treeMultiset.getLeftMost(node15);
const node15 = treeMultimap.getNode(15);
const minNodeBySpecificNode = node15 && treeMultimap.getLeftMost(node15);
expect(minNodeBySpecificNode?.key).toBe(12);
let subTreeSum = 0;
node15 && treeMultiset.subTreeTraverse((node: TreeMultisetNode<number>) => (subTreeSum += node.key), 15);
node15 && treeMultimap.subTreeTraverse((node: TreeMultimapNode<number>) => (subTreeSum += node.key), 15);
expect(subTreeSum).toBe(70);
let lesserSum = 0;
treeMultiset.lesserOrGreaterTraverse((node: TreeMultisetNode<number>) => (lesserSum += node.key), CP.lt, 10);
treeMultimap.lesserOrGreaterTraverse((node: TreeMultimapNode<number>) => (lesserSum += node.key), CP.lt, 10);
expect(lesserSum).toBe(45);
expect(node15 instanceof TreeMultisetNode);
if (node15 instanceof TreeMultisetNode) {
const subTreeAdd = treeMultiset.subTreeTraverse((node: TreeMultisetNode<number>) => (node.count += 1), 15);
expect(node15 instanceof TreeMultimapNode);
if (node15 instanceof TreeMultimapNode) {
const subTreeAdd = treeMultimap.subTreeTraverse((node: TreeMultimapNode<number>) => (node.count += 1), 15);
expect(subTreeAdd);
}
const node11 = treeMultiset.getNode(11);
expect(node11 instanceof TreeMultisetNode);
if (node11 instanceof TreeMultisetNode) {
const allGreaterNodesAdded = treeMultiset.lesserOrGreaterTraverse(node => (node.count += 2), CP.gt, 11);
const node11 = treeMultimap.getNode(11);
expect(node11 instanceof TreeMultimapNode);
if (node11 instanceof TreeMultimapNode) {
const allGreaterNodesAdded = treeMultimap.lesserOrGreaterTraverse(node => (node.count += 2), CP.gt, 11);
expect(allGreaterNodesAdded);
}
const dfsInorderNodes = treeMultiset.dfs(node => node, 'in');
const dfsInorderNodes = treeMultimap.dfs(node => node, 'in');
expect(dfsInorderNodes[0].key).toBe(1);
expect(dfsInorderNodes[dfsInorderNodes.length - 1].key).toBe(16);
expect(treeMultiset.isPerfectlyBalanced()).toBe(false);
expect(treeMultimap.isPerfectlyBalanced()).toBe(false);
treeMultiset.perfectlyBalance();
treeMultimap.perfectlyBalance();
expect(treeMultiset.isPerfectlyBalanced()).toBe(true);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultimap.isPerfectlyBalanced()).toBe(true);
expect(treeMultimap.isAVLBalanced()).toBe(true);
const bfsNodesAfterBalanced = treeMultiset.bfs(node => node);
const bfsNodesAfterBalanced = treeMultimap.bfs(node => node);
expect(bfsNodesAfterBalanced[0].key).toBe(8);
expect(bfsNodesAfterBalanced[bfsNodesAfterBalanced.length - 1].key).toBe(16);
const removed11 = treeMultiset.delete(11, undefined, true);
const removed11 = treeMultimap.delete(11, undefined, true);
expect(removed11 instanceof Array);
expect(removed11[0]);
expect(removed11[0].deleted);
if (removed11[0].deleted) expect(removed11[0].deleted.key).toBe(11);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight(15)).toBe(1);
expect(treeMultimap.getHeight(15)).toBe(1);
const removed1 = treeMultiset.delete(1, undefined, true);
const removed1 = treeMultimap.delete(1, undefined, true);
expect(removed1 instanceof Array);
expect(removed1[0]);
expect(removed1[0].deleted);
if (removed1[0].deleted) expect(removed1[0].deleted.key).toBe(1);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight()).toBe(4);
expect(treeMultimap.getHeight()).toBe(4);
const removed4 = treeMultiset.delete(4, undefined, true);
const removed4 = treeMultimap.delete(4, undefined, true);
expect(removed4 instanceof Array);
expect(removed4[0]);
expect(removed4[0].deleted);
if (removed4[0].deleted) expect(removed4[0].deleted.key).toBe(4);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight()).toBe(4);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(4);
const removed10 = treeMultiset.delete(10, undefined, true);
const removed10 = treeMultimap.delete(10, undefined, true);
expect(removed10 instanceof Array);
expect(removed10[0]);
expect(removed10[0].deleted);
if (removed10[0].deleted) expect(removed10[0].deleted.key).toBe(10);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight()).toBe(3);
expect(treeMultimap.getHeight()).toBe(3);
const removed15 = treeMultiset.delete(15, undefined, true);
const removed15 = treeMultimap.delete(15, undefined, true);
expect(removed15 instanceof Array);
expect(removed15[0]);
expect(removed15[0].deleted);
if (removed15[0].deleted) expect(removed15[0].deleted.key).toBe(15);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight()).toBe(3);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(3);
const removed5 = treeMultiset.delete(5, undefined, true);
const removed5 = treeMultimap.delete(5, undefined, true);
expect(removed5 instanceof Array);
expect(removed5[0]);
expect(removed5[0].deleted);
if (removed5[0].deleted) expect(removed5[0].deleted.key).toBe(5);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight()).toBe(3);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(3);
const removed13 = treeMultiset.delete(13, undefined, true);
const removed13 = treeMultimap.delete(13, undefined, true);
expect(removed13 instanceof Array);
expect(removed13[0]);
expect(removed13[0].deleted);
if (removed13[0].deleted) expect(removed13[0].deleted.key).toBe(13);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight()).toBe(3);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(3);
const removed3 = treeMultiset.delete(3, undefined, true);
const removed3 = treeMultimap.delete(3, undefined, true);
expect(removed3 instanceof Array);
expect(removed3[0]);
expect(removed3[0].deleted);
if (removed3[0].deleted) expect(removed3[0].deleted.key).toBe(3);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight()).toBe(3);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(3);
const removed8 = treeMultiset.delete(8, undefined, true);
const removed8 = treeMultimap.delete(8, undefined, true);
expect(removed8 instanceof Array);
expect(removed8[0]);
expect(removed8[0].deleted);
if (removed8[0].deleted) expect(removed8[0].deleted.key).toBe(8);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight()).toBe(3);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(3);
const removed6 = treeMultiset.delete(6, undefined, true);
const removed6 = treeMultimap.delete(6, undefined, true);
expect(removed6 instanceof Array);
expect(removed6[0]);
expect(removed6[0].deleted);
if (removed6[0].deleted) expect(removed6[0].deleted.key).toBe(6);
expect(treeMultiset.delete(6, undefined, true).length).toBe(0);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultimap.delete(6, undefined, true).length).toBe(0);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight()).toBe(2);
expect(treeMultimap.getHeight()).toBe(2);
const removed7 = treeMultiset.delete(7, undefined, true);
const removed7 = treeMultimap.delete(7, undefined, true);
expect(removed7 instanceof Array);
expect(removed7[0]);
expect(removed7[0].deleted);
if (removed7[0].deleted) expect(removed7[0].deleted.key).toBe(7);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight()).toBe(2);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(2);
const removed9 = treeMultiset.delete(9, undefined, true);
const removed9 = treeMultimap.delete(9, undefined, true);
expect(removed9 instanceof Array);
expect(removed9[0]);
expect(removed9[0].deleted);
if (removed9[0].deleted) expect(removed9[0].deleted.key).toBe(9);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight()).toBe(2);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(2);
const removed14 = treeMultiset.delete(14, undefined, true);
const removed14 = treeMultimap.delete(14, undefined, true);
expect(removed14 instanceof Array);
expect(removed14[0]);
expect(removed14[0].deleted);
if (removed14[0].deleted) expect(removed14[0].deleted.key).toBe(14);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultiset.getHeight()).toBe(1);
expect(treeMultimap.isAVLBalanced()).toBe(true);
expect(treeMultimap.getHeight()).toBe(1);
expect(treeMultiset.isAVLBalanced()).toBe(true);
expect(treeMultimap.isAVLBalanced()).toBe(true);
const bfsIDs = treeMultiset.bfs(node => node.key);
const bfsIDs = treeMultimap.bfs(node => node.key);
expect(bfsIDs[0]).toBe(12);
expect(bfsIDs[1]).toBe(2);
expect(bfsIDs[2]).toBe(16);
const bfsNodes = treeMultiset.bfs(node => node);
const bfsNodes = treeMultimap.bfs(node => node);
expect(bfsNodes[0].key).toBe(12);
expect(bfsNodes[1].key).toBe(2);
expect(bfsNodes[2].key).toBe(16);
expect(treeMultiset.count).toBe(9);
expect(treeMultimap.count).toBe(9);
});
it('should perform various operations on a Binary Search Tree with object values', () => {
const objTreeMultiset = new TreeMultiset<{key: number; keyA: number}>();
expect(objTreeMultiset).toBeInstanceOf(TreeMultiset);
objTreeMultiset.add(11, {key: 11, keyA: 11});
objTreeMultiset.add(3, {key: 3, keyA: 3});
const objTreeMultimap = new TreeMultimap<{key: number; keyA: number}>();
expect(objTreeMultimap).toBeInstanceOf(TreeMultimap);
objTreeMultimap.add(11, {key: 11, keyA: 11});
objTreeMultimap.add(3, {key: 3, keyA: 3});
const values = [
{key: 15, keyA: 15},
{key: 1, keyA: 1},
@ -468,29 +468,29 @@ describe('TreeMultiset operations test recursively', () => {
{key: 5, keyA: 5}
];
objTreeMultiset.addMany(
objTreeMultimap.addMany(
values.map(item => item.key),
values
);
expect(objTreeMultiset.root).toBeInstanceOf(TreeMultisetNode);
expect(objTreeMultimap.root).toBeInstanceOf(TreeMultimapNode);
if (objTreeMultiset.root) expect(objTreeMultiset.root.key).toBe(11);
if (objTreeMultimap.root) expect(objTreeMultimap.root.key).toBe(11);
expect(objTreeMultiset.count).toBe(16);
expect(objTreeMultimap.count).toBe(16);
expect(objTreeMultiset.has(6)).toBe(true);
expect(objTreeMultimap.has(6)).toBe(true);
});
});
describe('TreeMultiset Performance test', function () {
const treeMS = new TreeMultiset<TreeMultisetNode<number>>();
describe('TreeMultimap Performance test', function () {
const treeMS = new TreeMultimap<TreeMultimapNode<number>>();
const inputSize = 100000; // Adjust input sizes as needed
beforeEach(() => {
treeMS.clear();
});
it(`Observe the time consumption of TreeMultiset.add fitting O(n log n)`, function () {
it(`Observe the time consumption of TreeMultimap.add fitting O(n log n)`, function () {
// // Create a benchmark suite
// const suite = new Benchmark.Suite();
// // Define a function to generate a random array of a given size
@ -503,7 +503,7 @@ describe('TreeMultiset Performance test', function () {
// }
// const inputArray = generateRandomArray(inputSize[0]);
//
// suite.add(`TreeMultiset addMany (n=${inputSize[0]})`, () => {
// suite.add(`TreeMultimap addMany (n=${inputSize[0]})`, () => {
// treeMS.addMany([...inputArray]);
// });
//
@ -523,7 +523,7 @@ describe('TreeMultiset Performance test', function () {
// .run({async: true});
});
it(`Observe the time consumption of TreeMultiset.dfs be good`, function () {
it(`Observe the time consumption of TreeMultimap.dfs be good`, function () {
const startDFS = performance.now();
const dfs = treeMS.dfs(node => node);
isDebug && console.log('---bfs', performance.now() - startDFS, dfs.length);