diff --git a/CHANGELOG.md b/CHANGELOG.md
index 25c0d0d..a87c552 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
+
+## [4.1.0] - 2021-04-21
+
+### Added
+- `.lowerBound(k)` to find the node with biggest key less or equal a value k.
+- `.upperBound(k)` to find the node with smallest key bigger than a value k.
+
## [4.0.1] - 2021-04-15
### Fixed
- exported AvlTreeNode path.
diff --git a/README.md b/README.md
index a09b3d8..8bcdc47 100644
--- a/README.md
+++ b/README.md
@@ -32,6 +32,8 @@ Binary Search Tree & AVL Tree (Self Balancing Tree) implementation in javascript
* [.find(key)](#findkey)
* [.min()](#min)
* [.max()](#max)
+ * [.lowerBound(k)](#lowerboundk)
+ * [.upperBound(k)](#upperboundk)
* [.root()](#root)
* [.count()](#count)
* [.traverseInOrder(cb)](#traverseinordercb)
@@ -202,6 +204,49 @@ const max = bst.max();
console.log(max.getKey()); // 90
console.log(max.getValue()); // v4
```
+
+### .lowerBound(k)
+finds the node with the biggest key less or equal a given value k.
+
+
+
+```js
+console.log(bst.lowerBound(60).getKey()); // 50
+console.log(bst.lowerBound(10)); // null
+```
+
+### .upperBound(k)
+finds the node with the smallest key bigger than a given value k.
+
+
+
+```js
+console.log(bst.upperBound(75).getKey()); // 80
+console.log(bst.upperBound(110)); // null
+```
+
### .root()
returns the root node of the tree.
diff --git a/package.json b/package.json
index b285169..db0625b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@datastructures-js/binary-search-tree",
- "version": "4.0.1",
+ "version": "4.1.0",
"description": "binary search tree & avl tree (self balancing tree) implementation in javascript",
"main": "index.js",
"scripts": {
diff --git a/src/binarySearchTree.js b/src/binarySearchTree.js
index 1970d7b..cca16b3 100644
--- a/src/binarySearchTree.js
+++ b/src/binarySearchTree.js
@@ -142,6 +142,54 @@ class BinarySearchTree {
return current;
}
+ /**
+ * Returns the node with the biggest key less or equal to k
+ * @public
+ * @param {number|string} k
+ * @return {BinarySearchTreeNode|null}
+ */
+ lowerBound(k, current = this._root) {
+ if (current === null) {
+ return null;
+ }
+
+ if (current.getKey() === k) {
+ return current;
+ }
+
+ if (current.getKey() > k) {
+ return this.lowerBound(k, current.getLeft());
+ }
+
+ if (current.hasRight() && current.getRight().getKey() <= k) {
+ return this.lowerBound(k, current.getRight());
+ }
+
+ return current;
+ }
+
+ /**
+ * Returns the node with the smallest key bigger than k
+ * @public
+ * @param {number|string} k
+ * @return {BinarySearchTreeNode|null}
+ */
+ upperBound(k, current = this._root) {
+ if (current === null) {
+ return null;
+ }
+
+ if (current.getKey() <= k) {
+ return this.upperBound(k, current.getRight());
+ }
+
+ if (current.hasLeft() && current.getLeft().getKey() > k) {
+ return this.upperBound(k, current.getLeft());
+ }
+
+ return current;
+ }
+
/**
* Returns the root node
* @public
diff --git a/test/binarySearchTree.test.js b/test/binarySearchTree.test.js
index c9b8bf2..9460da3 100644
--- a/test/binarySearchTree.test.js
+++ b/test/binarySearchTree.test.js
@@ -80,6 +80,26 @@ describe('BinarySearchTree tests', () => {
});
});
+ describe('.lowerBound(k)', () => {
+ it('gets the node with biggest key less or equal k', () => {
+ expect(bst.lowerBound(60).getKey()).to.equal(50);
+ });
+
+ it('returns null when k is less than all tree keys', () => {
+ expect(bst.lowerBound(10)).to.equal(null);
+ });
+ });
+
+ describe('.upperBound(k)', () => {
+ it('gets the node with smallest key bigger than k', () => {
+ expect(bst.upperBound(75).getKey()).to.equal(80);
+ });
+
+ it('returns null when k is bigger than all tree keys', () => {
+ expect(bst.upperBound(110)).to.equal(null);
+ });
+ });
+
describe('.traverseInOrder(cb)', () => {
it('traverse the tree in-order', () => {
const keys = [];