=d*3!}o&SD8`oq|@_xf+16A
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 {
+ return new Array(h)
+ .fill(null)
+ .map(() => {
+ return new Array(w).fill(filler);
+ });
+};
+
+/**
+ * Calculates the energy of a pixel.
+ * @param {?PixelColor} left
+ * @param {PixelColor} middle
+ * @param {?PixelColor} right
+ * @returns {number}
+ */
+const getPixelEnergy = (left, middle, right) => {
+ // Middle pixel is the pixel we're calculating the energy for.
+ const [mR, mG, mB] = middle;
+
+ // Energy from the left pixel (if it exists).
+ let lEnergy = 0;
+ if (left) {
+ const [lR, lG, lB] = left;
+ lEnergy = (lR - mR) ** 2 + (lG - mG) ** 2 + (lB - mB) ** 2;
+ }
+
+ // Energy from the right pixel (if it exists).
+ let rEnergy = 0;
+ if (right) {
+ const [rR, rG, rB] = right;
+ rEnergy = (rR - mR) ** 2 + (rG - mG) ** 2 + (rB - mB) ** 2;
+ }
+
+ // Resulting pixel energy.
+ return Math.sqrt(lEnergy + rEnergy);
+};
+
+/**
+ * Calculates the energy of each pixel of the image.
+ * @param {ImageData} img
+ * @param {ImageSize} size
+ * @returns {EnergyMap}
+ */
+const calculateEnergyMap = (img, { w, h }) => {
+ // Create an empty energy map where each pixel has infinitely high energy.
+ // We will update the energy of each pixel.
+ const energyMap = matrix(w, h, Infinity);
+ for (let y = 0; y < h; y += 1) {
+ for (let x = 0; x < w; x += 1) {
+ // Left pixel might not exist if we're on the very left edge of the image.
+ const left = (x - 1) >= 0 ? getPixel(img, { x: x - 1, y }) : null;
+ // The color of the middle pixel that we're calculating the energy for.
+ const middle = getPixel(img, { x, y });
+ // Right pixel might not exist if we're on the very right edge of the image.
+ const right = (x + 1) < w ? getPixel(img, { x: x + 1, y }) : null;
+ energyMap[y][x] = getPixelEnergy(left, middle, right);
+ }
+ }
+ return energyMap;
+};
+
+/**
+ * Finds the seam (the sequence of pixels from top to bottom) that has the
+ * lowest resulting energy using the Dynamic Programming approach.
+ * @param {EnergyMap} energyMap
+ * @param {ImageSize} size
+ * @returns {Seam}
+ */
+const findLowEnergySeam = (energyMap, { w, h }) => {
+ // The 2D array of the size of w and h, where each pixel contains the
+ // seam metadata (pixel energy, pixel coordinate and previous pixel from
+ // the lowest energy seam at this point).
+ const seamPixelsMap = matrix(w, h, null);
+
+ // Populate the first row of the map by just copying the energies
+ // from the energy map.
+ for (let x = 0; x < w; x += 1) {
+ const y = 0;
+ seamPixelsMap[y][x] = {
+ energy: energyMap[y][x],
+ coordinate: { x, y },
+ previous: null,
+ };
+ }
+
+ // Populate the rest of the rows.
+ for (let y = 1; y < h; y += 1) {
+ for (let x = 0; x < w; x += 1) {
+ // Find the top adjacent cell with minimum energy.
+ // This cell would be the tail of a seam with lowest energy at this point.
+ // It doesn't mean that this seam (path) has lowest energy globally.
+ // Instead, it means that we found a path with the lowest energy that may lead
+ // us to the current pixel with the coordinates x and y.
+ let minPrevEnergy = Infinity;
+ let minPrevX = x;
+ for (let i = (x - 1); i <= (x + 1); i += 1) {
+ if (i >= 0 && i < w && seamPixelsMap[y - 1][i].energy < minPrevEnergy) {
+ minPrevEnergy = seamPixelsMap[y - 1][i].energy;
+ minPrevX = i;
+ }
+ }
+
+ // Update the current cell.
+ seamPixelsMap[y][x] = {
+ energy: minPrevEnergy + energyMap[y][x],
+ coordinate: { x, y },
+ previous: { x: minPrevX, y: y - 1 },
+ };
+ }
+ }
+
+ // Find where the minimum energy seam ends.
+ // We need to find the tail of the lowest energy seam to start
+ // traversing it from its tail to its head (from the bottom to the top).
+ let lastMinCoordinate = null;
+ let minSeamEnergy = Infinity;
+ for (let x = 0; x < w; x += 1) {
+ const y = h - 1;
+ if (seamPixelsMap[y][x].energy < minSeamEnergy) {
+ minSeamEnergy = seamPixelsMap[y][x].energy;
+ lastMinCoordinate = { x, y };
+ }
+ }
+
+ // Find the lowest energy energy seam.
+ // Once we know where the tail is we may traverse and assemble the lowest
+ // energy seam based on the "previous" value of the seam pixel metadata.
+ const seam = [];
+
+ const { x: lastMinX, y: lastMinY } = lastMinCoordinate;
+
+ // Adding new pixel to the seam path one by one until we reach the top.
+ let currentSeam = seamPixelsMap[lastMinY][lastMinX];
+ while (currentSeam) {
+ seam.push(currentSeam.coordinate);
+ const prevMinCoordinates = currentSeam.previous;
+ if (!prevMinCoordinates) {
+ currentSeam = null;
+ } else {
+ const { x: prevMinX, y: prevMinY } = prevMinCoordinates;
+ currentSeam = seamPixelsMap[prevMinY][prevMinX];
+ }
+ }
+
+ return seam;
+};
+
+/**
+ * Deletes the seam from the image data.
+ * We delete the pixel in each row and then shift the rest of the row pixels to the left.
+ * @param {ImageData} img
+ * @param {Seam} seam
+ * @param {ImageSize} size
+ */
+const deleteSeam = (img, seam, { w }) => {
+ seam.forEach(({ x: seamX, y: seamY }) => {
+ for (let x = seamX; x < (w - 1); x += 1) {
+ const nextPixel = getPixel(img, { x: x + 1, y: seamY });
+ setPixel(img, { x, y: seamY }, nextPixel);
+ }
+ });
+};
+
+/**
+ * Performs the content-aware image width resizing using the seam carving method.
+ * @param {ResizeImageWidthArgs} args
+ * @returns {ResizeImageWidthResult}
+ */
+const resizeImageWidth = ({ img, toWidth }) => {
+ /**
+ * For performance reasons we want to avoid changing the img data array size.
+ * Instead we'll just keep the record of the resized image width and height separately.
+ * @type {ImageSize}
+ */
+ const size = { w: img.width, h: img.height };
+
+ // Calculating the number of pixels to remove.
+ const pxToRemove = img.width - toWidth;
+
+ let energyMap = null;
+ let seam = null;
+
+ // Removing the lowest energy seams one by one.
+ for (let i = 0; i < pxToRemove; i += 1) {
+ // 1. Calculate the energy map for the current version of the image.
+ energyMap = calculateEnergyMap(img, size);
+
+ // 2. Find the seam with the lowest energy based on the energy map.
+ seam = findLowEnergySeam(energyMap, size);
+
+ // 3. Delete the seam with the lowest energy seam from the image.
+ deleteSeam(img, seam, size);
+
+ // Reduce the image width, and continue iterations.
+ size.w -= 1;
+ }
+
+ // Returning the resized image and its final size.
+ // The img is actually a reference to the ImageData, so technically
+ // the caller of the function already has this pointer. But let's
+ // still return it for better code readability.
+ return { img, size };
+};
+
+export default resizeImageWidth;
diff --git a/src/algorithms/image-processing/utils/imageData.js b/src/algorithms/image-processing/utils/imageData.js
new file mode 100644
index 0000000000..de397b8ead
--- /dev/null
+++ b/src/algorithms/image-processing/utils/imageData.js
@@ -0,0 +1,39 @@
+/**
+ * @typedef {ArrayLike | Uint8ClampedArray} PixelColor
+ */
+
+/**
+ * @typedef {Object} PixelCoordinate
+ * @property {number} x - horizontal coordinate.
+ * @property {number} y - vertical coordinate.
+ */
+
+/**
+ * Helper function that returns the color of the pixel.
+ * @param {ImageData} img
+ * @param {PixelCoordinate} coordinate
+ * @returns {PixelColor}
+ */
+export const getPixel = (img, { x, y }) => {
+ // The ImageData data array is a flat 1D array.
+ // Thus we need to convert x and y coordinates to the linear index.
+ const i = y * img.width + x;
+ const cellsPerColor = 4; // RGBA
+ // For better efficiency, instead of creating a new sub-array we return
+ // a pointer to the part of the ImageData array.
+ return img.data.subarray(i * cellsPerColor, i * cellsPerColor + cellsPerColor);
+};
+
+/**
+ * Helper function that sets the color of the pixel.
+ * @param {ImageData} img
+ * @param {PixelCoordinate} coordinate
+ * @param {PixelColor} color
+ */
+export const setPixel = (img, { x, y }, color) => {
+ // The ImageData data array is a flat 1D array.
+ // Thus we need to convert x and y coordinates to the linear index.
+ const i = y * img.width + x;
+ const cellsPerColor = 4; // RGBA
+ img.data.set(color, i * cellsPerColor);
+};
From cfd9a630ff8cacd17880b16b27f32781eaac6bb7 Mon Sep 17 00:00:00 2001
From: Oleksii Trekhleb
Date: Wed, 21 Apr 2021 07:39:58 +0200
Subject: [PATCH 102/285] Test that two images are identical for the Seam
Carving algorithm. (#694)
* Test that two images are identical for the Seam Carving algorithm.
* Tune the Seam Carving tests.
* Tune the Seam Carving tests.
* Tune the Seam Carving tests.
* Tune the Seam Carving tests.
---
.husky/pre-commit | 1 +
.../__tests__/resizeImageWidth.test.js | 44 ++++++++++++++++++-
2 files changed, 43 insertions(+), 2 deletions(-)
diff --git a/.husky/pre-commit b/.husky/pre-commit
index bec1c08a1a..a29a4166ea 100755
--- a/.husky/pre-commit
+++ b/.husky/pre-commit
@@ -1,5 +1,6 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
+# @TODO: Implement the pre-commit checks.
# npm run lint
# npm run test
diff --git a/src/algorithms/image-processing/seam-carving/__tests__/resizeImageWidth.test.js b/src/algorithms/image-processing/seam-carving/__tests__/resizeImageWidth.test.js
index b6400a3522..9afed97123 100644
--- a/src/algorithms/image-processing/seam-carving/__tests__/resizeImageWidth.test.js
+++ b/src/algorithms/image-processing/seam-carving/__tests__/resizeImageWidth.test.js
@@ -4,6 +4,40 @@ import resizeImageWidth from '../resizeImageWidth';
const testImageBeforePath = './src/algorithms/image-processing/seam-carving/__tests__/test-image-before.jpg';
const testImageAfterPath = './src/algorithms/image-processing/seam-carving/__tests__/test-image-after.jpg';
+/**
+ * Compares two images and finds the number of different pixels.
+ *
+ * @param {ImageData} imgA - ImageData for the first image.
+ * @param {ImageData} imgB - ImageData for the second image.
+ * @param {number} threshold - Color difference threshold [0..255]. Smaller - stricter.
+ * @returns {number} - Number of different pixels.
+ */
+function pixelsDiff(imgA, imgB, threshold = 0) {
+ if (imgA.width !== imgB.width || imgA.height !== imgB.height) {
+ throw new Error('Images must have the same size');
+ }
+
+ let differentPixels = 0;
+ const numColorParams = 4; // RGBA
+
+ for (let pixelIndex = 0; pixelIndex < imgA.data.length; pixelIndex += numColorParams) {
+ // Get pixel's color for each image.
+ const [aR, aG, aB] = imgA.data.subarray(pixelIndex, pixelIndex + numColorParams);
+ const [bR, bG, bB] = imgB.data.subarray(pixelIndex, pixelIndex + numColorParams);
+
+ // Get average pixel's color for each image (make them greyscale).
+ const aAvgColor = Math.floor((aR + aG + aB) / 3);
+ const bAvgColor = Math.floor((bR + bG + bB) / 3);
+
+ // Compare pixel colors.
+ if (Math.abs(aAvgColor - bAvgColor) > threshold) {
+ differentPixels += 1;
+ }
+ }
+
+ return differentPixels;
+}
+
describe('resizeImageWidth', () => {
it('should perform content-aware image width reduction', () => {
// @see: https://jestjs.io/docs/asynchronous
@@ -21,6 +55,7 @@ describe('resizeImageWidth', () => {
const canvasAfter = createCanvas(imgAfter.width, imgAfter.height);
const ctxAfter = canvasAfter.getContext('2d');
ctxAfter.drawImage(imgAfter, 0, 0, imgAfter.width, imgAfter.height);
+ const imgDataAfter = ctxAfter.getImageData(0, 0, imgAfter.width, imgAfter.height);
const toWidth = Math.floor(imgBefore.width / 2);
@@ -44,8 +79,13 @@ describe('resizeImageWidth', () => {
expect(imgDataTest.width).toBe(imgAfter.width);
expect(imgDataTest.height).toBe(imgAfter.height);
- // @TODO: Check that images are identical.
- // expect(canvasTest.toDataURL()).toEqual(canvasAfter.toDataURL());
+ const colorThreshold = 50;
+ const differentPixels = pixelsDiff(imgDataTest, imgDataAfter, colorThreshold);
+
+ // Allow 10% of pixels to be different
+ const pixelsThreshold = Math.floor((imgAfter.width * imgAfter.height) / 10);
+
+ expect(differentPixels).toBeLessThanOrEqual(pixelsThreshold);
});
});
});
From 144b6867761a064bfe766c0c1994ebd1be676e74 Mon Sep 17 00:00:00 2001
From: Oleksii Trekhleb
Date: Wed, 21 Apr 2021 16:55:26 +0200
Subject: [PATCH 103/285] Testing Husky integration
---
.husky/pre-commit | 5 ++---
.npmrc | 1 +
package.json | 5 ++++-
3 files changed, 7 insertions(+), 4 deletions(-)
create mode 100644 .npmrc
diff --git a/.husky/pre-commit b/.husky/pre-commit
index a29a4166ea..660b820968 100755
--- a/.husky/pre-commit
+++ b/.husky/pre-commit
@@ -1,6 +1,5 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
-# @TODO: Implement the pre-commit checks.
-# npm run lint
-# npm run test
+npm run lint
+npm run test
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 0000000000..c0c80ba447
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1 @@
+engine-strict=false
diff --git a/package.json b/package.json
index c4ae69b6fd..f77d87ff50 100644
--- a/package.json
+++ b/package.json
@@ -48,5 +48,8 @@
"husky": "6.0.0",
"jest": "26.6.3"
},
- "dependencies": {}
+ "engines": {
+ "node": ">=12.0.0",
+ "npm": ">=6.9.0"
+ }
}
From f7d07ae66d0fbd2c9b093bb074c8cb02de7be4b8 Mon Sep 17 00:00:00 2001
From: Oleksii Trekhleb
Date: Wed, 21 Apr 2021 17:09:59 +0200
Subject: [PATCH 104/285] Testing Husky integration
---
.husky/pre-commit | 1 +
1 file changed, 1 insertion(+)
diff --git a/.husky/pre-commit b/.husky/pre-commit
index 660b820968..4c19307277 100755
--- a/.husky/pre-commit
+++ b/.husky/pre-commit
@@ -1,5 +1,6 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
+# Testing Husky.
npm run lint
npm run test
From 4ca41ea83b8fdbfe2eb056c8b89852466a840a29 Mon Sep 17 00:00:00 2001
From: Oleksii Trekhleb
Date: Wed, 21 Apr 2021 17:12:53 +0200
Subject: [PATCH 105/285] Testing Husky integration
---
.husky/pre-commit | 1 -
1 file changed, 1 deletion(-)
diff --git a/.husky/pre-commit b/.husky/pre-commit
index 4c19307277..660b820968 100755
--- a/.husky/pre-commit
+++ b/.husky/pre-commit
@@ -1,6 +1,5 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
-# Testing Husky.
npm run lint
npm run test
From 912941be1d42d19a0a8b5ded73b35deee8e05718 Mon Sep 17 00:00:00 2001
From: Oleksii Trekhleb
Date: Wed, 21 Apr 2021 17:30:49 +0200
Subject: [PATCH 106/285] Add troubleshooting instructions.
---
README.md | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/README.md b/README.md
index 71b0798fbe..a9fc7b5ea0 100644
--- a/README.md
+++ b/README.md
@@ -236,6 +236,7 @@ tree is being used.
## How to use this repository
**Install all dependencies**
+
```
npm install
```
@@ -249,15 +250,26 @@ npm run lint
```
**Run all tests**
+
```
npm test
```
**Run tests by name**
+
```
npm test -- 'LinkedList'
```
+**Troubleshooting**
+
+In case if linting or testing is failing try to delete the `node_modules` folder and re-install npm packages:
+
+```
+rm -rf ./node_modules
+npm i
+```
+
**Playground**
You may play with data-structures and algorithms in `./src/playground/playground.js` file and write
From 7ad3fbc0f9eebfc4e86623be94e7c3dfbe9e611d Mon Sep 17 00:00:00 2001
From: Oleksii Trekhleb
Date: Wed, 21 Apr 2021 18:09:48 +0200
Subject: [PATCH 107/285] Disabling tests in pre-commit to speed up the
commits.
---
.husky/pre-commit | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.husky/pre-commit b/.husky/pre-commit
index 660b820968..598a5dceaa 100755
--- a/.husky/pre-commit
+++ b/.husky/pre-commit
@@ -2,4 +2,4 @@
. "$(dirname "$0")/_/husky.sh"
npm run lint
-npm run test
+# npm run test
From d38cecd2e79d64efba1dd0b37cdd9acd60bc42ba Mon Sep 17 00:00:00 2001
From: Coco Guerra
Date: Wed, 5 May 2021 22:43:28 -0600
Subject: [PATCH 108/285] Update README.es-ES.md (#704)
* Update README.es-ES.md
* Update README.es-ES.md
---
.../linked-list/README.es-ES.md | 41 +++++++++----------
1 file changed, 20 insertions(+), 21 deletions(-)
diff --git a/src/data-structures/linked-list/README.es-ES.md b/src/data-structures/linked-list/README.es-ES.md
index 978e234ddf..58eb2b860d 100644
--- a/src/data-structures/linked-list/README.es-ES.md
+++ b/src/data-structures/linked-list/README.es-ES.md
@@ -7,27 +7,26 @@ _Lee esto en otros idiomas:_
[_Português_](README.pt-BR.md)
[_English_](README.md)
-En ciencias de la computaciòn una **lista enlazada** es una coleccion linear
+En ciencias de la computación una **lista enlazada** es una colección linear
de elemntos de datos, en los cuales el orden linear no es dado por
-su posciòn fisica en memoria. En cambio, cada
-elemento señala al siguiente. Es una estructura de datos
+su posción física en memoria. En cambio, cada
+elemento señala al siguiente. Es una estructura de datos
que consiste en un grupo de nodos los cuales juntos representan
-una secuencia. Bajo la forma mas simple, cada nodo es
-compuesto de datos y una referencia (en otras palabras,
+una secuencia. Bajo la forma más simple, cada nodo es
+compuesto de datos y una referencia (en otras palabras,
un lazo) al siguiente nodo en la secuencia. Esta estructura
-permite la insercion o remocion de elementos
-desde cualquier posicion en la secuencia durante la iteracion.
-Variantes mas complejas agregan lazos adicionales, permitiendo
-una eficiente insercion o remocion desde referencias arbitrarias
+permite la inserción o remoción de elementos
+desde cualquier posición en la secuencia durante la iteración.
+Variantes más complejas agregan lazos adicionales, permitiendo
+una eficiente inserción o remoción desde referencias arbitrarias
del elemento. Una desventaja de las listas lazadas es que el tiempo de
-acceso es linear (y dificil de canalizar) Un acceso
-mas rapido, como un acceso aleatorio, no es factible. Los arreglos
+acceso es linear (y difícil de canalizar). Un acceso
+más rápido, como un acceso aleatorio, no es factible. Los arreglos
tienen una mejor locazion comparados con las listas lazadas.
-

-## Pseudocodigo para operacones basicas
+## Pseudocódigo para operacones básicas
### Insertar
@@ -76,7 +75,7 @@ Contains(head, value)
return true
end Contains
```
-
+
### Borrar
```text
@@ -146,19 +145,19 @@ ReverseTraversal(head, tail)
end ReverseTraversal
```
-## Complexities
+## Complejidades
-### Time Complexity
+### Complejidad del Tiempo
-| Access | Search | Insertion | Deletion |
-| :-------: | :-------: | :-------: | :-------: |
-| O(n) | O(n) | O(1) | O(n) |
+| Access | Search | Insertion | Deletion |
+| :----: | :----: | :-------: | :------: |
+| O(n) | O(n) | O(1) | O(n) |
-### Space Complexity
+### Complejidad Espacial
O(n)
-## References
+## Referencias
- [Wikipedia](https://en.wikipedia.org/wiki/Linked_list)
- [YouTube](https://www.youtube.com/watch?v=njTh_OwMljA&index=2&t=1s&list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8)
From 64abcf12f28e02580b28cc8b64bab5ff0ac9c037 Mon Sep 17 00:00:00 2001
From: Deniz Binay <69312106+denizbinay@users.noreply.github.com>
Date: Thu, 6 May 2021 06:46:04 +0200
Subject: [PATCH 109/285] add german translation for main readme (#703)
---
README.ar-AR.md | 3 +-
README.de-DE.md | 333 ++++++++++++++++++++++++++++++++++++++++++++++++
README.es-ES.md | 3 +-
README.fr-FR.md | 3 +-
README.id-ID.md | 3 +-
README.it-IT.md | 3 +-
README.ja-JP.md | 3 +-
README.ko-KR.md | 3 +-
README.md | 3 +-
README.pl-PL.md | 3 +-
README.pt-BR.md | 3 +-
README.ru-RU.md | 3 +-
README.tr-TR.md | 3 +-
README.uk-UA.md | 3 +-
README.zh-CN.md | 3 +-
README.zh-TW.md | 3 +-
16 files changed, 363 insertions(+), 15 deletions(-)
create mode 100644 README.de-DE.md
diff --git a/README.ar-AR.md b/README.ar-AR.md
index 378334fab0..797006b6ef 100644
--- a/README.ar-AR.md
+++ b/README.ar-AR.md
@@ -21,7 +21,8 @@ _اقرأ هذا في لغات أخرى:_
[_Português_](README.pt-BR.md),
[_Русский_](README.ru-RU.md),
[_Türk_](README.tr-TR.md),
-[_Italiana_](README.it-IT.md)
+[_Italiana_](README.it-IT.md),
+[_Deutsch_](README.de-DE.md)
☝ ملاحضة هذا المشروع مخصص للاستخدام لأغراض التعلم والبحث
فقط ، و ** ليست ** معدة للاستخدام في **الإنتاج**
diff --git a/README.de-DE.md b/README.de-DE.md
new file mode 100644
index 0000000000..3e127c3ea0
--- /dev/null
+++ b/README.de-DE.md
@@ -0,0 +1,333 @@
+# JavaScript-Algorithmen und Datenstrukturen
+
+[](https://github.com/trekhleb/javascript-algorithms/actions?query=workflow%3ACI+branch%3Amaster)
+[](https://codecov.io/gh/trekhleb/javascript-algorithms)
+
+Dieses Repository enthält JavaScript Beispiele für viele
+gängige Algorithmen und Datenstrukturen.
+
+Jeder Algorithmus und jede Datenstruktur hat eine eigene README
+mit zugehörigen Erklärungen und weiterführenden Links (einschließlich zu YouTube-Videos).
+
+_Lies dies in anderen Sprachen:_
+[_English_](https://github.com/trekhleb/javascript-algorithms/)
+[_简体中文_](README.zh-CN.md),
+[_繁體中文_](README.zh-TW.md),
+[_한국어_](README.ko-KR.md),
+[_日本語_](README.ja-JP.md),
+[_Polski_](README.pl-PL.md),
+[_Français_](README.fr-FR.md),
+[_Español_](README.es-ES.md),
+[_Português_](README.pt-BR.md),
+[_Русский_](README.ru-RU.md),
+[_Türk_](README.tr-TR.md),
+[_Italiana_](README.it-IT.md),
+[_Bahasa Indonesia_](README.id-ID.md),
+[_Українська_](README.uk-UA.md),
+[_Arabic_](README.ar-AR.md)
+
+_☝ Beachte, dass dieses Projekt nur für Lern- und Forschungszwecke gedacht ist und **nicht** für den produktiven Einsatz verwendet werden soll_
+
+## Datenstrukturen
+
+Eine Datenstruktur ist eine bestimmte Art und Weise, Daten in einem Computer so zu organisieren und zu speichern, dass sie
+effizient erreicht und verändert werden können. Genauer gesagt, ist eine Datenstruktur eine Sammlung von Werten,
+den Beziehungen zwischen ihnen und den Funktionen oder Operationen, die auf die Daten angewendet werden können.
+
+`B` - Anfänger:innen, `A` - Fortgeschrittene
+
+* `B` [Verkettete Liste (Linked List)](src/data-structures/linked-list)
+* `B` [Doppelt verkettete Liste (Doubly Linked List)](src/data-structures/doubly-linked-list)
+* `B` [Warteschlange (Queue)](src/data-structures/queue)
+* `B` [Stapelspeicher (Stack)](src/data-structures/stack)
+* `B` [Hashtabelle (Hash Table)](src/data-structures/hash-table)
+* `B` [Heap-Algorithmus (Heap)](src/data-structures/heap) - max und min Heap-Versionen
+* `B` [Vorrangwarteschlange (Priority Queue)](src/data-structures/priority-queue)
+* `A` [Trie (Trie)](src/data-structures/trie)
+* `A` [Baum (Tree)](src/data-structures/tree)
+ * `A` [Binärer Suchbaum (Binary Search Tree)](src/data-structures/tree/binary-search-tree)
+ * `A` [AVL-Baum (AVL Tree)](src/data-structures/tree/avl-tree)
+ * `A` [Rot-Schwarz-Baum (Red-Black Tree)](src/data-structures/tree/red-black-tree)
+ * `A` [Segment-Baum (Segment Tree)](src/data-structures/tree/segment-tree) - mit Min/Max/Summenbereich-Abfrage Beispiel
+ * `A` [Fenwick Baum (Fenwick Tree)](src/data-structures/tree/fenwick-tree) (Binär indizierter Baum / Binary Indexed Tree)
+* `A` [Graph (Graph)](src/data-structures/graph) (sowohl gerichtet als auch ungerichtet)
+* `A` [Union-Find-Struktur (Disjoint Set)](src/data-structures/disjoint-set)
+* `A` [Bloomfilter (Bloom Filter)](src/data-structures/bloom-filter)
+
+## Algorithmen
+
+Ein Algorithmus ist eine eindeutige Spezifikation, wie eine Klasse von Problemen zu lösen ist. Er besteht
+aus einem Satz von Regeln, die eine Abfolge von Operationen genau definieren.
+
+`B` - Anfänger:innen, `A` - Fortgeschrittene
+
+### Algorithmen nach Thema
+
+* **Mathe**
+ * `B` [Bitmanipulation (Bit Manipulation)](src/algorithms/math/bits) - Bits setzen/lesen/aktualisieren/löschen, Multiplikation/Division durch zwei negieren usw..
+ * `B` [Faktoriell (Factorial)](src/algorithms/math/factorial)
+ * `B` [Fibonacci-Zahl (Fibonacci Number)](src/algorithms/math/fibonacci) - Klassische und geschlossene Version
+ * `B` [Primfaktoren (Prime Factors)](src/algorithms/math/prime-factors) - Auffinden von Primfaktoren und deren Zählung mit Hilfe des Satz von Hardy-Ramanujan (Hardy-Ramanujan's theorem)
+ * `B` [Primzahl-Test (Primality Test)](src/algorithms/math/primality-test) (Probedivision / trial division method)
+ * `B` [Euklidischer Algorithmus (Euclidean Algorithm)](src/algorithms/math/euclidean-algorithm) - Berechnen des größten gemeinsamen Teilers (ggT)
+ * `B` [Kleinstes gemeinsames Vielfaches (Least Common Multiple)](src/algorithms/math/least-common-multiple) (kgV)
+ * `B` [Sieb des Eratosthenes (Sieve of Eratosthenes)](src/algorithms/math/sieve-of-eratosthenes) - Finden aller Primzahlen bis zu einer bestimmten Grenze
+ * `B` [Power of two (Is Power of Two)](src/algorithms/math/is-power-of-two) - Prüft, ob die Zahl eine Zweierpotenz ist (naive und bitweise Algorithmen)
+ * `B` [Pascalsches Dreieck (Pascal's Triangle)](src/algorithms/math/pascal-triangle)
+ * `B` [Komplexe Zahlen (Complex Number)](src/algorithms/math/complex-number) - Komplexe Zahlen und Grundoperationen mit ihnen
+ * `B` [Bogenmaß & Grad (Radian & Degree)](src/algorithms/math/radian) - Umrechnung von Bogenmaß in Grad und zurück
+ * `B` [Fast Powering Algorithmus (Fast Powering)](src/algorithms/math/fast-powering)
+ * `B` [Horner-Schema (Horner's method)](src/algorithms/math/horner-method) - Polynomauswertung
+ * `B` [Matrizen (Matrices)](src/algorithms/math/matrix) - Matrizen und grundlegende Matrixoperationen (Multiplikation, Transposition usw.)
+ * `B` [Euklidischer Abstand (Euclidean Distance)](src/algorithms/math/euclidean-distance) - Abstand zwischen zwei Punkten/Vektoren/Matrizen
+ * `A` [Ganzzahlige Partitionierung (Integer Partition)](src/algorithms/math/integer-partition)
+ * `A` [Quadratwurzel (Square Root)](src/algorithms/math/square-root) - Newtonverfahren (Newton's method)
+ * `A` [Liu Hui π Algorithmus (Liu Hui π Algorithm)](src/algorithms/math/liu-hui) - Näherungsweise π-Berechnungen auf Basis von N-gons
+ * `A` [Diskrete Fourier-Transformation (Discrete Fourier Transform)](src/algorithms/math/fourier-transform) - Eine Funktion der Zeit (ein Signal) in die Frequenzen zerlegen, aus denen sie sich zusammensetzt
+* **Sets**
+ * `B` [Kartesisches Produkt (Cartesian Product)](src/algorithms/sets/cartesian-product) - Produkt aus mehreren Mengen
+ * `B` [Fisher-Yates-Verfahren (Fisher–Yates Shuffle)](src/algorithms/sets/fisher-yates) - Zufällige Permutation einer endlichen Folge
+ * `A` [Potenzmenge (Power Set)](src/algorithms/sets/power-set) - Alle Teilmengen einer Menge (Bitweise und Rücksetzverfahren Lösungen(backtracking solutions))
+ * `A` [Permutation (Permutations)](src/algorithms/sets/permutations) (mit und ohne Wiederholungen)
+ * `A` [Kombination (Combinations)](src/algorithms/sets/combinations) (mit und ohne Wiederholungen)
+ * `A` [Problem der längsten gemeinsamen Teilsequenz (Longest Common Subsequence)](src/algorithms/sets/longest-common-subsequence) (LCS)
+ * `A` [Längste gemeinsame Teilsequenz (Longest Increasing Subsequence)](src/algorithms/sets/longest-increasing-subsequence)
+ * `A` [Der kürzeste gemeinsame String (Shortest Common Supersequence)](src/algorithms/sets/shortest-common-supersequence) (SCS)
+ * `A` [Rucksackproblem (Knapsack Problem)](src/algorithms/sets/knapsack-problem) - "0/1" und "Ungebunden"
+ * `A` [Das Maximum-Subarray Problem (Maximum Subarray)](src/algorithms/sets/maximum-subarray) - "Brute-Force-Methode" und "Dynamische Programmierung" (Kadane' Algorithmus)
+ * `A` [Kombinationssumme (Combination Sum)](src/algorithms/sets/combination-sum) - Alle Kombinationen finden, die eine bestimmte Summe bilden
+* **Zeichenketten (Strings)**
+ * `B` [Hamming-Abstand (Hamming Distance)](src/algorithms/string/hamming-distance) - Anzahl der Positionen, an denen die Symbole unterschiedlich sind
+ * `A` [Levenshtein-Distanz (Levenshtein Distance)](src/algorithms/string/levenshtein-distance) - Minimaler Editierabstand zwischen zwei Sequenzen
+ * `A` [Knuth-Morris-Pratt-Algorithmus (Knuth–Morris–Pratt Algorithm)](src/algorithms/string/knuth-morris-pratt) (KMP Algorithmus) - Teilstringsuche (Mustervergleich / Pattern Matching)
+ * `A` [Z-Algorithmus (Z Algorithm)](src/algorithms/string/z-algorithm) - Teilstringsuche (Mustervergleich / Pattern Matching)
+ * `A` [Rabin-Karp-Algorithmus (Rabin Karp Algorithm)](src/algorithms/string/rabin-karp) - Teilstringsuche
+ * `A` [Längstes häufiges Teilzeichenfolgenproblem (Longest Common Substring)](src/algorithms/string/longest-common-substring)
+ * `A` [Regulärer Ausdruck (Regular Expression Matching)](src/algorithms/string/regular-expression-matching)
+* **Suchen**
+ * `B` [Lineare Suche (Linear Search)](src/algorithms/search/linear-search)
+ * `B` [Sprungsuche (Jump Search)](src/algorithms/search/jump-search) (oder Blocksuche) - Suche im sortierten Array
+ * `B` [Binäre Suche (Binary Search)](src/algorithms/search/binary-search) - Suche in einem sortierten Array
+ * `B` [Interpolationssuche (Interpolation Search)](src/algorithms/search/interpolation-search) - Suche in gleichmäßig verteilt sortiertem Array
+* **Sortieren**
+ * `B` [Bubblesort (Bubble Sort)](src/algorithms/sorting/bubble-sort)
+ * `B` [Selectionsort (Selection Sort)](src/algorithms/sorting/selection-sort)
+ * `B` [Einfügesortierenmethode (Insertion Sort)](src/algorithms/sorting/insertion-sort)
+ * `B` [Haldensortierung (Heap Sort)](src/algorithms/sorting/heap-sort)
+ * `B` [Mergesort (Merge Sort)](src/algorithms/sorting/merge-sort)
+ * `B` [Quicksort (Quicksort)](src/algorithms/sorting/quick-sort) - in-place und non-in-place Implementierungen
+ * `B` [Shellsort (Shellsort)](src/algorithms/sorting/shell-sort)
+ * `B` [Countingsort (Counting Sort)](src/algorithms/sorting/counting-sort)
+ * `B` [Fachverteilen (Radix Sort)](src/algorithms/sorting/radix-sort)
+* **Verkettete Liste (Linked List)**
+ * `B` [Gerade Traversierung (Straight Traversal)](src/algorithms/linked-list/traversal)
+ * `B` [Umgekehrte Traversierung (Reverse Traversal)](src/algorithms/linked-list/reverse-traversal)
+* **Bäume**
+ * `B` [Tiefensuche (Depth-First Search)](src/algorithms/tree/depth-first-search) (DFS)
+ * `B` [Breitensuche (Breadth-First Search)](src/algorithms/tree/breadth-first-search) (BFS)
+* **Graphen**
+ * `B` [Tiefensuche (Depth-First Search)](src/algorithms/graph/depth-first-search) (DFS)
+ * `B` [Breitensuche (Breadth-First Search)](src/algorithms/graph/breadth-first-search) (BFS)
+ * `B` [Algorithmus von Kruskal (Kruskal’s Algorithm)](src/algorithms/graph/kruskal) - Finden des Spannbaum (Minimum Spanning Tree / MST) für einen gewichteten ungerichteten Graphen
+ * `A` [Dijkstra-Algorithmus (Dijkstra Algorithm)](src/algorithms/graph/dijkstra) - Finden der kürzesten Wege zu allen Knoten des Graphen von einem einzelnen Knotenpunkt aus
+ * `A` [Bellman-Ford-Algorithmus (Bellman-Ford Algorithm)](src/algorithms/graph/bellman-ford) - Finden der kürzesten Wege zu allen Knoten des Graphen von einem einzelnen Knotenpunkt aus
+ * `A` [Algorithmus von Floyd und Warshall (Floyd-Warshall Algorithm)](src/algorithms/graph/floyd-warshall) - Die kürzesten Wege zwischen allen Knotenpaaren finden
+ * `A` [Zykluserkennung (Detect Cycle)](src/algorithms/graph/detect-cycle) - Sowohl für gerichtete als auch für ungerichtete Graphen (DFS- und Disjoint-Set-basierte Versionen)
+ * `A` [Algorithmus von Prim (Prim’s Algorithm)](src/algorithms/graph/prim) - Finden des Spannbaums (Minimum Spanning Tree / MST) für einen gewichteten ungerichteten Graphen
+ * `A` [Topologische Sortierung (Topological Sorting)](src/algorithms/graph/topological-sorting) - DFS-Verfahren
+ * `A` [Artikulationspunkte (Articulation Points)](src/algorithms/graph/articulation-points) - Algorithmus von Tarjan (Tarjan's algorithm) (DFS basiert)
+ * `A` [Brücke (Bridges)](src/algorithms/graph/bridges) - DFS-basierter Algorithmus
+ * `A` [Eulerkreisproblem (Eulerian Path and Eulerian Circuit)](src/algorithms/graph/eulerian-path) - Algorithmus von Fleury (Fleury's algorithm) - Jede Kante genau einmal durchlaufen.
+ * `A` [Hamiltonkreisproblem (Hamiltonian Cycle)](src/algorithms/graph/hamiltonian-cycle) - Jeden Eckpunkt genau einmal durchlaufen.
+ * `A` [Starke Zusammenhangskomponente (Strongly Connected Components)](src/algorithms/graph/strongly-connected-components) - Kosarajus Algorithmus
+ * `A` [Problem des Handlungsreisenden (Travelling Salesman Problem)](src/algorithms/graph/travelling-salesman) - Kürzestmögliche Route, die jede Stadt besucht und zur Ausgangsstadt zurückkehrt
+* **Kryptographie**
+ * `B` [Polynomiale Streuwertfunktion(Polynomial Hash)](src/algorithms/cryptography/polynomial-hash) - Rollierende Streuwert-Funktion basierend auf Polynom
+ * `B` [Schienenzaun Chiffre (Rail Fence Cipher)](src/algorithms/cryptography/rail-fence-cipher) - Ein Transpositionsalgorithmus zur Verschlüsselung von Nachrichten
+ * `B` [Caesar-Verschlüsselung (Caesar Cipher)](src/algorithms/cryptography/caesar-cipher) - Einfache Substitutions-Chiffre
+ * `B` [Hill-Chiffre (Hill Cipher)](src/algorithms/cryptography/hill-cipher) - Substitutionschiffre basierend auf linearer Algebra
+* **Maschinelles Lernen**
+ * `B` [Künstliches Neuron (NanoNeuron)](https://github.com/trekhleb/nano-neuron) - 7 einfache JS-Funktionen, die veranschaulichen, wie Maschinen tatsächlich lernen können (Vorwärts-/Rückwärtspropagation)
+ * `B` [Nächste-Nachbarn-Klassifikation (k-NN)](src/algorithms/ml/knn) - k-nächste-Nachbarn-Algorithmus
+ * `B` [k-Means (k-Means)](src/algorithms/ml/k-means) - k-Means-Algorithmus
+* **Image Processing**
+ * `B` [Inhaltsabhängige Bildverzerrung (Seam Carving)](src/algorithms/image-processing/seam-carving) - Algorithmus zur inhaltsabhängigen Bildgrößenänderung
+* **Unkategorisiert**
+ * `B` [Türme von Hanoi (Tower of Hanoi)](src/algorithms/uncategorized/hanoi-tower)
+ * `B` [Rotationsmatrix (Square Matrix Rotation)](src/algorithms/uncategorized/square-matrix-rotation) - In-Place-Algorithmus
+ * `B` [Jump Game (Jump Game)](src/algorithms/uncategorized/jump-game) - Backtracking, dynamische Programmierung (Top-down + Bottom-up) und gierige Beispiele
+ * `B` [Eindeutige Pfade (Unique Paths)](src/algorithms/uncategorized/unique-paths) - Backtracking, dynamische Programmierung und Pascalsches Dreieck basierte Beispiele
+ * `B` [Regenterrassen (Rain Terraces)](src/algorithms/uncategorized/rain-terraces) - Auffangproblem für Regenwasser (trapping rain water problem) (dynamische Programmierung und Brute-Force-Versionen)
+ * `B` [Rekursive Treppe (Recursive Staircase)](src/algorithms/uncategorized/recursive-staircase) - Zählen der Anzahl der Wege, die nach oben führen (4 Lösungen)
+ * `B` [Beste Zeit zum Kaufen/Verkaufen von Aktien (Best Time To Buy Sell Stocks)](src/algorithms/uncategorized/best-time-to-buy-sell-stocks) - Beispiele für "Teile und Herrsche" und Beispiele für den One-Pass-Algorithmus
+ * `A` [Damenproblem (N-Queens Problem)](src/algorithms/uncategorized/n-queens)
+ * `A` [Springerproblem (Knight's Tour)](src/algorithms/uncategorized/knight-tour)
+
+### Algorithmen nach Paradigma
+
+Ein algorithmisches Paradigma ist eine generische Methode oder ein Ansatz, der dem Entwurf einer Klasse von Algorithmen zugrunde liegt. Es ist eine Abstraktion, die höher ist als der Begriff des Algorithmus. Genauso wie ein Algorithmus eine Abstraktion ist, die höher ist als ein Computerprogramm.
+
+* **Brachiale Gewalt (Brute Force)** - schaut sich alle Möglichkeiten an und wählt die beste Lösung aus
+ * `B` [Lineare Suche (Linear Search)](src/algorithms/search/linear-search)
+ * `B` [Regenterrassen (Rain Terraces)](src/algorithms/uncategorized/rain-terraces) - Auffangproblem für Regenwasser (trapping rain water problem) (dynamische Programmierung und Brute-Force-Versionen)
+ * `B` [Rekursive Treppe (Recursive Staircase)](src/algorithms/uncategorized/recursive-staircase) - Zählen der Anzahl der Wege, die nach oben führen (4 Lösungen)
+ * `A` [Das Maximum-Subarray Problem (Maximum Subarray)](src/algorithms/sets/maximum-subarray)
+ * `A` [Problem des Handlungsreisenden (Travelling Salesman Problem)](src/algorithms/graph/travelling-salesman) - Kürzestmögliche Route, die jede Stadt besucht und zur Ausgangsstadt zurückkehrt
+ * `A` [Diskrete Fourier-Transformation (Discrete Fourier Transform)](src/algorithms/math/fourier-transform) - Eine Funktion der Zeit (ein Signal) in die Frequenzen zerlegen, aus denen sie sich zusammensetzt
+* **Gierig (Greedy)** - Wählt die beste Option zum aktuellen Zeitpunkt, ohne Rücksicht auf die Zukunft
+ * `B` [Jump Game (Jump Game)](src/algorithms/uncategorized/jump-game)
+ * `A` [Rucksackproblem (Unbound Knapsack Problem)](src/algorithms/sets/knapsack-problem)
+ * `A` [Dijkstra-Algorithmus (Dijkstra Algorithm)](src/algorithms/graph/dijkstra) - Finden der kürzesten Wege zu allen Knoten des Graphen von einem einzelnen Knotenpunkt aus
+ * `A` [Algorithmus von Prim (Prim’s Algorithm)](src/algorithms/graph/prim) - Finden des Spannbaums (Minimum Spanning Tree / MST) für einen gewichteten ungerichteten Graphen
+ * `B` [Algorithmus von Kruskal (Kruskal’s Algorithm)](src/algorithms/graph/kruskal) - Finden des Spannbaum (Minimum Spanning Tree / MST) für einen gewichteten ungerichteten Graphen
+* **Teile und herrsche** - Das Problem in kleinere Teile aufteilen und diese Teile dann lösen
+ * `B` [Binäre Suche (Binary Search)](src/algorithms/search/binary-search)
+ * `B` [Türme von Hanoi (Tower of Hanoi)](src/algorithms/uncategorized/hanoi-tower)
+ * `B` [Pascalsches Dreieck (Pascal's Triangle)](src/algorithms/math/pascal-triangle)
+ * `B` [Euklidischer Algorithmus (Euclidean Algorithm)](src/algorithms/math/euclidean-algorithm) - calculate the Greatest Common Divisor (GCD)
+ * `B` [Mergesort (Merge Sort)](src/algorithms/sorting/merge-sort)
+ * `B` [Quicksort (Quicksort)](src/algorithms/sorting/quick-sort)
+ * `B` [Tiefensuche (Depth-First Search)](src/algorithms/tree/depth-first-search) (DFS)
+ * `B` [Breitensuche (Breadth-First Search)](src/algorithms/graph/depth-first-search) (DFS)
+ * `B` [Matrizen (Matrices)](src/algorithms/math/matrix) - Matrizen und grundlegende Matrixoperationen (Multiplikation, Transposition usw.)
+ * `B` [Jump Game (Jump Game)](src/algorithms/uncategorized/jump-game)
+ * `B` [Fast Powering Algorithmus (Fast Powering)](src/algorithms/math/fast-powering)
+ * `B` [Beste Zeit zum Kaufen/Verkaufen von Aktien (Best Time To Buy Sell Stocks)](src/algorithms/uncategorized/best-time-to-buy-sell-stocks) - Beispiele für "Teile und Herrsche" und Beispiele für den One-Pass-Algorithmus
+ * `A` [Permutation (Permutations)](src/algorithms/sets/permutations) (mit und ohne Wiederholungen)
+ * `A` [Kombination (Combinations)](src/algorithms/sets/combinations) (mit und ohne Wiederholungen)
+* **Dynamische Programmierung** - Eine Lösung aus zuvor gefundenen Teillösungen aufbauen
+ * `B` [Fibonacci-Zahl (Fibonacci Number)](src/algorithms/math/fibonacci)
+ * `B` [Jump Game (Jump Game)](src/algorithms/uncategorized/jump-game)
+ * `B` [Eindeutige Pfade (Unique Paths)](src/algorithms/uncategorized/unique-paths)
+ * `B` [Regenterrassen (Rain Terraces)](src/algorithms/uncategorized/rain-terraces) - Auffangproblem für Regenwasser (trapping rain water problem) (dynamische Programmierung und Brute-Force-Versionen)
+ * `B` [Rekursive Treppe (Recursive Staircase)](src/algorithms/uncategorized/recursive-staircase) - Zählen der Anzahl der Wege, die nach oben führen (4 Lösungen)
+ * `B` [Inhaltsabhängige Bildverzerrung (Seam Carving)](src/algorithms/image-processing/seam-carving) - Algorithmus zur inhaltsabhängigen Bildgrößenänderung
+ * `A` [Levenshtein-Distanz (Levenshtein Distance)](src/algorithms/string/levenshtein-distance) - Minimaler Editierabstand zwischen zwei Sequenzen
+ * `A` [Problem der längsten gemeinsamen Teilsequenz (Longest Common Subsequence)](src/algorithms/sets/longest-common-subsequence) (LCS)
+ * `A` [Längstes häufiges Teilzeichenfolgenproblem (Longest Common Substring)](src/algorithms/string/longest-common-substring)
+ * `A` [Längste gemeinsame Teilsequenz (Longest Increasing Subsequence)](src/algorithms/sets/longest-increasing-subsequence)
+ * `A` [Der kürzeste gemeinsame String (Shortest Common Supersequence)](src/algorithms/sets/shortest-common-supersequence)
+ * `A` [Rucksackproblem (0/1 Knapsack Problem)](src/algorithms/sets/knapsack-problem)
+ * `A` [Ganzzahlige Partitionierung (Integer Partition)](src/algorithms/math/integer-partition)
+ * `A` [Das Maximum-Subarray Problem (Maximum Subarray)](src/algorithms/sets/maximum-subarray)
+ * `A` [Bellman-Ford-Algorithmus (Bellman-Ford Algorithm)](src/algorithms/graph/bellman-ford) - Finden der kürzesten Wege zu allen Knoten des Graphen von einem einzelnen Knotenpunkt aus
+ * `A` [Algorithmus von Floyd und Warshall (Floyd-Warshall Algorithm)](src/algorithms/graph/floyd-warshall) - Die kürzesten Wege zwischen allen Knotenpaaren finden
+ * `A` [Regulärer Ausdruck (Regular Expression Matching)](src/algorithms/string/regular-expression-matching)
+* **Zurückverfolgung** - Ähnlich wie bei Brute-Force versuchen Sie, alle möglichen Lösungen zu generieren, aber jedes Mal, wenn Sie die nächste Lösung generieren, testen Sie, ob sie alle Bedingungen erfüllt, und fahren erst dann mit der Generierung weiterer Lösungen fort. Andernfalls gehen Sie zurück und nehmen einen anderen Weg, um eine Lösung zu finden. Normalerweise wird das DFS-Traversal des Zustandsraums verwendet.
+ * `B` [Jump Game (Jump Game)](src/algorithms/uncategorized/jump-game)
+ * `B` [Eindeutige Pfade (Unique Paths)](src/algorithms/uncategorized/unique-paths)
+ * `A` [Potenzmenge (Power Set)](src/algorithms/sets/power-set) - Alle Teilmengen einer Menge
+ * `A` [Hamiltonkreisproblem (Hamiltonian Cycle)](src/algorithms/graph/hamiltonian-cycle) - Jeden Eckpunkt genau einmal durchlaufen.
+ * `A` [Damenproblem (N-Queens Problem)](src/algorithms/uncategorized/n-queens)
+ * `A` [Springerproblem (Knight's Tour)](src/algorithms/uncategorized/knight-tour)
+ * `A` [Kombinationssumme (Combination Sum)](src/algorithms/sets/combination-sum) - Alle Kombinationen finden, die eine bestimmte Summe bilden
+* **Verzweigung & Bindung** - Merkt sich die Lösung mit den niedrigsten Kosten, die in jeder Phase der Backtracking-Suche gefunden wurde, und verwendet die Kosten der bisher gefundenen Lösung mit den niedrigsten Kosten als untere Schranke für die Kosten einer Lösung des Problems mit den geringsten Kosten, um Teillösungen zu verwerfen, deren Kosten größer sind als die der bisher gefundenen Lösung mit den niedrigsten Kosten. Normalerweise wird das BFS-Traversal in Kombination mit dem DFS-Traversal des Zustandsraumbaums verwendet.
+
+## So verwendest du dieses Repository
+
+**Alle Abhängigkeiten installieren**
+
+```
+npm install
+```
+
+**ESLint ausführen**
+
+You may want to run it to check code quality.
+
+```
+npm run lint
+```
+
+**Alle Tests ausführen**
+
+```
+npm test
+```
+
+**Tests nach Namen ausführen**
+
+```
+npm test -- 'LinkedList'
+```
+
+**Fehlerbehebung**
+
+Falls das Linting oder Testen fehlschlägt, versuche, den Ordner "node_modules" zu löschen und die npm-Pakete neu zu installieren:
+
+```
+rm -rf ./node_modules
+npm i
+```
+
+**Spielwiese**
+
+Du kannst mit Datenstrukturen und Algorithmen in der Datei `./src/playground/playground.js` herumspielen und
+dir in dieser Datei Tests schreiben `./src/playground/__test__/playground.test.js`.
+
+Dann führe einfach folgenden Befehl aus, um zu testen, ob dein Spielwiesencode wie erwartet funktioniert:
+
+```
+npm test -- 'playground'
+```
+
+## Nützliche Informationen
+
+### Referenzen
+
+[▶ Datenstrukturen und Algorithmen auf YouTube(Englisch)](https://www.youtube.com/playlist?list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8)
+
+### O-Notation (_Big O Notation_)
+
+Die O-Notation wird verwendet, um Algorithmen danach zu klassifizieren, wie ihre Laufzeit oder ihr Platzbedarf mit zunehmender Eingabegröße wächst. In der folgenden Tabelle finden Sie die häufigsten Wachstumsordnungen von Algorithmen, die in Big-O-Notation angegeben sind.
+
+
+
+Quelle: [Big O Cheat Sheet](http://bigocheatsheet.com/).
+
+Nachfolgend finden Sie eine Liste einiger der am häufigsten verwendeten Big O-Notationen und deren Leistungsvergleiche für unterschiedliche Größen der Eingabedaten.
+
+| Big O Notation | Berechnungen für 10 Elemente | Berechnungen für 100 Elemente | Berechnungen für 1000 Elemente |
+| -------------- | ---------------------------- | ----------------------------- | ------------------------------ |
+| **O(1)** | 1 | 1 | 1 |
+| **O(log N)** | 3 | 6 | 9 |
+| **O(N)** | 10 | 100 | 1000 |
+| **O(N log N)** | 30 | 600 | 9000 |
+| **O(N^2)** | 100 | 10000 | 1000000 |
+| **O(2^N)** | 1024 | 1.26e+29 | 1.07e+301 |
+| **O(N!)** | 3628800 | 9.3e+157 | 4.02e+2567 |
+
+### Komplexität von Datenstrukturoperationen
+
+| Datenstruktur | Zugriff auf | Suche | Einfügen | Löschung | Kommentare |
+| ---------------------- | :---------: | :----: | :------: | :------: | :-------------------------------------------------------------- |
+| **Array** | 1 | n | n | n | |
+| **Stack** | n | n | 1 | 1 | |
+| **Queue** | n | n | 1 | 1 | |
+| **Linked List** | n | n | 1 | n | |
+| **Hash Table** | - | n | n | n | Im Falle einer perfekten Hash-Funktion wären die Kosten O(1) |
+| **Binary Search Tree** | n | n | n | n | Im Falle eines ausgeglichenen Baumes wären die Kosten O(log(n)) |
+| **B-Tree** | log(n) | log(n) | log(n) | log(n) | |
+| **Red-Black Tree** | log(n) | log(n) | log(n) | log(n) | |
+| **AVL Tree** | log(n) | log(n) | log(n) | log(n) | |
+| **Bloom Filter** | - | 1 | 1 | - | Falschpostive sind bei der Suche möglichen |
+
+### Komplexität von Array-Sortieralgorithmen
+
+| Name | Bester | Durchschnitt | Schlechtester | Speicher | Stabil | Kommentar |
+| ------------------ | :-----------: | :---------------------: | :-------------------------: | :------: | :----: | :------------------------------------------------------------------------- |
+| **Bubble sort** | n | n2 | n2 | 1 | JA | |
+| **Insertion sort** | n | n2 | n2 | 1 | Ja | |
+| **Selection sort** | n2 | n2 | n2 | 1 | Nein | |
+| **Heap sort** | n log(n) | n log(n) | n log(n) | 1 | Nein | |
+| **Merge sort** | n log(n) | n log(n) | n log(n) | n | Ja | |
+| **Quick sort** | n log(n) | n log(n) | n2 | log(n) | Nein | Quicksort wird normalerweise in-place mit O(log(n)) Stapelplatz ausgeführt |
+| **Shell sort** | n log(n) | abhängig von Spaltfolge | n (log(n))2 | 1 | Nein | |
+| **Counting sort** | n + r | n + r | n + r | n + r | Ja | r - größte Zahl im Array |
+| **Radix sort** | n \* k | n \* k | n \* k | n + k | Ja | k - Länge des längsten Schlüssels |
+
+## Projekt-Unterstützer
+
+> Du kannst dieses Projekt unterstützen über ❤️️ [GitHub](https://github.com/sponsors/trekhleb) or ❤️️ [Patreon](https://www.patreon.com/trekhleb).
+
+[Leute, die dieses Projekt unterstützen](https://github.com/trekhleb/javascript-algorithms/blob/master/BACKERS.md) `∑ = 0`
diff --git a/README.es-ES.md b/README.es-ES.md
index fa1fd340c6..f350ee059e 100644
--- a/README.es-ES.md
+++ b/README.es-ES.md
@@ -23,7 +23,8 @@ _Léelo en otros idiomas:_
[_Italiana_](README.it-IT.md),
[_Bahasa Indonesia_](README.id-ID.md),
[_Українська_](README.uk-UA.md),
-[_Arabic_](README.ar-AR.md)
+[_Arabic_](README.ar-AR.md),
+[_Deutsch_](README.de-DE.md)
*☝ Nótese que este proyecto está pensado con fines de aprendizaje e investigación,
y **no** para ser usado en producción.*
diff --git a/README.fr-FR.md b/README.fr-FR.md
index 024a3b1904..4508340aec 100644
--- a/README.fr-FR.md
+++ b/README.fr-FR.md
@@ -24,7 +24,8 @@ _Lisez ceci dans d'autres langues:_
[_Italiana_](README.it-IT.md),
[_Bahasa Indonesia_](README.id-ID.md),
[_Українська_](README.uk-UA.md),
-[_Arabic_](README.ar-AR.md)
+[_Arabic_](README.ar-AR.md),
+[_Deutsch_](README.de-DE.md)
## Data Structures
diff --git a/README.id-ID.md b/README.id-ID.md
index 2a258f973c..2f5212ac64 100644
--- a/README.id-ID.md
+++ b/README.id-ID.md
@@ -21,7 +21,8 @@ _Baca ini dalam bahasa yang lain:_
[_Türk_](README.tr-TR.md),
[_Italiana_](README.it-IT.md),
[_Українська_](README.uk-UA.md),
-[_Arabic_](README.ar-AR.md)
+[_Arabic_](README.ar-AR.md),
+[_Deutsch_](README.de-DE.md)
_☝ Perhatikan bahwa proyek ini hanya dimaksudkan untuk tujuan pembelajaran dan riset, dan **tidak** dimaksudkan untuk digunakan sebagai produksi._
diff --git a/README.it-IT.md b/README.it-IT.md
index 9d8c664f6a..d74befd683 100644
--- a/README.it-IT.md
+++ b/README.it-IT.md
@@ -20,7 +20,8 @@ _Leggilo in altre lingue:_
[_Türk_](README.tr-TR.md),
[_Bahasa Indonesia_](README.id-ID.md),
[_Українська_](README.uk-UA.md),
-[_Arabic_](README.ar-AR.md)
+[_Arabic_](README.ar-AR.md),
+[_Deutsch_](README.de-DE.md)
*☝ Si noti che questo progetto è destinato ad essere utilizzato solo per l'apprendimento e la ricerca e non è destinato ad essere utilizzato per il commercio.*
diff --git a/README.ja-JP.md b/README.ja-JP.md
index af2c887c2c..a1c13211a0 100644
--- a/README.ja-JP.md
+++ b/README.ja-JP.md
@@ -23,7 +23,8 @@ _Read this in other languages:_
[_Italiana_](README.it-IT.md),
[_Bahasa Indonesia_](README.id-ID.md),
[_Українська_](README.uk-UA.md),
-[_Arabic_](README.ar-AR.md)
+[_Arabic_](README.ar-AR.md),
+[_Deutsch_](README.de-DE.md)
## データ構造
diff --git a/README.ko-KR.md b/README.ko-KR.md
index 02f35d0250..e9b77dca27 100644
--- a/README.ko-KR.md
+++ b/README.ko-KR.md
@@ -22,7 +22,8 @@ _Read this in other languages:_
[_Italiana_](README.it-IT.md),
[_Bahasa Indonesia_](README.id-ID.md),
[_Українська_](README.uk-UA.md),
-[_Arabic_](README.ar-AR.md)
+[_Arabic_](README.ar-AR.md),
+[_Deutsch_](README.de-DE.md)
## 자료 구조
diff --git a/README.md b/README.md
index a9fc7b5ea0..d16c264d1e 100644
--- a/README.md
+++ b/README.md
@@ -24,7 +24,8 @@ _Read this in other languages:_
[_Italiana_](README.it-IT.md),
[_Bahasa Indonesia_](README.id-ID.md),
[_Українська_](README.uk-UA.md),
-[_Arabic_](README.ar-AR.md)
+[_Arabic_](README.ar-AR.md),
+[_Deutsch_](README.de-DE.md)
*☝ Note that this project is meant to be used for learning and researching purposes
only, and it is **not** meant to be used for production.*
diff --git a/README.pl-PL.md b/README.pl-PL.md
index 08dc09b6aa..235d0d47d6 100644
--- a/README.pl-PL.md
+++ b/README.pl-PL.md
@@ -24,7 +24,8 @@ _Read this in other languages:_
[_Italiana_](README.it-IT.md),
[_Bahasa Indonesia_](README.id-ID.md),
[_Українська_](README.uk-UA.md),
-[_Arabic_](README.ar-AR.md)
+[_Arabic_](README.ar-AR.md),
+[_Deutsch_](README.de-DE.md)
## Struktury Danych
diff --git a/README.pt-BR.md b/README.pt-BR.md
index baffbc3179..c410fda651 100644
--- a/README.pt-BR.md
+++ b/README.pt-BR.md
@@ -24,7 +24,8 @@ _Leia isto em outros idiomas:_
[_Italiana_](README.it-IT.md),
[_Bahasa Indonesia_](README.id-ID.md),
[_Українська_](README.uk-UA.md),
-[_Arabic_](README.ar-AR.md)
+[_Arabic_](README.ar-AR.md),
+[_Deutsch_](README.de-DE.md)
## Estrutura de Dados
diff --git a/README.ru-RU.md b/README.ru-RU.md
index 32f4b2f526..ef9e9444a3 100644
--- a/README.ru-RU.md
+++ b/README.ru-RU.md
@@ -21,7 +21,8 @@ _Читать на других языках:_
[_Italiana_](README.it-IT.md),
[_Bahasa Indonesia_](README.id-ID.md),
[_Українська_](README.uk-UA.md),
-[_Arabic_](README.ar-AR.md)
+[_Arabic_](README.ar-AR.md),
+[_Deutsch_](README.de-DE.md)
*☝ Замечание: этот репозиторий предназначен для учебно-исследовательских целей (**не** для использования в продакшн-системах).*
diff --git a/README.tr-TR.md b/README.tr-TR.md
index f7ed57fc91..fff640c415 100644
--- a/README.tr-TR.md
+++ b/README.tr-TR.md
@@ -22,7 +22,8 @@ _Read this in other languages:_
[_Italiana_](README.it-IT.md),
[_Bahasa Indonesia_](README.id-ID.md),
[_Українська_](README.uk-UA.md),
-[_Arabic_](README.ar-AR.md)
+[_Arabic_](README.ar-AR.md),
+[_Deutsch_](README.de-DE.md)
*☝ Not, bu proje araştırma ve öğrenme amacı ile yapılmış
olup üretim için **yaplılmamıştır**.*
diff --git a/README.uk-UA.md b/README.uk-UA.md
index 4391ed1992..6fdd7b4c13 100644
--- a/README.uk-UA.md
+++ b/README.uk-UA.md
@@ -21,7 +21,8 @@ _Вивчення матеріалу на інших мовах:_
[_Türk_](README.tr-TR.md),
[_Italiana_](README.it-IT.md),
[_Bahasa Indonesia_](README.id-ID.md),
-[_Arabic_](README.ar-AR.md)
+[_Arabic_](README.ar-AR.md),
+[_Deutsch_](README.de-DE.md)
*☝ Зверніть увагу! Даний проект призначений лише для навчальних та дослідницьких цілей, і він **не** призначений для виробництва (продакшн).*
diff --git a/README.zh-CN.md b/README.zh-CN.md
index 35a3733fc3..22b50d405c 100644
--- a/README.zh-CN.md
+++ b/README.zh-CN.md
@@ -21,7 +21,8 @@ _Read this in other languages:_
[_Italiana_](README.it-IT.md),
[_Bahasa Indonesia_](README.id-ID.md),
[_Українська_](README.uk-UA.md),
-[_Arabic_](README.ar-AR.md)
+[_Arabic_](README.ar-AR.md),
+[_Deutsch_](README.de-DE.md)
*注意:这个项目仅用于学习和研究,**不是**用于生产环境。*
diff --git a/README.zh-TW.md b/README.zh-TW.md
index 4a09b8433e..bf90fbbe62 100644
--- a/README.zh-TW.md
+++ b/README.zh-TW.md
@@ -20,7 +20,8 @@ _Read this in other languages:_
[_Italiana_](README.it-IT.md),
[_Bahasa Indonesia_](README.id-ID.md),
[_Українська_](README.uk-UA.md),
-[_Arabic_](README.ar-AR.md)
+[_Arabic_](README.ar-AR.md),
+[_Deutsch_](README.de-DE.md)
## 資料結構
From 464a84bc7cb8fcc9c78ccb9fab0d77d978e8363c Mon Sep 17 00:00:00 2001
From: justforever
Date: Thu, 6 May 2021 12:56:40 +0800
Subject: [PATCH 110/285] Update README.zh-TW.md (#690)
---
README.zh-TW.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.zh-TW.md b/README.zh-TW.md
index bf90fbbe62..ddf043d7af 100644
--- a/README.zh-TW.md
+++ b/README.zh-TW.md
@@ -215,7 +215,7 @@ npm test -- 'playground'
| 名稱 | 最佳 | 平均 | 最差 | 記憶體 | 穩定 |
| ---------------------- | :-------: | :-------: | :-----------: | :-------: | :-------: |
-| **氣派排序** | n | n^2 | n^2 | 1 | Yes |
+| **氣泡排序** | n | n^2 | n^2 | 1 | Yes |
| **插入排序** | n | n^2 | n^2 | 1 | Yes |
| **選擇排序** | n^2 | n^2 | n^2 | 1 | No |
| **Heap 排序** | n log(n) | n log(n) | n log(n) | 1 | No |
From 5ffab573ca4610c3ea6bd00709883b0a2ec5b898 Mon Sep 17 00:00:00 2001
From: Freivin Campbell
Date: Wed, 5 May 2021 23:00:10 -0600
Subject: [PATCH 111/285] Create README.es-ES.md (#680)
new translation added
---
.../doubly-linked-list/README.es-ES.md | 102 ++++++++++++++++++
1 file changed, 102 insertions(+)
create mode 100644 src/data-structures/doubly-linked-list/README.es-ES.md
diff --git a/src/data-structures/doubly-linked-list/README.es-ES.md b/src/data-structures/doubly-linked-list/README.es-ES.md
new file mode 100644
index 0000000000..0736d499ac
--- /dev/null
+++ b/src/data-structures/doubly-linked-list/README.es-ES.md
@@ -0,0 +1,102 @@
+# Lista doblemente enlazada
+
+_Lea esto en otros idiomas:_
+[_Русский_](README.ru-RU.md),
+[_简体中文_](README.zh-CN.md),
+[_日本語_](README.ja-JP.md),
+[_Português_](README.pt-BR.md)
+[_한국어_](README.ko-KR.md)
+
+En informática, una **lista doblemente enlazada** es una estructura de datos enlazados que consta de un conjunto de registros enlazados secuencialmente llamados nodos. Cada nodo contiene dos campos, llamados enlaces, que son referencias al nodo anterior y al siguiente en la secuencia de nodos. Los enlaces anterior y siguiente de los nodos inicial y final, respectivamente, apuntan a algún tipo de terminador, normalmente un nodo centinela o nulo, para facilitar el recorrido de la lista. Si solo hay un ganglio centinela, la lista se enlaza circularmente a través del ganglio centinela. Puede conceptualizarse como dos listas enlazadas individualmente formadas a partir de los mismos elementos de datos, pero en órdenes secuenciales opuestos.
+
+
+
+Los dos enlaces de nodo permiten recorrer la lista en cualquier dirección. Si bien agregar o eliminar un nodo en una lista doblemente enlazada requiere cambiar más enlaces que las mismas operaciones en una lista enlazada individualmente, las operaciones son más simples y potencialmente más eficientes (para nodos que no sean los primeros) porque no hay necesidad de realizar un seguimiento de el nodo anterior durante el recorrido o no es necesario recorrer la lista para encontrar el nodo anterior, de modo que se pueda modificar su enlace.
+
+## Pseudocódigo para operaciones básicas
+
+### Insertar
+
+```text
+Add(value)
+ Pre: value is the value to add to the list
+ Post: value has been placed at the tail of the list
+ n ← node(value)
+ if head = ø
+ head ← n
+ tail ← n
+ else
+ n.previous ← tail
+ tail.next ← n
+ tail ← n
+ end if
+end Add
+```
+
+### Eliminar
+
+```text
+Remove(head, value)
+ Pre: head is the head node in the list
+ value is the value to remove from the list
+ Post: value is removed from the list, true; otherwise false
+ if head = ø
+ return false
+ end if
+ if value = head.value
+ if head = tail
+ head ← ø
+ tail ← ø
+ else
+ head ← head.next
+ head.previous ← ø
+ end if
+ return true
+ end if
+ n ← head.next
+ while n != ø and value !== n.value
+ n ← n.next
+ end while
+ if n = tail
+ tail ← tail.previous
+ tail.next ← ø
+ return true
+ else if n != ø
+ n.previous.next ← n.next
+ n.next.previous ← n.previous
+ return true
+ end if
+ return false
+end Remove
+```
+
+### Recorrido Inverso
+
+```text
+ReverseTraversal(tail)
+ Pre: tail is the node of the list to traverse
+ Post: the list has been traversed in reverse order
+ n ← tail
+ while n != ø
+ yield n.value
+ n ← n.previous
+ end while
+end Reverse Traversal
+```
+
+## Complejidades
+
+## Complejidad del Tiempo
+
+| Acceso | Busqueda | Inserción | Supresión |
+| :-------: | :-------: | :-------: | :-------: |
+| O(n) | O(n) | O(1) | O(n) |
+
+### Complejidad del Espacio
+
+O(n)
+
+## Referencias
+
+- [Wikipedia](https://en.wikipedia.org/wiki/Doubly_linked_list)
+- [YouTube](https://www.youtube.com/watch?v=JdQeNxWCguQ&t=7s&index=72&list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8)
From 22b323e6b112a85210369f48bf9044d9fa9c6371 Mon Sep 17 00:00:00 2001
From: CodingInvoker <71058225+CodingInvoker@users.noreply.github.com>
Date: Thu, 6 May 2021 13:02:52 +0800
Subject: [PATCH 112/285] update linkedlist comment (#687)
Co-authored-by: Jiachen Zhou
Co-authored-by: Oleksii Trekhleb
---
src/data-structures/linked-list/LinkedList.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/data-structures/linked-list/LinkedList.js b/src/data-structures/linked-list/LinkedList.js
index 1fb0b5eaf4..71c2b49755 100644
--- a/src/data-structures/linked-list/LinkedList.js
+++ b/src/data-structures/linked-list/LinkedList.js
@@ -65,7 +65,7 @@ export default class LinkedList {
let deletedNode = null;
- // If the head must be deleted then make next node that is differ
+ // If the head must be deleted then make next node that is different
// from the head to be a new head.
while (this.head && this.compare.equal(this.head.value, value)) {
deletedNode = this.head;
From cb50e4e9f394ebaf8172f71bc31dd2f68b1417d4 Mon Sep 17 00:00:00 2001
From: Oleksii Trekhleb
Date: Thu, 6 May 2021 07:05:27 +0200
Subject: [PATCH 113/285] Add link to Spanish translation in Doubly-Linked list
README.
---
.../doubly-linked-list/README.md | 39 ++++++++++---------
1 file changed, 20 insertions(+), 19 deletions(-)
diff --git a/src/data-structures/doubly-linked-list/README.md b/src/data-structures/doubly-linked-list/README.md
index c64b51262d..703520aaf4 100644
--- a/src/data-structures/doubly-linked-list/README.md
+++ b/src/data-structures/doubly-linked-list/README.md
@@ -4,26 +4,27 @@ _Read this in other languages:_
[_Русский_](README.ru-RU.md),
[_简体中文_](README.zh-CN.md),
[_日本語_](README.ja-JP.md),
-[_Português_](README.pt-BR.md)
-[_한국어_](README.ko-KR.md)
-
-In computer science, a **doubly linked list** is a linked data structure that
-consists of a set of sequentially linked records called nodes. Each node contains
-two fields, called links, that are references to the previous and to the next
-node in the sequence of nodes. The beginning and ending nodes' previous and next
-links, respectively, point to some kind of terminator, typically a sentinel
-node or null, to facilitate the traversal of the list. If there is only one
-sentinel node, then the list is circularly linked via the sentinel node. It can
-be conceptualized as two singly linked lists formed from the same data items,
+[_Português_](README.pt-BR.md),
+[_한국어_](README.ko-KR.md),
+[_Español_](README.es-ES.md),
+
+In computer science, a **doubly linked list** is a linked data structure that
+consists of a set of sequentially linked records called nodes. Each node contains
+two fields, called links, that are references to the previous and to the next
+node in the sequence of nodes. The beginning and ending nodes' previous and next
+links, respectively, point to some kind of terminator, typically a sentinel
+node or null, to facilitate the traversal of the list. If there is only one
+sentinel node, then the list is circularly linked via the sentinel node. It can
+be conceptualized as two singly linked lists formed from the same data items,
but in opposite sequential orders.

-The two node links allow traversal of the list in either direction. While adding
-or removing a node in a doubly linked list requires changing more links than the
-same operations on a singly linked list, the operations are simpler and
-potentially more efficient (for nodes other than first nodes) because there
-is no need to keep track of the previous node during traversal or no need
+The two node links allow traversal of the list in either direction. While adding
+or removing a node in a doubly linked list requires changing more links than the
+same operations on a singly linked list, the operations are simpler and
+potentially more efficient (for nodes other than first nodes) because there
+is no need to keep track of the previous node during traversal or no need
to traverse the list to find the previous node, so that its link can be modified.
## Pseudocode for Basic Operations
@@ -45,7 +46,7 @@ Add(value)
end if
end Add
```
-
+
### Delete
```text
@@ -82,7 +83,7 @@ Remove(head, value)
return false
end Remove
```
-
+
### Reverse Traversal
```text
@@ -96,7 +97,7 @@ ReverseTraversal(tail)
end while
end Reverse Traversal
```
-
+
## Complexities
## Time Complexity
From 8a24fbfac94dc5d446d51768eaa062637a6c1a16 Mon Sep 17 00:00:00 2001
From: Oleksii Trekhleb
Date: Fri, 14 May 2021 09:56:18 +0200
Subject: [PATCH 114/285] Adding more details on how to run the playground code
to address the issue #705.
---
src/playground/__test__/playground.test.js | 7 +++++--
src/playground/playground.js | 13 ++++++++++++-
2 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/src/playground/__test__/playground.test.js b/src/playground/__test__/playground.test.js
index 501a87a728..84a3e8301f 100644
--- a/src/playground/__test__/playground.test.js
+++ b/src/playground/__test__/playground.test.js
@@ -1,5 +1,8 @@
+import playground from '../playground';
+
describe('playground', () => {
- it('should perform playground tasks', () => {
- // Place your playground tests here.
+ it('should return correct results', () => {
+ // Replace the next dummy test with your playground function tests.
+ expect(playground()).toBe(120);
});
});
diff --git a/src/playground/playground.js b/src/playground/playground.js
index 7872c9e3b8..b8c5b210bc 100644
--- a/src/playground/playground.js
+++ b/src/playground/playground.js
@@ -1 +1,12 @@
-// Place your playground code here.
+// Import any algorithmic dependencies you need for your playground code here.
+import factorial from '../algorithms/math/factorial/factorial';
+
+// Write your playground code inside the playground() function.
+// Test your code from __tests__/playground.test.js
+// Launch playground tests by running: npm test -- 'playground'
+function playground() {
+ // Replace the next line with your playground code.
+ return factorial(5);
+}
+
+export default playground;
From 6d2d8c9379873d0da2b1262a14dd26d0f9779522 Mon Sep 17 00:00:00 2001
From: Oleksii Trekhleb
Date: Tue, 18 May 2021 08:44:13 +0200
Subject: [PATCH 115/285] Testing Codecov integration without web-hooks.
---
src/utils/comparator/Comparator.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/utils/comparator/Comparator.js b/src/utils/comparator/Comparator.js
index 12957d2d73..f5c41b5c18 100644
--- a/src/utils/comparator/Comparator.js
+++ b/src/utils/comparator/Comparator.js
@@ -1,5 +1,6 @@
export default class Comparator {
/**
+ * Constructor.
* @param {function(a: *, b: *)} [compareFunction] - It may be custom compare function that, let's
* say may compare custom objects together.
*/
From ee35bd6240af55d3353934cb50261c9e256d1326 Mon Sep 17 00:00:00 2001
From: Oleksii Trekhleb
Date: Wed, 26 May 2021 10:29:05 +0200
Subject: [PATCH 116/285] Testing Codecov integration without web-hooks.
---
README.ar-AR.md | 2 ++
README.de-DE.md | 3 +++
README.es-ES.md | 2 ++
README.fr-FR.md | 1 +
README.id-ID.md | 2 ++
README.it-IT.md | 2 ++
README.ja-JP.md | 2 ++
README.ko-KR.md | 2 ++
README.md | 2 ++
README.pl-PL.md | 2 ++
README.pt-BR.md | 2 ++
README.ru-RU.md | 2 ++
README.tr-TR.md | 2 ++
README.uk-UA.md | 2 ++
README.zh-CN.md | 2 ++
README.zh-TW.md | 2 ++
16 files changed, 32 insertions(+)
diff --git a/README.ar-AR.md b/README.ar-AR.md
index 797006b6ef..3514bce12f 100644
--- a/README.ar-AR.md
+++ b/README.ar-AR.md
@@ -321,3 +321,5 @@ npm test -- 'playground'
> يمكنك دعم هذا المشروع عبر ❤️️ [GitHub](https://github.com/sponsors/trekhleb) أو ❤️️ [Patreon](https://www.patreon.com/trekhleb).
[الناس الذين يدعمون هذا المشروع](https://github.com/trekhleb/javascript-algorithms/blob/master/BACKERS.md) `∑ = 0`
+
+> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.de-DE.md b/README.de-DE.md
index 3e127c3ea0..bd250ab3b0 100644
--- a/README.de-DE.md
+++ b/README.de-DE.md
@@ -331,3 +331,6 @@ Nachfolgend finden Sie eine Liste einiger der am häufigsten verwendeten Big O-N
> Du kannst dieses Projekt unterstützen über ❤️️ [GitHub](https://github.com/sponsors/trekhleb) or ❤️️ [Patreon](https://www.patreon.com/trekhleb).
[Leute, die dieses Projekt unterstützen](https://github.com/trekhleb/javascript-algorithms/blob/master/BACKERS.md) `∑ = 0`
+
+> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
+
diff --git a/README.es-ES.md b/README.es-ES.md
index f350ee059e..b5246bd61d 100644
--- a/README.es-ES.md
+++ b/README.es-ES.md
@@ -299,3 +299,5 @@ frente a diferentes tamaños de los datos de entrada.
| **Shellsort** | n log(n) | depende de la secuencia de huecos | n (log(n))2 | 1 | No | |
| **Ordenamiento por cuentas** | n + r | n + r | n + r | n + r | Si | r - mayor número en el arreglo |
| **Ordenamiento Radix** | n \* k | n \* k | n \* k | n + k | Si | k - largo de la llave más larga |
+
+> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.fr-FR.md b/README.fr-FR.md
index 4508340aec..aa7a9007a3 100644
--- a/README.fr-FR.md
+++ b/README.fr-FR.md
@@ -293,3 +293,4 @@ comparaisons de performance suivant différentes tailles pour les données d'ent
| **Tri Shell** | n log(n) | dépend du gap séquence | n (log(n))2 | 1 | Non | |
| **Tri Comptage** | n + r | n + r | n + r | n + r | Oui | r - le plus grand nombre dans la liste |
| **Tri Radix** | n \* k | n \* k | n \* k | n + k | Non | k - longueur du plus long index |
+> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.id-ID.md b/README.id-ID.md
index 2f5212ac64..f1ad648258 100644
--- a/README.id-ID.md
+++ b/README.id-ID.md
@@ -304,3 +304,5 @@ Di bawah ini adalah daftar dari beberapa notasi _Bog O_ yang sering digunakan da
> Anda dapat mendukung proyek ini via ❤️️ [GitHub](https://github.com/sponsors/trekhleb) atau ❤️️ [Patreon](https://www.patreon.com/trekhleb).
[Orang-orang yang mendukung proyek ini](https://github.com/trekhleb/javascript-algorithms/blob/master/BACKERS.md) `∑ = 1`
+
+> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.it-IT.md b/README.it-IT.md
index d74befd683..5947b92e75 100644
--- a/README.it-IT.md
+++ b/README.it-IT.md
@@ -297,3 +297,5 @@ Nella tabella qua sotto ci sono riportate la lista delle notazioni Big O più us
| **Shell sort** | n log(n) | dipende dagli spazi vuoti nella sequenza | n (log(n))2 | 1 | No | |
| **Counting sort** | n + r | n + r | n + r | n + r | Yes | r - numero più grande nell'array |
| **Radix sort** | n * k | n * k | n * k | n + k | Yes | k - lunghezza della chiave più grande |
+
+> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.ja-JP.md b/README.ja-JP.md
index a1c13211a0..30a9979908 100644
--- a/README.ja-JP.md
+++ b/README.ja-JP.md
@@ -296,3 +296,5 @@ npm test -- 'playground'
| **Shell sort** | n log(n) | depends on gap sequence | n (log(n))2 | 1 | No | |
| **Counting sort** | n + r | n + r | n + r | n + r | Yes | r - biggest number in array |
| **Radix sort** | n * k | n * k | n * k | n + k | Yes | k - length of longest key |
+
+> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.ko-KR.md b/README.ko-KR.md
index e9b77dca27..8bdb98b837 100644
--- a/README.ko-KR.md
+++ b/README.ko-KR.md
@@ -277,3 +277,5 @@ Source: [Big O Cheat Sheet](http://bigocheatsheet.com/).
| **셸 정렬** | n log(n) | 간격 순서에 영향을 받습니다. | n (log(n))2 | 1 | No | |
| **계수 정렬** | n + r | n + r | n + r | n + r | Yes | r - 배열내 가장 큰 수 |
| **기수 정렬** | n * k | n * k | n * k | n + k | Yes | k - 키값의 최대 길이 |
+
+> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.md b/README.md
index d16c264d1e..a589d710e1 100644
--- a/README.md
+++ b/README.md
@@ -343,3 +343,5 @@ Below is the list of some of the most used Big O notations and their performance
> You may support this project via ❤️️ [GitHub](https://github.com/sponsors/trekhleb) or ❤️️ [Patreon](https://www.patreon.com/trekhleb).
[Folks who are backing this project](https://github.com/trekhleb/javascript-algorithms/blob/master/BACKERS.md) `∑ = 0`
+
+> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.pl-PL.md b/README.pl-PL.md
index 235d0d47d6..cc20e947e7 100644
--- a/README.pl-PL.md
+++ b/README.pl-PL.md
@@ -289,3 +289,5 @@ Poniżej umieszczamy listę najbardziej używanych Big O notacji i ich porównan
| **Sortowanie Shella** | n log(n) | zależy od luki w układzie | n (log(n))2 | 1 | No | |
| **Sortowanie przez zliczanie** | n + r | n + r | n + r | n + r | Yes | r - największy numer w tablicy|
| **Sortowanie Radix** | n * k | n * k | n * k | n + k | Yes | k -długość najdłuższego klucza |
+
+> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.pt-BR.md b/README.pt-BR.md
index c410fda651..cc3b9f2191 100644
--- a/README.pt-BR.md
+++ b/README.pt-BR.md
@@ -290,3 +290,5 @@ Abaixo está a lista de algumas das notações Big O mais usadas e suas compara
| **Shell sort** | n log(n) | depende da sequência de lacunas | n (log(n))2 | 1 | Não | |
| **Counting sort** | n + r | n + r | n + r | n + r | Sim | r - maior número na matriz |
| **Radix sort** | n * k | n * k | n * k | n + k | Sim | k - comprimento da chave mais longa |
+
+> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.ru-RU.md b/README.ru-RU.md
index ef9e9444a3..d5c2c69c6f 100644
--- a/README.ru-RU.md
+++ b/README.ru-RU.md
@@ -295,3 +295,5 @@ npm test -- 'playground'
| **Сортировка Шелла** | n log(n) | зависит от выбранных шагов | n (log(n))2 | 1 | Нет | |
| **Сортировка подсчётом** | n + r | n + r | n + r | n + r | Да | r — наибольшее число в массиве |
| **Поразрядная сортировка** | n * k | n * k | n * k | n + k | Да | k — длина самого длинного ключа |
+
+> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.tr-TR.md b/README.tr-TR.md
index fff640c415..73f3077e1e 100644
--- a/README.tr-TR.md
+++ b/README.tr-TR.md
@@ -315,3 +315,5 @@ Altta Big O notations ve farklı input boyutlarına karşın yapılmış perform
## Projeyi Destekleme
Bu projeyi buradan destekleyebilirsiniz ❤️️ [GitHub](https://github.com/sponsors/trekhleb) veya ❤️️ [Patreon](https://www.patreon.com/trekhleb).
+
+> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.uk-UA.md b/README.uk-UA.md
index 6fdd7b4c13..be4d923b70 100644
--- a/README.uk-UA.md
+++ b/README.uk-UA.md
@@ -305,3 +305,5 @@ npm test -- 'playground'
> Ви можете підтримати цей проект через ❤️️ [GitHub](https://github.com/sponsors/trekhleb) або ❤️️ [Patreon](https://www.patreon.com/trekhleb).
[Люди, які підтримують цей проект](https://github.com/trekhleb/javascript-algorithms/blob/master/BACKERS.md) `∑ = 1`
+
+> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.zh-CN.md b/README.zh-CN.md
index 22b50d405c..1425f87993 100644
--- a/README.zh-CN.md
+++ b/README.zh-CN.md
@@ -292,3 +292,5 @@ npm test -- 'playground'
| **希尔排序** | n log(n) | 取决于差距序列 | n (log(n))^2 | 1 | No | |
| **计数排序** | n + r | n + r | n + r | n + r | Yes | r - 数组里最大的数 |
| **基数排序** | n * k | n * k | n * k | n + k | Yes | k - 最长 key 的升序 |
+
+> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.zh-TW.md b/README.zh-TW.md
index ddf043d7af..10b6e84f08 100644
--- a/README.zh-TW.md
+++ b/README.zh-TW.md
@@ -222,3 +222,5 @@ npm test -- 'playground'
| **合併排序** | n log(n) | n log(n) | n log(n) | n | Yes |
| **快速排序** | n log(n) | n log(n) | n^2 | log(n) | No |
| **希爾排序** | n log(n) | 由gap sequence決定 | n (log(n))^2 | 1 | No |
+
+> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
From 433515f1b22a1a53443429b20f09f821a3325895 Mon Sep 17 00:00:00 2001
From: Oleksii Trekhleb
Date: Wed, 26 May 2021 10:55:57 +0200
Subject: [PATCH 117/285] Fix typo in READMEs.
---
README.ar-AR.md | 2 +-
README.de-DE.md | 2 +-
README.es-ES.md | 2 +-
README.fr-FR.md | 3 ++-
README.id-ID.md | 2 +-
README.it-IT.md | 2 +-
README.ja-JP.md | 2 +-
README.ko-KR.md | 2 +-
README.md | 2 +-
README.pl-PL.md | 2 +-
README.pt-BR.md | 2 +-
README.ru-RU.md | 2 +-
README.tr-TR.md | 2 +-
README.uk-UA.md | 2 +-
README.zh-CN.md | 2 +-
README.zh-TW.md | 2 +-
16 files changed, 17 insertions(+), 16 deletions(-)
diff --git a/README.ar-AR.md b/README.ar-AR.md
index 3514bce12f..07522e78a6 100644
--- a/README.ar-AR.md
+++ b/README.ar-AR.md
@@ -322,4 +322,4 @@ npm test -- 'playground'
[الناس الذين يدعمون هذا المشروع](https://github.com/trekhleb/javascript-algorithms/blob/master/BACKERS.md) `∑ = 0`
-> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
+> ℹ️ A few more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.de-DE.md b/README.de-DE.md
index bd250ab3b0..b34ad3563f 100644
--- a/README.de-DE.md
+++ b/README.de-DE.md
@@ -332,5 +332,5 @@ Nachfolgend finden Sie eine Liste einiger der am häufigsten verwendeten Big O-N
[Leute, die dieses Projekt unterstützen](https://github.com/trekhleb/javascript-algorithms/blob/master/BACKERS.md) `∑ = 0`
-> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
+> ℹ️ A few more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.es-ES.md b/README.es-ES.md
index b5246bd61d..6f5db59bb8 100644
--- a/README.es-ES.md
+++ b/README.es-ES.md
@@ -300,4 +300,4 @@ frente a diferentes tamaños de los datos de entrada.
| **Ordenamiento por cuentas** | n + r | n + r | n + r | n + r | Si | r - mayor número en el arreglo |
| **Ordenamiento Radix** | n \* k | n \* k | n \* k | n + k | Si | k - largo de la llave más larga |
-> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
+> ℹ️ A few more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.fr-FR.md b/README.fr-FR.md
index aa7a9007a3..59087825ff 100644
--- a/README.fr-FR.md
+++ b/README.fr-FR.md
@@ -293,4 +293,5 @@ comparaisons de performance suivant différentes tailles pour les données d'ent
| **Tri Shell** | n log(n) | dépend du gap séquence | n (log(n))2 | 1 | Non | |
| **Tri Comptage** | n + r | n + r | n + r | n + r | Oui | r - le plus grand nombre dans la liste |
| **Tri Radix** | n \* k | n \* k | n \* k | n + k | Non | k - longueur du plus long index |
-> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
+
+> ℹ️ A few more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.id-ID.md b/README.id-ID.md
index f1ad648258..01d539c5ef 100644
--- a/README.id-ID.md
+++ b/README.id-ID.md
@@ -305,4 +305,4 @@ Di bawah ini adalah daftar dari beberapa notasi _Bog O_ yang sering digunakan da
[Orang-orang yang mendukung proyek ini](https://github.com/trekhleb/javascript-algorithms/blob/master/BACKERS.md) `∑ = 1`
-> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
+> ℹ️ A few more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.it-IT.md b/README.it-IT.md
index 5947b92e75..b459ac87d1 100644
--- a/README.it-IT.md
+++ b/README.it-IT.md
@@ -298,4 +298,4 @@ Nella tabella qua sotto ci sono riportate la lista delle notazioni Big O più us
| **Counting sort** | n + r | n + r | n + r | n + r | Yes | r - numero più grande nell'array |
| **Radix sort** | n * k | n * k | n * k | n + k | Yes | k - lunghezza della chiave più grande |
-> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
+> ℹ️ A few more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.ja-JP.md b/README.ja-JP.md
index 30a9979908..44b6b6c13e 100644
--- a/README.ja-JP.md
+++ b/README.ja-JP.md
@@ -297,4 +297,4 @@ npm test -- 'playground'
| **Counting sort** | n + r | n + r | n + r | n + r | Yes | r - biggest number in array |
| **Radix sort** | n * k | n * k | n * k | n + k | Yes | k - length of longest key |
-> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
+> ℹ️ A few more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.ko-KR.md b/README.ko-KR.md
index 8bdb98b837..040ac8a57d 100644
--- a/README.ko-KR.md
+++ b/README.ko-KR.md
@@ -278,4 +278,4 @@ Source: [Big O Cheat Sheet](http://bigocheatsheet.com/).
| **계수 정렬** | n + r | n + r | n + r | n + r | Yes | r - 배열내 가장 큰 수 |
| **기수 정렬** | n * k | n * k | n * k | n + k | Yes | k - 키값의 최대 길이 |
-> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
+> ℹ️ A few more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.md b/README.md
index a589d710e1..b8e2be362a 100644
--- a/README.md
+++ b/README.md
@@ -344,4 +344,4 @@ Below is the list of some of the most used Big O notations and their performance
[Folks who are backing this project](https://github.com/trekhleb/javascript-algorithms/blob/master/BACKERS.md) `∑ = 0`
-> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
+> ℹ️ A few more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.pl-PL.md b/README.pl-PL.md
index cc20e947e7..51777b0da2 100644
--- a/README.pl-PL.md
+++ b/README.pl-PL.md
@@ -290,4 +290,4 @@ Poniżej umieszczamy listę najbardziej używanych Big O notacji i ich porównan
| **Sortowanie przez zliczanie** | n + r | n + r | n + r | n + r | Yes | r - największy numer w tablicy|
| **Sortowanie Radix** | n * k | n * k | n * k | n + k | Yes | k -długość najdłuższego klucza |
-> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
+> ℹ️ A few more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.pt-BR.md b/README.pt-BR.md
index cc3b9f2191..68b7e1721f 100644
--- a/README.pt-BR.md
+++ b/README.pt-BR.md
@@ -291,4 +291,4 @@ Abaixo está a lista de algumas das notações Big O mais usadas e suas compara
| **Counting sort** | n + r | n + r | n + r | n + r | Sim | r - maior número na matriz |
| **Radix sort** | n * k | n * k | n * k | n + k | Sim | k - comprimento da chave mais longa |
-> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
+> ℹ️ A few more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.ru-RU.md b/README.ru-RU.md
index d5c2c69c6f..6200aedd53 100644
--- a/README.ru-RU.md
+++ b/README.ru-RU.md
@@ -296,4 +296,4 @@ npm test -- 'playground'
| **Сортировка подсчётом** | n + r | n + r | n + r | n + r | Да | r — наибольшее число в массиве |
| **Поразрядная сортировка** | n * k | n * k | n * k | n + k | Да | k — длина самого длинного ключа |
-> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
+> ℹ️ A few more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.tr-TR.md b/README.tr-TR.md
index 73f3077e1e..0dd0ee3bf2 100644
--- a/README.tr-TR.md
+++ b/README.tr-TR.md
@@ -316,4 +316,4 @@ Altta Big O notations ve farklı input boyutlarına karşın yapılmış perform
Bu projeyi buradan destekleyebilirsiniz ❤️️ [GitHub](https://github.com/sponsors/trekhleb) veya ❤️️ [Patreon](https://www.patreon.com/trekhleb).
-> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
+> ℹ️ A few more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.uk-UA.md b/README.uk-UA.md
index be4d923b70..b43da83ca6 100644
--- a/README.uk-UA.md
+++ b/README.uk-UA.md
@@ -306,4 +306,4 @@ npm test -- 'playground'
[Люди, які підтримують цей проект](https://github.com/trekhleb/javascript-algorithms/blob/master/BACKERS.md) `∑ = 1`
-> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
+> ℹ️ A few more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.zh-CN.md b/README.zh-CN.md
index 1425f87993..8bf216d6bd 100644
--- a/README.zh-CN.md
+++ b/README.zh-CN.md
@@ -293,4 +293,4 @@ npm test -- 'playground'
| **计数排序** | n + r | n + r | n + r | n + r | Yes | r - 数组里最大的数 |
| **基数排序** | n * k | n * k | n * k | n + k | Yes | k - 最长 key 的升序 |
-> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
+> ℹ️ A few more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
diff --git a/README.zh-TW.md b/README.zh-TW.md
index 10b6e84f08..e42aba445d 100644
--- a/README.zh-TW.md
+++ b/README.zh-TW.md
@@ -223,4 +223,4 @@ npm test -- 'playground'
| **快速排序** | n log(n) | n log(n) | n^2 | log(n) | No |
| **希爾排序** | n log(n) | 由gap sequence決定 | n (log(n))^2 | 1 | No |
-> ℹ️ Some more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
+> ℹ️ A few more [projects](https://trekhleb.dev/projects/) and [articles](https://trekhleb.dev/blog/) about JavaScript and algorithms on [trekhleb.dev](https://trekhleb.dev)
From b2d1ec83f04a66d9d2d3f09150bcaf0cacb0f7ba Mon Sep 17 00:00:00 2001
From: Oleksii Trekhleb
Date: Fri, 16 Jul 2021 11:51:53 +0200
Subject: [PATCH 118/285] Binary representation of floating-point numbers
(#737)
* Add "Binary representation of floating point numbers" section.
* Adding a half-precision explanatory picture.
* Binary representation of the floating-point numbers.
---
README.md | 1 +
.../math/binary-floating-point/README.md | 93 ++++++++++++++
.../__tests__/bitsToFloat.test.js | 32 +++++
.../__tests__/floatAsBinaryString.test.js | 20 +++
.../math/binary-floating-point/bitsToFloat.js | 119 ++++++++++++++++++
.../floatAsBinaryString.js | 61 +++++++++
...cision-floating-point-number-explained.png | Bin 0 -> 352613 bytes
.../images/03-scientific-notation.png | Bin 0 -> 76251 bytes
.../math/binary-floating-point/testCases.js | 71 +++++++++++
9 files changed, 397 insertions(+)
create mode 100644 src/algorithms/math/binary-floating-point/README.md
create mode 100644 src/algorithms/math/binary-floating-point/__tests__/bitsToFloat.test.js
create mode 100644 src/algorithms/math/binary-floating-point/__tests__/floatAsBinaryString.test.js
create mode 100644 src/algorithms/math/binary-floating-point/bitsToFloat.js
create mode 100644 src/algorithms/math/binary-floating-point/floatAsBinaryString.js
create mode 100644 src/algorithms/math/binary-floating-point/images/02-half-precision-floating-point-number-explained.png
create mode 100644 src/algorithms/math/binary-floating-point/images/03-scientific-notation.png
create mode 100644 src/algorithms/math/binary-floating-point/testCases.js
diff --git a/README.md b/README.md
index b8e2be362a..d00945e5a5 100644
--- a/README.md
+++ b/README.md
@@ -68,6 +68,7 @@ a set of rules that precisely define a sequence of operations.
* **Math**
* `B` [Bit Manipulation](src/algorithms/math/bits) - set/get/update/clear bits, multiplication/division by two, make negative etc.
+ * `B` [Binary Floating Point](src/algorithms/math/binary-floating-point) - binary representation of the floating-point numbers.
* `B` [Factorial](src/algorithms/math/factorial)
* `B` [Fibonacci Number](src/algorithms/math/fibonacci) - classic and closed-form versions
* `B` [Prime Factors](src/algorithms/math/prime-factors) - finding prime factors and counting them using Hardy-Ramanujan's theorem
diff --git a/src/algorithms/math/binary-floating-point/README.md b/src/algorithms/math/binary-floating-point/README.md
new file mode 100644
index 0000000000..2851902845
--- /dev/null
+++ b/src/algorithms/math/binary-floating-point/README.md
@@ -0,0 +1,93 @@
+# Binary representation of floating-point numbers
+
+Have you ever wondered how computers store the floating-point numbers like `3.1415` (𝝿) or `9.109 × 10⁻³¹` (the mass of the electron in kg) in the memory which is limited by a finite number of ones and zeroes (aka bits)?
+
+It seems pretty straightforward for integers (i.e. `17`). Let's say we have 16 bits (2 bytes) to store the number. In 16 bits we may store the integers in a range of `[0, 65535]`:
+
+```text
+(0000000000000000)₂ = (0)₁₀
+
+(0000000000010001)₂ =
+ (1 × 2⁴) +
+ (0 × 2³) +
+ (0 × 2²) +
+ (0 × 2¹) +
+ (1 × 2⁰) = (17)₁₀
+
+(1111111111111111)₂ =
+ (1 × 2¹⁵) +
+ (1 × 2¹⁴) +
+ (1 × 2¹³) +
+ (1 × 2¹²) +
+ (1 × 2¹¹) +
+ (1 × 2¹⁰) +
+ (1 × 2⁹) +
+ (1 × 2⁸) +
+ (1 × 2⁷) +
+ (1 × 2⁶) +
+ (1 × 2⁵) +
+ (1 × 2⁴) +
+ (1 × 2³) +
+ (1 × 2²) +
+ (1 × 2¹) +
+ (1 × 2⁰) = (65535)₁₀
+```
+
+If we need a signed integer we may use [two's complement](https://en.wikipedia.org/wiki/Two%27s_complement) and shift the range of `[0, 65535]` towards the negative numbers. In this case, our 16 bits would represent the numbers in a range of `[-32768, +32767]`.
+
+As you might have noticed, this approach won't allow you to represent the numbers like `-27.15625` (numbers after the decimal point are just being ignored).
+
+We're not the first ones who have noticed this issue though. Around ≈36 years ago some smart folks overcame this limitation by introducing the [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754) standard for floating-point arithmetic.
+
+The IEEE 754 standard describes the way (the framework) of using those 16 bits (or 32, or 64 bits) to store the numbers of wider range, including the small floating numbers (smaller than 1 and closer to 0).
+
+To get the idea behind the standard we might recall the [scientific notation](https://en.wikipedia.org/wiki/Scientific_notation) - a way of expressing numbers that are too large or too small (usually would result in a long string of digits) to be conveniently written in decimal form.
+
+
+
+As you may see from the image, the number representation might be split into three parts:
+
+- **sign**
+- **fraction (aka significand)** - the valuable digits (the meaning, the payload) of the number
+- **exponent** - controls how far and in which direction to move the decimal point in the fraction
+
+The **base** part we may omit by just agreeing on what it will be equal to. In our case, we'll be using `2` as a base.
+
+Instead of using all 16 bits (or 32 bits, or 64 bits) to store the fraction of the number, we may share the bits and store a sign, exponent, and fraction at the same time. Depending on the number of bits that we're going to use to store the number we end up with the following splits:
+
+| Floating-point format | Total bits | Sign bits | Exponent bits | Fraction bits | Base |
+| :-------------------- | :--------: | :-------: | :-----------: | :--------------: | :--: |
+| [Half-precision](https://en.wikipedia.org/wiki/Half-precision_floating-point_format) | 16 | 1 | 5 | 10 | 2 |
+| [Single-precision](https://en.wikipedia.org/wiki/Single-precision_floating-point_format) | 32 | 1 | 8 | 23 | 2 |
+| [Double-precision](https://en.wikipedia.org/wiki/Double-precision_floating-point_format) | 64 | 1 | 11 | 52 | 2 |
+
+With this approach, the number of bits for the fraction has been reduced (i.e. for the 16-bits number it was reduced from 16 bits to 10 bits). It means that the fraction might take a narrower range of values now (losing some precision). However, since we also have an exponent part, it will actually increase the ultimate number range and also allow us to describe the numbers between 0 and 1 (if the exponent is negative).
+
+> For example, a signed 32-bit integer variable has a maximum value of 2³¹ − 1 = 2,147,483,647, whereas an IEEE 754 32-bit base-2 floating-point variable has a maximum value of ≈ 3.4028235 × 10³⁸.
+
+To make it possible to have a negative exponent, the IEEE 754 standard uses the [biased exponent](https://en.wikipedia.org/wiki/Exponent_bias). The idea is simple - subtract the bias from the exponent value to make it negative. For example, if the exponent has 5 bits, it might take the values from the range of `[0, 31]` (all values are positive here). But if we subtract the value of `15` from it, the range will be `[-15, 16]`. The number `15` is called bias, and it is being calculated by the following formula:
+
+```
+exponent_bias = 2 ^ (k−1) − 1
+
+k - number of exponent bits
+```
+
+I've tried to describe the logic behind the converting of floating-point numbers from a binary format back to the decimal format on the image below. Hopefully, it will give you a better understanding of how the IEEE 754 standard works. The 16-bits number is being used here for simplicity, but the same approach works for 32-bits and 64-bits numbers as well.
+
+
+
+> Checkout the [interactive version of this diagram](https://trekhleb.dev/blog/2021/binary-floating-point/) to play around with setting bits on and off, and seeing how it would influence the final result
+
+## Code examples
+
+- See the [bitsToFloat.js](bitsToFloat.js) for the example of how to convert array of bits to the floating point number (the example is a bit artificial but still it gives the overview of how the conversion is going on)
+- See the [floatAsBinaryString.js](floatAsBinaryString.js) for the example of how to see the actual binary representation of the floating-point number in JavaScript
+
+## References
+
+You might also want to check out the following resources to get a deeper understanding of the binary representation of floating-point numbers:
+
+- [Here is what you need to know about JavaScript’s Number type](https://indepth.dev/posts/1139/here-is-what-you-need-to-know-about-javascripts-number-type)
+- [Float Exposed](https://float.exposed/)
+- [IEEE754 Visualization](https://bartaz.github.io/ieee754-visualization/)
diff --git a/src/algorithms/math/binary-floating-point/__tests__/bitsToFloat.test.js b/src/algorithms/math/binary-floating-point/__tests__/bitsToFloat.test.js
new file mode 100644
index 0000000000..53afe691a2
--- /dev/null
+++ b/src/algorithms/math/binary-floating-point/__tests__/bitsToFloat.test.js
@@ -0,0 +1,32 @@
+import { testCases16Bits, testCases32Bits, testCases64Bits } from '../testCases';
+import { bitsToFloat16, bitsToFloat32, bitsToFloat64 } from '../bitsToFloat';
+
+describe('bitsToFloat16', () => {
+ it('should convert floating point binary bits to floating point decimal number', () => {
+ for (let testCaseIndex = 0; testCaseIndex < testCases16Bits.length; testCaseIndex += 1) {
+ const [decimal, binary] = testCases16Bits[testCaseIndex];
+ const bits = binary.split('').map((bitString) => parseInt(bitString, 10));
+ expect(bitsToFloat16(bits)).toBeCloseTo(decimal, 4);
+ }
+ });
+});
+
+describe('bitsToFloat32', () => {
+ it('should convert floating point binary bits to floating point decimal number', () => {
+ for (let testCaseIndex = 0; testCaseIndex < testCases32Bits.length; testCaseIndex += 1) {
+ const [decimal, binary] = testCases32Bits[testCaseIndex];
+ const bits = binary.split('').map((bitString) => parseInt(bitString, 10));
+ expect(bitsToFloat32(bits)).toBeCloseTo(decimal, 7);
+ }
+ });
+});
+
+describe('bitsToFloat64', () => {
+ it('should convert floating point binary bits to floating point decimal number', () => {
+ for (let testCaseIndex = 0; testCaseIndex < testCases64Bits.length; testCaseIndex += 1) {
+ const [decimal, binary] = testCases64Bits[testCaseIndex];
+ const bits = binary.split('').map((bitString) => parseInt(bitString, 10));
+ expect(bitsToFloat64(bits)).toBeCloseTo(decimal, 14);
+ }
+ });
+});
diff --git a/src/algorithms/math/binary-floating-point/__tests__/floatAsBinaryString.test.js b/src/algorithms/math/binary-floating-point/__tests__/floatAsBinaryString.test.js
new file mode 100644
index 0000000000..efb8a2ba5e
--- /dev/null
+++ b/src/algorithms/math/binary-floating-point/__tests__/floatAsBinaryString.test.js
@@ -0,0 +1,20 @@
+import { floatAs32BinaryString, floatAs64BinaryString } from '../floatAsBinaryString';
+import { testCases32Bits, testCases64Bits } from '../testCases';
+
+describe('floatAs32Binary', () => {
+ it('should create a binary representation of the floating numbers', () => {
+ for (let testCaseIndex = 0; testCaseIndex < testCases32Bits.length; testCaseIndex += 1) {
+ const [decimal, binary] = testCases32Bits[testCaseIndex];
+ expect(floatAs32BinaryString(decimal)).toBe(binary);
+ }
+ });
+});
+
+describe('floatAs64Binary', () => {
+ it('should create a binary representation of the floating numbers', () => {
+ for (let testCaseIndex = 0; testCaseIndex < testCases64Bits.length; testCaseIndex += 1) {
+ const [decimal, binary] = testCases64Bits[testCaseIndex];
+ expect(floatAs64BinaryString(decimal)).toBe(binary);
+ }
+ });
+});
diff --git a/src/algorithms/math/binary-floating-point/bitsToFloat.js b/src/algorithms/math/binary-floating-point/bitsToFloat.js
new file mode 100644
index 0000000000..6d1ef0d851
--- /dev/null
+++ b/src/algorithms/math/binary-floating-point/bitsToFloat.js
@@ -0,0 +1,119 @@
+/**
+ * Sequence of 0s and 1s.
+ * @typedef {number[]} Bits
+ */
+
+/**
+ * @typedef {{
+ * signBitsCount: number,
+ * exponentBitsCount: number,
+ * fractionBitsCount: number,
+ * }} PrecisionConfig
+ */
+
+/**
+ * @typedef {{
+ * half: PrecisionConfig,
+ * single: PrecisionConfig,
+ * double: PrecisionConfig
+ * }} PrecisionConfigs
+ */
+
+/**
+ * ┌───────────────── sign bit
+ * │ ┌───────────── exponent bits
+ * │ │ ┌───── fraction bits
+ * │ │ │
+ * X XXXXX XXXXXXXXXX
+ *
+ * @type {PrecisionConfigs}
+ */
+const precisionConfigs = {
+ // @see: https://en.wikipedia.org/wiki/Half-precision_floating-point_format
+ half: {
+ signBitsCount: 1,
+ exponentBitsCount: 5,
+ fractionBitsCount: 10,
+ },
+ // @see: https://en.wikipedia.org/wiki/Single-precision_floating-point_format
+ single: {
+ signBitsCount: 1,
+ exponentBitsCount: 8,
+ fractionBitsCount: 23,
+ },
+ // @see: https://en.wikipedia.org/wiki/Double-precision_floating-point_format
+ double: {
+ signBitsCount: 1,
+ exponentBitsCount: 11,
+ fractionBitsCount: 52,
+ },
+};
+
+/**
+ * Converts the binary representation of the floating point number to decimal float number.
+ *
+ * @param {Bits} bits - sequence of bits that represents the floating point number.
+ * @param {PrecisionConfig} precisionConfig - half/single/double precision config.
+ * @return {number} - floating point number decoded from its binary representation.
+ */
+function bitsToFloat(bits, precisionConfig) {
+ const { signBitsCount, exponentBitsCount } = precisionConfig;
+
+ // Figuring out the sign.
+ const sign = (-1) ** bits[0]; // -1^1 = -1, -1^0 = 1
+
+ // Calculating the exponent value.
+ const exponentBias = 2 ** (exponentBitsCount - 1) - 1;
+ const exponentBits = bits.slice(signBitsCount, signBitsCount + exponentBitsCount);
+ const exponentUnbiased = exponentBits.reduce(
+ (exponentSoFar, currentBit, bitIndex) => {
+ const bitPowerOfTwo = 2 ** (exponentBitsCount - bitIndex - 1);
+ return exponentSoFar + currentBit * bitPowerOfTwo;
+ },
+ 0,
+ );
+ const exponent = exponentUnbiased - exponentBias;
+
+ // Calculating the fraction value.
+ const fractionBits = bits.slice(signBitsCount + exponentBitsCount);
+ const fraction = fractionBits.reduce(
+ (fractionSoFar, currentBit, bitIndex) => {
+ const bitPowerOfTwo = 2 ** -(bitIndex + 1);
+ return fractionSoFar + currentBit * bitPowerOfTwo;
+ },
+ 0,
+ );
+
+ // Putting all parts together to calculate the final number.
+ return sign * (2 ** exponent) * (1 + fraction);
+}
+
+/**
+ * Converts the 16-bit binary representation of the floating point number to decimal float number.
+ *
+ * @param {Bits} bits - sequence of bits that represents the floating point number.
+ * @return {number} - floating point number decoded from its binary representation.
+ */
+export function bitsToFloat16(bits) {
+ return bitsToFloat(bits, precisionConfigs.half);
+}
+
+/**
+ * Converts the 32-bit binary representation of the floating point number to decimal float number.
+ *
+ * @param {Bits} bits - sequence of bits that represents the floating point number.
+ * @return {number} - floating point number decoded from its binary representation.
+ */
+export function bitsToFloat32(bits) {
+ return bitsToFloat(bits, precisionConfigs.single);
+}
+
+/**
+ * Converts the 64-bit binary representation of the floating point number to decimal float number.
+ *
+ * @param {Bits} bits - sequence of bits that represents the floating point number.
+ * @return {number} - floating point number decoded from its binary representation.
+ */
+export function bitsToFloat64(bits) {
+ return bitsToFloat(bits, precisionConfigs.double);
+}
diff --git a/src/algorithms/math/binary-floating-point/floatAsBinaryString.js b/src/algorithms/math/binary-floating-point/floatAsBinaryString.js
new file mode 100644
index 0000000000..aa907ac049
--- /dev/null
+++ b/src/algorithms/math/binary-floating-point/floatAsBinaryString.js
@@ -0,0 +1,61 @@
+// @see: https://en.wikipedia.org/wiki/Single-precision_floating-point_format
+const singlePrecisionBytesLength = 4; // 32 bits
+
+// @see: https://en.wikipedia.org/wiki/Double-precision_floating-point_format
+const doublePrecisionBytesLength = 8; // 64 bits
+
+const bitsInByte = 8;
+
+/**
+ * Converts the float number into its IEEE 754 binary representation.
+ * @see: https://en.wikipedia.org/wiki/IEEE_754
+ *
+ * @param {number} floatNumber - float number in decimal format.
+ * @param {number} byteLength - number of bytes to use to store the float number.
+ * @return {string} - binary string representation of the float number.
+ */
+function floatAsBinaryString(floatNumber, byteLength) {
+ let numberAsBinaryString = '';
+
+ const arrayBuffer = new ArrayBuffer(byteLength);
+ const dataView = new DataView(arrayBuffer);
+
+ const byteOffset = 0;
+ const littleEndian = false;
+
+ if (byteLength === singlePrecisionBytesLength) {
+ dataView.setFloat32(byteOffset, floatNumber, littleEndian);
+ } else {
+ dataView.setFloat64(byteOffset, floatNumber, littleEndian);
+ }
+
+ for (let byteIndex = 0; byteIndex < byteLength; byteIndex += 1) {
+ let bits = dataView.getUint8(byteIndex).toString(2);
+ if (bits.length < bitsInByte) {
+ bits = new Array(bitsInByte - bits.length).fill('0').join('') + bits;
+ }
+ numberAsBinaryString += bits;
+ }
+
+ return numberAsBinaryString;
+}
+
+/**
+ * Converts the float number into its IEEE 754 64-bits binary representation.
+ *
+ * @param {number} floatNumber - float number in decimal format.
+ * @return {string} - 64 bits binary string representation of the float number.
+ */
+export function floatAs64BinaryString(floatNumber) {
+ return floatAsBinaryString(floatNumber, doublePrecisionBytesLength);
+}
+
+/**
+ * Converts the float number into its IEEE 754 32-bits binary representation.
+ *
+ * @param {number} floatNumber - float number in decimal format.
+ * @return {string} - 32 bits binary string representation of the float number.
+ */
+export function floatAs32BinaryString(floatNumber) {
+ return floatAsBinaryString(floatNumber, singlePrecisionBytesLength);
+}
diff --git a/src/algorithms/math/binary-floating-point/images/02-half-precision-floating-point-number-explained.png b/src/algorithms/math/binary-floating-point/images/02-half-precision-floating-point-number-explained.png
new file mode 100644
index 0000000000000000000000000000000000000000..1bc0a5b83596b9479525362d67af1dfb5168ef70
GIT binary patch
literal 352613
zcmeFZXIN8Rw>7MElww4RQiWSYdhg8wC<2O_gdWO`ARPkI!GMZVRlq_K1O=pp4xxhr
z3P^|0Ly_L4gckT#K%e{ZIi7Rg-`{n9Sg)|N_gr(0Ip&yS?WZ?&G-!{VIdgJ<>DO=lldX)
zlD{l{MfR}gOp=dYxh9-PMrCsH1}V?7qPJ1O&3{lSr=BxF=4xK#hwzi2(GP9`HwHD_}R_<#NxS28kEZLjV7X_5Zhp_`mr7&pYA&;`4v;`46D{{}cY8
zoNYGdZgi1d`AYqT%KN=$L2~xVjnuzj_m6oXdJVvLq@+Q==1=&x
zRvjtm)VVGI&t}uR^>Eo_cZ^x)X6FdELlt48z-Q}+>mp_<1?^9m`!Fj%`P!nxEQlRu
zgHV9{kJZTZB{>QB=Q1&w|G;#_hlAao=jQ?!aEZcesy(!q1IUldqiM49sVRDNku=1s6r6RM
zh=!+>EtU!pMkrOLed_l2RQ9L#3v{E!r`}b|&t*pT7&=z8V7KSc2}J`AWow_$D?4)(
z-HH5D*j`&6t*O@M@bx`^_|123nFaxaY}sfDQj*z3nu_G}A;YuF?PQa9g5nSW^U
zc;sGQ>K!6fbd}Yy+&LJFY^cgFdeqSI;ri`|(Vory(-A#5g{5+dc;Ah_nGnRTdFevY
zfVx0)`|a~NIKQ0_RhuDIS4BK(j;CZh%3t|IrLF$^7!`%iWXV0LgP6U(jnYt>)xA8I
zFc&?wB>61KZiJ3i5?7>!#8HNU8yjCFiVr!b#0UokEC
zW?JA+ONHd&Vv&_uv^jSWB?ckzul7$^>Z1oMe?ErhzB-jvq_*@&!uH6b`Y{Tfjq=WI
z3`DQQ$xI$Uh@^yZWKjC;4B+0z)_=R0Makx*DoLnrAw!CXs^?Htl=ZK|{>XKZ=fKy)f6V^88A0%`n!r~bdVwg+37z8a2DVwxl<(pYy>jA`uu4^mZ>xvfa*M)J9EaERyL(IN
zdxd|UKr<=tZH^oA8|VI!nXw3Su~UoB8mwqE`~oTmDy0=h>ZP{3TZ4vIQ)X1;BPp7iC6442=
zR*Asg{i%n11LwcLRzvTXv+i~0KM?OQhfyX+YgCaxnP3_SfZiKB6L!&TkQ0QL!p8Ci
zORNk(E89BY(Z3ywqOJYbam*8wfDj|eKN)3rzepQ#?>Lj-)#9Q118Z(t5tCO&
zLM2+RiujBkpL*{Qeew?=AX)|hCSPI0OXnbKZH|8rV1&_RYAd`XZD6DUnJ9ESQ%~A1
z_5=KNxTO>HQlbXerD7ubOrI3EKkT=&kWo?TZEzNet(ta!So1JC)r}%*4hzv>d#+5F
zx$$bC&xA~q>T}^n?Qs#U8@{u*ug}{v|B*9Ef@JIsO}=#yi)t-uuw6EsrUJyY$rX^R
z-wV;c_VNn_oxH5K=ct>JD81*%(b`9(hJ9UI%B`pU2FeFBCau0%+^V;aTi9)cSH7T=
zpH6g!eat=$>2<>zcRoG;R+gutTl-I6JsC*EDHd}3!|*WhK0EI7%`JzUd6#NY-^=ap
z(%Kmf(VS+ML1e3vM80O`$MP23jDC=M3NX;iZPeTX`^y!4**=RHx}>iH1J%PL@M~K
z#^SX6*WvzBNJ7u(3N`pyj+v72a8|@48}2`3o@ojZ{k=Bb-X3hsE`}2{nN!k;aPZWk
zFmA(A*O_YJrJPT67hnr{2XzFs#hvr_*B1qLeR*3QYzwb%q4esYvfi4M@Zvw9akB&f
zV^3+Wn9Bzl#(Pm!)aj)9Jtx+w%c9Hwtm~~gVkI=SA>;5_u34M6Qt`IgPUcyKbD6*i
z;qK)Yd(t|M0;C!#I5$Wa&@W3f5mH44v>E>$u(`K4iZN602~`uQr~XVXwIljy~h8Mt^#4uC~$#rlxbB`47{j^E?2|J`4We
z?oX_NEfPF#$>ebuH%ghL80V+(=gn6D@UK@s_t;^e*1*HVSUWv7%UmWJTP`B@x3O@A
z&1*NjZuOgo2z7v}ax-fr#``!$&qLOg9CMD(RTZcQEc>r15AX@MRcegbU}iw8-&V;B=AGb~$&RcE#D+HzNR5P)S)hq_fAx!S(Br97#Pq04_FKUON4
z(2#c_$Zz7*RCl6WWsiZao1eN?2Q04GxkbIotC(eJOBzp3dj8&HZ9hZsr$5d5e_g-_
z)qha|1gYh_$8#8NE3krFN1t+io=Hu3+oFUYtbCVv@!XY79ukHi4liq4v(%IT6u?dv
zDltA9DBI14NiHuSY;qgD7Ra)~Jp$O-g2vtpg}!sAd+NT)g7j6?P!_40m`g%H8)
zvA6*z2w)L?th7g#A
zjr91-C2d4STN1cW$Tn^<98JG{L#c3O^=|JVe}IYeVnnHw@34lR#3k#%BHf0p;z6pH
zjMy4oA#*{VwEn-X?FKo9DAcO&ci9>kv2tg!Szy;->t`VA4H#CWUDOHp_Eg@6()2J>
zQ>fTZ1h;5oD@J$LP4G{2C!feL49ByI4=6w)1ZBjPIg@y;TYV~kR(BX%xlyPdcscjS
z?aa?T^?}1w^;b;aee8}RBh6?@+uw=l^kB595~`ng>%BPRlR*_EUFc#Gb=pm%E$bMYY}5!LpcnFhWoUkE>cnU}#Eh+T)hp0D$8#K|XT?%dC$VIEhW^;Bu$GU}GQ
zeV5H5L6j;)^t2mmsz!THk)QHssk7S>uSQ2xc9;aH>RYFDr+ni*xmolyzKOY!_m?0t
z2bdcE#N$OPKyG&`6nPygPX+)1cl`?>e+M&ms~aEXm(hb9k(-J`p7H#aW@@VAy}mTn
z><3DO>m^j~8AKnP0)9{J;osbX60^2z|A~(h&o5WTc-21KhMT3$SQyZOpoW
zH`|mS!<4Us;9RI7S|b)&RhCV4O+(cw%ASp5Xd$GV!NRRdx;W+1`}X=lsU+{p&*^FQ
zab;pl<6hV+ETzF^rlyQSJK_9b4bl_G|J3#H0S2I_{#E&qp;hyPr`msIVPy82MCFnW
zZf~PlgYNqGOAeNSmoT1fpYKUfqfdtW)d!>OACZ(b_;)#(3a>E?L(GG7Y`e4O%P%yt
zW4AihWkqWfAi*{~Wc{s5wN8-WjQm3OhpbpxCSOh|w%#HQJWC;C+?))3jKMt-_b@&f
zqkWlUd%~utOpCUtQ(XV-Ng7GYKfy0c5Fib*QQa30uqQ=}iGXTol*EDJ5~ABumXE~rE5
za*T($bN8}oPaq0EQH&RpH*o;1`J_;EN^5PdfKt5dFUIL$
zo*DLus*~AK*kkstl)TrvDo{R~9R*`eYemWBo4MH+w5wOK?^AiGd7LLXT8G6KIyn}Z2Gl^7)4$0R7>RI{T^D%qSFsUoUArq^^M81Se#(0)2lB;
zmry+Z3c%hZC9OpnGM2s?JS?pgT;H%O%z7$(?y^|J_~!D3Nsrxq52$0G9LG+Ce5*!<
z`W62qS}|-{Yv1w{vG5=8Y$JWII18yB-Il%%M#4Ul--MtDHzfPMShc^`f=wHUvCV$-
zc0JST!zRA3)$hJRkzL=_(K1=AS8H(z{pksl@71LAS{iK5S5hHV?tu=JBi|<_mclD{W@rw^^
z*Mu&qK&<&0HbT2MlGr~LQIXYSLI@9qaT;olalOtsUgOT`4K`G^9h!_HMxDF;h}pR
zgJm`(IWtWUe+EK$TKS6FMT5Qll`XnLS|K`i(=#gT`##Q07)BE+I-;Yn5Vg@~l~B-k
zH}(TzV*tIu?*kzj1fT7=NXZ_RG`MIV<&qqi5{PQYuC}W97ryHQU5Cao(UD5{BiY8{qCbRTE?$ox@Lh;%q7vOb}7&Gi?S@
z2mr~s>>$+W15yNty
zy2ZQp3K@RnJ5UxLFEVA!t0`nqRC33$*f&2SovTzY*E%6wue_0A!HDFoSHbQPOJB#J
z&76^7KEFwK5fcMXy$T6ZE`*A`J}y14Z~|igM2^mY2sdQjmUI37^}kt;rmb5(148
z(0pzd*!fciQM$Z}%sV~QYEWuI7p*K^UO3myhc@H5i-totO?6G)IGM&n@r?z(QL0Yv
zJII>6^ot**!BZcd(M9uEwgk#!Yorx}R|FVdW+I0--ikovTON^q;x&mkzT4fn_#?xJ
zXRM@jv^A-v1U3ny3-t?i(H8P1I4ZE{Jv<7Owpm4r_@P=rPwy`C{A3Eoo
zfHK7#Kg>B*OO!qx#pJe$)x>*0(i0iigiOjkrhB`LA^glPtWs?ZVGbZPp0(0Wsx5-)
z)*vvFg?7uSvl(}q9{a`2UvEzxwDm}Cq0+o#td`~O(Udt4UxyA_)+c{lzSTM9$2w)6
z-Av`7eihl3)oeSEVM2+tM|%^RqFI@=ACiC&%y!8v+Fp6Htxn7NGCs(joYX?9ii%YI
ziAXV&x?Ih3MSge~OW}@%n3Vy2OH9bPv|!b7C~L;lw17uz%qOJ#NOF7-r=LgZ=2!^a
zHp$dOuoYIR
z-aD>B#V>9R9k~urs(5hm?AJ$s$D}2Hm5US*uwrVEVK@02<{vNL)I7>p+_ELsoYO1-
zi_Mf^{;sgrc3A=KB9vdZ{x=X+I7)4!e>8TziFJgMAnfBpJ^V(8&
z*`j9qE2_RB|9t}Hc4ilT0MOrb*$;py!y5g5!;xP#Q_omcv@P>rz4`ZmGttN60!e2d
zK64T9lq%GO)jU6rn6FZ7B$X{UgWpjlz!vh
z#4x2B^>bghTZ{5WsU{R^NSnW|y6vj!dPE7-V~z
zo3$!&-d*VeQW;+H_SJ>_#n!hM317pmb*|IeG?WCQay3mdUt%kwX(`mXL<3M21J5-$
z-ss3pL=AR*-1V)gZv4BCG@VR6|4|?6zt$e`KcvLTBJE*!keFAUNkPgZDkk`ZIfG*X
z6z*sxO7=FG9yfEr$1{J;VE2p$V$+hvrcaWGeab{gxS&d9QyOiZn;!b5N5KQK^RGKd
z6-v)GXI+9xr!h{g{g`N?ykD4w8N9PIAj^!Lx*SRfY$v*0I+ty@(EWL(;kYIIQkIRRAWI3>#QOsg9PNwx?#7#sN7tCD&Czg
zlfQ9(D0ssWl+p{8<{@x8e5Ej^Y(6IxJuGBWXjC9n$vmM}X3ki*DN~<>bB5Z_E{d?|
z!CRdFlpS{0QL=c0QCbT?<*q2xO@r7pwUbWrLzyFfpSm&%gkBBN9eaw2FgJmPT
z=T=#ygzE?haf8xl%mejk=%>uZLf(sx5zYPWrPIPD{mLc2v?E-;8<86Nn>gw;1{5*O;_?ghl@`3J&Mb
zkoY48WbLKJrRXmU#RfzXcfxhKhEhgec<9mkafHe=duWd0@zOT=
zI5(Mr(f&3$<&Ikpf=fJHX}Ovde*DG;2j}?73_0iPc;JvYWT2dgV(o<4X{1WxsJz)~<9a%}gVV
zi)nHOS(yux*abSM<%=J!nAJ(E8T;i0;CV?e8?9d_gb(g5x)j!qGfK>xFOgw?7*aIR
z$c8=U=r*aAyn0=
zqRZ3C5sSNK*YQO_1#3Cxn@cjfny|l%%g%BCL@VQZ$q{bs2958WC~jCgPVrJG$J%gd
z4`4FSlhg02^9;#YfDW^x^UOKUZ~*(rc|*VU=lL
zj;e8Yj7bf(XS$_^o7>Z5{!N
z9yUZxb&L}uy{$l^Sokx;&e7Ol*RUmJy8Me_Em>^vbIq?}Z$lgTLll|O5aE95c>_kX
zbdPhhIYPzaCehVUeYANM)pc5LA?xO^n~nBFU=lSdxIpr5MRRnkNNVAEEYE?0f_4|O
zvv?~A3LlqS^r}4QRW$oc@ZW~u1-e!uz3<6LcPi9nO)j#bO2*tOD||z`kMShJWp<@C
zMV)RgXM?4y>OS>pEG5=q+aBkQz_H;XmcN5$LAj@?yMTg}6R3i&V^7bgY|1FFDs8t%
zEc!6+m*M=Ie5+c-Fya|LRo=K^3&Ol|$!}ZFxAq|H<
zX*Y+hO2ff)5vQ;=Gli4D^@bS!ah`4q)CB<98y(wD#vdk9E=Fn=hqV_$iZ)&~i9!l1?eb0P|OHp!Bp>Gh=aGBDN
z#6HPsjhAt&KR?y09$&E#_t4a|ycD0;By9L$22ySaB)0r{h+hbNXV`NpzR%a&o#hlw
zX!Vd9vvHTFu~UIrg73yP1t2TgOyIqTmU2u@-H$?HFvYF!k?@Qv_qtm9;vwmHw;uhB
zLa_kUxX*`W5M?AbxiQl5ExYKwqYcuRqA}ugkA=%3Y?DFX6FW${<4j2!n~i3^AmczBceJ$`I23-;a~6eh#I+h40>U)t5J@#u-{`qo
z!;f7|pK@9BlFXLtxT63l0t+?|8_PeXmQAql>KmxMMnyq)tT4JTJerh;P0wwPnZ{=X
zMcLs1N`paL4lcuor+jm8O4&Wy2GE2JL+xCIC9%Ng0e%G$T*sdf#Fo=I(*asbp
z5iZj*MZ0sNiZQWB8(vX+5Y$06=v6e4m#ME2j}b??T@7=2|lt|-m@&AouN$8dyaPB*_~2J
zpi|jhhVHH2jkSL{CRJWBS}o$g)ig5_NT2O045g+}udy`QA5a$sS^kiR4+F?ii$Dar
zbT(a+;DEHMsg`z&R+=NRgrzq>q6HY+Sm{>#VrU}503N>`E1!apvmd&1#J{u!R5z26?(eqlEBa0dAg%$8-THfXn)ajNMvBqKhvVi6n?I*Y
zMdU8@%No=%lIHxJ_wrWd+#Mv@ft>Kwxq%&Sb+z85S+qE=8_XFbH&!d?G-IdC3(nWJiK)yzCN10P
zs)#W)M6)||@Q{ogXBK9Y71Rd7tXF}V8CCjhRU5ltOU9}P%OeQ0yMtf94Gp?ggvomk
zNK)5S`yH(yw$4Dj^E0gCGRq8R&cH+aVyGyD_4D2{v}mH`u$-Ea>YZ6$L+(
z9!mT^(U>$by&Hfc%6Y+6q5HFNpb$|W4z-S;wuw95l9X!QP;~bTh+E#pbR$-tQ~4e%
zW2f9&>R{&upC5lCCFZC7*wM=vxr%O){l2Y8mv6Sv(v7&UJk=7G5~zi_k3F5i8*#cQ
zxW6PTW*+XYZ~rz#O=-noG%fY(32QP^p3qYQ)Y4mxqr6HkmQudTw6Q#xqVL(xYJC__
z&YkWpOk^w$Gv~$Xwo!ENWB`f~;Fo)B7z}_Eo|V`gaqMM*(o($atFkL=%vA0j+5n@V
zGKP&M{F#YiW%aAeUw9(oA|E80nl7e~>=08%6hSujb_2Ihz;zNQY(%@qR)^riZ#_8b
z1&IU$O=wkO)pG6e&U3GfUfdsaZg`=1|EJkxoBBJ)$SYc|f)9qgy*H(=N@a$n#@{zE
zD6rNw9O8pI#OGWQ&g}lYDaCl}qr|>u&H8-Q+^THz<3a`a{>Rj}F?6yc5A3kS4SF%f
zs4Sn>!86EgT-hO`sI-3)(>pLJ8lu_;Og#g7?%bzXGDg*`GoC&$jpV@Oad)v~91FK-
zDm>>NCeZ&n7N3iVPf(Bx9Q0ND6&|8i3mh%^uzOy@EFJ*Y&`d9g#bW}n!#9ZtcYVtZ
zM*$X=1wByX6-KK8ehUoLd2}xW-AiV}2?XlC_549wx_V{gk%*63>3m+(Ewb5SprCnn
z@PGR~PI<&Q`OI8L#I&gF@4BwkF@retf6R;^{A}Zue!Nb`1UL(>ntm|Wxyz~n4UK?zq^ldC&*AGMo
zvp2CQ(4UrHtQ~oRX3#W{R-S&ctk~$FrJEz0C@lsAs^Zp(Y^^qQ*)C}MJPUDU<%@3U
zxn1Ry-hLViCbuh9JX#o_=eX_}`xDl8bn2)m)%C>p*s;7UvcmV)iO!DdG?HA+5k|Pt
z^UAGnjwxA1{We`=Y&U+}X%%BYAUxnc=;KL%0>svZQWmcPA-{umT#{2GqG3cX)z*LP9Yt1s44cU
zbXkg_466l*(@0NY^%6Of0JGBwB1`--6pB1+a@5#;y_&ew!jN^(a1hq2Z!N?
zBRycJv2OlbDz#7Mp-Pkdq4*^k7&H(Cz}&FN*s`(l8+vR9l4(@#;f#wWdnKs<0*sbn
zMQP9R3^Z(SZXP|@WxOaVYy&5^k?(r2&iM7Cj{_m$W86IY$sL0G~RSXeH`@tgI@Tgc46*25s%X5-~D
ztntNFgoTvYE)UPu8KclSt8xPwJ9ws^ZW-E)6IrPvn{zFKXa-^sKT|-&CDJD2|N|(F{jP2Jr_g6S)3~}4AkGMyn1_{5vZK;
zxv=paVtz#o%E1AkPu>BD6*uq;!<=c%CgiybAgE?D!}wLS%Vl*%Q{{w^I?VtGQ*(uM
z#jAG?#26CUM9QT_Biq?C5PNHj;i+tA5V$$H3pLeX;pO68JFaC&?gLYm*3LpPBG^BK
zD7##@0{w#x8j{WM0C46|ukDH#va_Mlk4lUE%s%T9%fK_pT1YhlFU?op>xh#VPBwZ=
zPO8z4JQ&Z0-X3Y)n{Vy#-<$HkzlcrP8Jr5ww{iQefm0*~1wTKq
zPGk$QR4=<7jb}5}3r%YR-l+i==E{5$4N+ug0)c@qUs?Zhn*!
z&JI$qXtD*Phskbk^v1|_yNc#~#KuZXg+rUZVz6@i=|yH;g!2GDd~Qq2jbR{
z--0b-z!T~mopmi@aO+ft?(qEqduR;Y8|R$Ge}>l1Vz@O3X@4sKB}PFoL3{5L@a`s$
zyn!O~o>pcsC*NxrOo}j#abCar3e5*O&F@)3!zPa||Iz4L#|U?w4Q(^eWa%wiKmG$q
zcpScK?HLu@#nZOCtY%-P@rlvLUI`n=j16b@au=}FG@8Ux!PF7;h13+`*A0{o_H(-G
zO2cz3!r#}c1^HIO#yR|_`|&5viybHOTJ+v5x&w?`;wzUQiTuqu9pOoH=TMU2)#1V)
zsd{SK$H#}sQI9e{&%z=Q8}GM0LmCS^|6V*Zfe35|3PR*)tnTEc+YNxp-ZYGjqr~LJ
z0P%aW=3Nknd=Fd(7Eh0{HGWu0Q4w5XV{E^Wz#53DG{MiglacW}xx>q)=SCB=#6&