Skip to content

Commit 1282ade

Browse files
committed
docs(string): add algorithms for strings
1 parent 07846d6 commit 1282ade

9 files changed

+293
-0
lines changed

README.md

+23
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,31 @@ These ones use a key-value structure in which the key corresponds to an index on
8383

8484
- [**Linear Probing Hash:**](./algorithms/searching/hash-table/LinearProbingHash.js) It is a hash table which we store keys and values in separated arrays in order to get an easy search match later.
8585

86+
## String
87+
88+
String is necessary for almost all kind of communication, we deal with it in information processing, genomics, communication systems and programming systems. Being minded about that, we have the following algorithms:
89+
90+
### String Sorting
91+
92+
We have some sorting methods for string that take advantage of special properties of strings to develop sorts for string keys that are more efficient than the general-purpose sorts that we have seen above.
93+
94+
- [**LSD String Sort:**](./algorithms/string/sorting/LSDStringSort.js) It is known as least-significant-digit string sort. It sorts an array of strings from left word letter to right using a key-indexed count array (so it means that it only sort fixed-length strings).
95+
96+
- [**MSD String Sort:**](./algorithms/string/sorting/MSDStringSort.js) It is known as most-significant-digit string sort. We use key-indexed counting to sort the strings according to their first character, then, recursively sort the sub-arrays corresponding to each character. It is similar to LSD string sort, but, it can be done without a fixed-word length.
97+
98+
- [**Three-way String Quicksort:**](./algorithms/string/sorting/ThreeWayStringQuickSort.js) It is an implementation of quicksort for strings, so it deals with partitioning the string array into sub-arrays while sorting it.
99+
100+
### String Searching
101+
102+
We can implement some search methods that can take benefits of using it into a string. Some of them are shown below:
103+
104+
- [**Trie Symbol Table:**](./algorithms/string/searching/TrieSymbolTable.js) It is a basic symbol table that creates a search tree using the characters of the string keys that allow us to use the characters of the search key to guide the search.
105+
106+
86107
## TODO
87108

88109
- [TOPIC] Adding Analysis of Algorithms
89110
- [REFACTOR] Adding complexity order for all algorithms
90111
- [TOPIC] Graphs
112+
- [TOPIC/ALGORITHM] String -> String Sort -> LSD String Sort
113+
- [TOPIC/ALGORITHM] String -> String Sort -> MSD String Sort

algorithms/string/Char.js

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
class Node {
2+
#value
3+
#next
4+
5+
constructor () {
6+
this.#value = null
7+
this.#next = []
8+
}
9+
10+
get value() {
11+
return this.#value
12+
}
13+
14+
get next() {
15+
return this.#next
16+
}
17+
18+
set value(value) {
19+
this.#value = value
20+
}
21+
}
22+
23+
class TrieSymbolTable {
24+
#root
25+
26+
constructor () {
27+
this.#root = null
28+
}
29+
30+
#getNodeValue (node, key, d) {
31+
if (!node) {
32+
return null
33+
}
34+
35+
if (d === key.length) {
36+
return node
37+
}
38+
39+
const letter = key.charAt(d)
40+
41+
return this.#getNodeValue(node.next[letter], key, d + 1)
42+
}
43+
44+
get (key) {
45+
const node = this.#getNodeValue(this.#root, key, 0)
46+
47+
if (!node) {
48+
return null
49+
}
50+
51+
return node.value
52+
}
53+
54+
#putNode (node, key, value, d) {
55+
if (!node) {
56+
node = new Node()
57+
}
58+
59+
if (d === key.length) {
60+
node.value = value
61+
62+
return node
63+
}
64+
65+
const letter = key.charAt(d)
66+
67+
node.next[letter] = this.#putNode(node.next[letter], key, value, d + 1)
68+
69+
return node
70+
}
71+
72+
put (key, value) {
73+
this.#root = this.#putNode(this.#root, key, value, 0)
74+
}
75+
}
76+
77+
module.exports = TrieSymbolTable
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const assert = require("assert")
2+
const TrieSymbolTable = require("./TrieSymbolTable.js")
3+
4+
const trieSymbolTable = new TrieSymbolTable()
5+
6+
trieSymbolTable.put("Guilherme", "abc")
7+
trieSymbolTable.put("Mota", "eae")
8+
trieSymbolTable.put("teste", "oi")
9+
10+
assert.deepEqual(trieSymbolTable.get("Guilherme"), "abc")
11+
assert.deepEqual(trieSymbolTable.get("NotExistentKey"), null)
12+
+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
class LSDStringSort {
2+
sort(wordArray, wordSize) {
3+
const arraySize = wordArray.length
4+
5+
const R = 256
6+
7+
const auxiliaryArray = []
8+
9+
for (let d = wordSize - 1; d >= 0; d--) {
10+
const count = []
11+
12+
for (let i = 0; i < arraySize; i++) {
13+
const word = wordArray[i]
14+
15+
if (!word) {
16+
continue
17+
}
18+
19+
const letter = word.charAt(d)
20+
21+
const countIndex = parseInt(letter, 16) + 1
22+
23+
if (!count[countIndex]) {
24+
count[countIndex] = 0
25+
}
26+
27+
count[countIndex]++
28+
29+
}
30+
31+
for (let r = 0; r < R; r++) {
32+
count[r + 1] += count[r]
33+
}
34+
35+
for (let i = 0; i < arraySize; i++) {
36+
const word = wordArray[i]
37+
38+
if (!word) {
39+
continue
40+
}
41+
42+
const letter = word.charAt(d)
43+
44+
const countIndex = parseInt(letter, 16) + 1
45+
46+
if (!count[countIndex]) {
47+
count[countIndex] = 0
48+
}
49+
50+
auxiliaryArray[count[countIndex]] = wordArray[i]
51+
52+
count[countIndex]++
53+
}
54+
55+
for (let i = 0; i < arraySize; i++) {
56+
wordArray[i] = auxiliaryArray[i]
57+
}
58+
}
59+
}
60+
}
61+
62+
module.exports = LSDStringSort
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
const assert = require("assert")
2+
const LSDStringSort = require("./LSDStringSort.js")
3+
4+
const lsdStringSort = new LSDStringSort()
5+
6+
const unorderedValues = [
7+
"4PGC938",
8+
"2IYE230",
9+
"3CIO720",
10+
"1ICK750",
11+
"1OHV845",
12+
"4JZY524",
13+
"1ICK750",
14+
"3CIO720",
15+
"1OHV845",
16+
"1OHV845",
17+
"2RLA629",
18+
"2RLA629",
19+
"3ATW723"
20+
]
21+
22+
lsdStringSort.sort(unorderedValues, 7)
23+
24+
console.log(unorderedValues)
25+
26+
// assert.deepEqual(unorderedValues[0], 1)
27+
// assert.deepEqual(unorderedValues[1], 2)
28+
// assert.deepEqual(unorderedValues[2], 3)
29+
// assert.deepEqual(unorderedValues[3], 4)
30+
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
const Char = require("../Char")
2+
const InsertionSort = require("../../sorting/elementary-sorts/InsertionSort")
3+
4+
class MSDStringSort extends Char {
5+
#radix
6+
#M
7+
#auxiliaryArray
8+
9+
constructor () {
10+
this.#radix = 256
11+
this.#M = 15
12+
this.#auxiliaryArray = []
13+
}
14+
15+
#sortBySubArrays (array, lowerIndex, higherIndex, d) {
16+
if (higherIndex <= lowerIndex + this.#M) {
17+
const insertionSort = new InsertionSort()
18+
}
19+
}
20+
}
21+
22+
module.exports = MSDStringSort
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
const Sort = require("../../sorting/Sort")
2+
const Char = require("../Char")
3+
4+
class ThreeWayStringQuickSort extends Char {
5+
#sortHelper = new Sort()
6+
7+
sort(array = []) {
8+
const arraySize = array.length
9+
10+
this.#sortBySubArrays(array, 0, arraySize - 1, 0)
11+
}
12+
13+
#sortBySubArrays(array, lowerIndex, higherIndex, d) {
14+
if (higherIndex <= lowerIndex) {
15+
return
16+
}
17+
18+
let lt = lowerIndex
19+
let gt = higherIndex
20+
let index = lowerIndex + 1
21+
22+
const value = this.charAt(array[lowerIndex], d)
23+
24+
while (index <= gt) {
25+
const comparableValue = this.charAt(array[index], d)
26+
27+
if (comparableValue < value) {
28+
this.#sortHelper.exchangeValues(array, lt++, index++)
29+
} else if (comparableValue > value) {
30+
this.#sortHelper.exchangeValues(array, index, gt--)
31+
} else {
32+
index++
33+
}
34+
}
35+
36+
this.#sortBySubArrays(array, lowerIndex, lt - 1, d)
37+
38+
if (value >= 0) {
39+
this.#sortBySubArrays(array, lt, gt, d + 1)
40+
}
41+
42+
this.#sortBySubArrays(array, gt + 1, higherIndex, d)
43+
}
44+
}
45+
46+
module.exports = ThreeWayStringQuickSort
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const assert = require("assert")
2+
const ThreeWayStringQuickSort = require("./ThreeWayStringQuickSort.js")
3+
4+
const threeWayStringQuickSort = new ThreeWayStringQuickSort()
5+
6+
const unorderedValues = ["R", "B", "W", "W", "R", "W", "B", "R", "R", "W", "B", "R"]
7+
8+
threeWayStringQuickSort.sort(unorderedValues)
9+
10+
assert.deepEqual(unorderedValues[0], "B")
11+
assert.deepEqual(unorderedValues[1], "B")
12+
assert.deepEqual(unorderedValues[2], "B")
13+
assert.deepEqual(unorderedValues[3], "R")
14+
assert.deepEqual(unorderedValues[4], "R")
15+
assert.deepEqual(unorderedValues[5], "R")
16+
assert.deepEqual(unorderedValues[6], "R")
17+
assert.deepEqual(unorderedValues[7], "R")
18+
assert.deepEqual(unorderedValues[8], "W")
19+
assert.deepEqual(unorderedValues[9], "W")
20+
assert.deepEqual(unorderedValues[10], "W")
21+
assert.deepEqual(unorderedValues[11], "W")

0 commit comments

Comments
 (0)