Gary Bernhardt@garybernhardtDon't listen to people who tell you that the core topics in a CS degree are irrelevant. I mean... I haven't exactly needed the things I learned (and forgot) in my required "Chemistry of Materials" course. And my "Software Engineering" course was silly. But the core is real.17:38 PM  21 May 2020
@Cor3ntin Just try java, javascript or C# for a while, I did, I really prefer the problems I have in C++. Namely problems I can just solve instead of problems you can only work around or are just going to have to life with.20:39 PM  22 Apr 2020
Prerequisite (โ๐)
If you're reading this article right now, please considered to read our Part 01: BigO Notation, Part 02: JavaScript Unique Part, Part 03: JavaScript Numbers to Part 10: Searching and Sorting Algorithm

Part Table of Contents Description 01 BigO Notation By the end of this chapter, you will understand how to analyze an implementation of an algorithm with respect to both time (execution time) and space (memory consumed). 02 JavaScript Unique Parts BigO is important for analyzing and comparing the efficiencies of algorithms. The analysis of BigO starts by looking at the code, and, applying the rules, applying the rules is because to simplify the BigO notation linear or quadratic rule is not enough. 03 JavaScript Numbers This part 3 will focus on JavaScript number operations, number representation, Number objects, common number algorithms, and random number generation. 04 JavaScript Strings This part 4 will focus on strings, JavaScript String object, and the String objectโs builtin functions. You will learn how to access, compare, decompose, and search strings for commonly used reallife purposes. In addition, the chapter will explore string encoding, decoding, encryption, and decryption. 05 JavaScript Arrays As a JavaScript developer, you will use the array often; it is the most commonly used data structure. Arrays in JavaScript come with a lot of builtin methods. By the end of this part, you will understand arrays and choose the right method 06 JavaScript Object This part will focus on what JavaScript objects are, how they are declared, and how their properties can be changed. In addition, this part will cover how JavaScript classes are implemented using prototypal inheritance. Also this part will be short. 07 JavaScript Memory Management A variable takes up some memory. In C, the programmer allocate and deallocate memory manually. In contrast, modern JavaScript engines have garbage collectors that delete unused variables. However, there are pitfalls(unexpected) that developers can fall into(โ) This part will show these unexpected and present techniques to help the garbage collector minimize the memory problems. 08 Recursion This part 8 introduces the concept of recursion and recursive algorithms(Remember they are different, we will discuss them later(๐)). We will also discuss the definition of recursion and fundamental rules for recursive algorithms. 09 Sets This part focuses on the concepts of sets from both a mathematical definition and on the implementation. Also, Common set operations, as well as their implementations, are covered in great detail (๐ก). 10 Searching and Sorting This part 10 focuses on searching and sorting for arrays. By the end of this part 10, you will understand how to use sorting and searching algorithms for arrays. Also, this article is a bit complicated for beginners, so as much as possible the visual aids is your friend (๐). (๐) 11 Hash Tables A hash table is a fixedsized data structure in which the size is defined at the start. This part 11 explains how hash tables work, and the method of generating a unique key. By the end of this part 11, you will understand various hashing techniques and know how to implement a hash table. (๐) 12 Stacks and Queues This part 12 covers stacks and queues(pronounce as kyooz (๐)) not (kwewe) okay? hehehe (๐ ); both are data structures used in the implementation of complex data structures. You'll learn what the stacks and queues are, how they're used, when they're used, and how to implement them (๐) Let's go! (๐ฅ๐ฅ๐ฅ) 13 Linked Lists A linked list is a data structure in which each node (or element) points to another node. Unlike arrays, which have a fixed size, a linked list is a dynamic data structure. By the end of this part 13, you will understand how to implement and work with linked lists. And oh! (๐ฎ) There are two types of linked lists: singly (โก๏ธ) and doubly (โ๏ธ). Letโs examine the singly linked list first.(๐) Let's go! (๐ฅ๐ฅ๐ฅ) 14 Caching Caching is the process of storing data into temporary memory so that it can be easily retrieved for later use if it is required again. As an example, a database keeps data cached to avoid rereading the hard drive, and a web browser caches web images to avoid redownloading. In this part 14, two caching techniques will discussed: LFU and LRU caching. 15 Trees A general tree data structure is composed of nodes with children nodes. The top node is called the root node. This part 15 will explore different types of trees such as binary trees, binary search trees, and selfbalancing binary search trees. First, this part 15 will cover what trees are and how they are structured. Then, it will cover methods of traversing(crossing or taking a zigzag path) the tree data structure in detail. Finally, you will learn about binary search trees and selfbalancing binary search trees to understand how to store searchable data. (๐) 16 Heaps A heap is an important data structure that returns the highest or lowest element in O(1) time. This part 16 will focus on explaining how heaps are implemented as well as how to work with them. One example is heap sort, which is a sorting algorithm based on heaps. 17 Graphs In this Part 17, you will learn graph basics, including fundamental terminology and graph types. The Part 17 will also cover working with these different graph types and methods of representing graphs in data structures. Finally, algorithms for traversing, searching, and sorting graphs are explored to solve problems such as finding the shortest path between two graph nodes. (๐) 18 Advance Strings Part 18 will cover more complex string algorithms than covered in the previous section. Now that you have heard of certain other data models or structures, they should be easier to comprehend. Specifically, Part 18 will focus on string searching algorithms. (๐) 19 Dynamic Programming Dynamic programming involves breaking down problems into their subproblems. Solving the subproblems and saving those results into memory to access them whenever a repeated problem needs to be solved, the algorithmic complexity decreases significantly (โฌ๏ธ). To explain dynamic programming, letโs re examine the Fibonacci sequence that was discussed in Part 8. Then Part 19 will cover the rules of dynamic programming and walk you through some examples to make the concepts more concrete. (๐) 20 Bit Manipulation Bit manipulation is an advanced topic that JavaScript developers typically do not need to know. However, you should learn a bit about bit manipulation if you want to implement highperformance serverside code. Understanding bit manipulation requires some knowledge of digital logic. Any introductory course in discrete math or circuits would be helpful to understand these concepts.
Part 11: Hash Tables (๐ฑ ๐ฅ ๐)
A hash table is a fixedsized data structure in which the size is defined at the start. This part 11 explains how hash tables work, and the method of generating a unique key. By the end of this part 11, you will understand various hashing techniques and know how to implement a hash table. (๐)
Introducing Hash Tables (๐๐)
Hash tables are excellent for quick storage and retrieval of data based on keyvalue pairs. In JavaScript, JavaScript objects work this way by defining a key and value.

Figure 111. Simple hash table overview
Figure 111 shows each key and its associated item. A hash table contains two functions: put() and get(). put() is used for storing data, while get() is used for retrieving data from the hash table. Both of these functions have a time complexity of $O(1)$ .
localStorage is an example of a data structure based on a hash table. It is a native JavaScript object. It lets developers persist(preserve) data. Let's see an example of localstorage:
Example:
localStorage.setItem("testKey", "testValue");
//
console.log(localStorage.getItem("testKey")); // prints "testValue"
Note (๐): click remix to edit. And view app to view the result. To see the localstorage example please see the script.js
Hashing Technique (โก๏ธ๐ข)
The most important part of a hash table is the hash function. The hash function converts a key into an index that stores the data. The three(3) primary requirements for a good hash function are as follows(see below):
 Deterministic: Equal keys produce equal values.
 Efficiency: It should be $O(1)$ in time.
 Uniform distribution: It makes the most use of the array. (๐)
The first technique for hashing is to use prime numbers. With prime numbers, a uniform distribution of the index can be guaranteed.
Prime Number Hashing (1๏ธโฃโก๏ธ๐ข)
Remember: Prime numbers in hashing are important. Modulus division using prime numbers yields an array index in a distributed(uniform) manner. Let's see an example below:
We have Prime Numbers:
$5,\space 7,\space 4,\space 13,\space 15,\space 17$
and a Modulus Number:
$11$
Collisions can be seen with $15$ and $4$ yielding the same key because they're not even a prime numbers. This is the list of prime numbers just below:
Handling this collision is discussed later below. As of now, I just want to remind you that such collision exist in hash table. What is important here is that modulus by prime numbers guarantees the best distribution for a fixed size, okay? (๐). A small modulus number such as $4$ by a nonprime number which is $6$ and $10$ guarantees only a range from $0$ to $3$ and leads to a large number of collisions (๐ฅ). Let's see an example below:
We have NonPrime Numbers:
$6,\space 10$
and a Modulus Number:
$4$
Remember: This is the first(or basic) hashing technique. Let's see an example hash table below:

Figure 112. Hash table of size 11, with all empty elements
This hash table of size 11, with all empty elements is the same as the example JavaScript code below(now look (๐)):
Example:
[
{ keys: "", values: "" }, // 0
{ keys: "", values: "" }, // 1
{ keys: "", values: "" }, // 2
{ keys: "", values: "" }, // 3
{ keys: "", values: "" }, // 4
{ keys: "", values: "" }, // 5
{ keys: "", values: "" }, // 6
{ keys: "", values: "" }, // 7
{ keys: "", values: "" }, // 8
{ keys: "", values: "" }, // 9
{ keys: "", values: "" } // 10
]
In this example below(look first), we will only use 4 index for the sake of simplifying my explanation (๐ ), now in the example below, letโs hash the following keyvalue pairs:
Example:
[
{ keys: 7, values: "hi" }, // 0
{ keys: 23, values: "hello" }, // 1
{ keys: 43, values: "sunny" }, // 2
{ keys: 31, values: "weather" },// 3
]
// We have index 0, 1, 2, 3. With a total of 4
We have Prime Numbers:
$7,\space 23,\space 43,\space 31$
and a Modulus Number:
$11$
The resulting hash table is shown in Figure 113 below:

Figure 113. Hash table after inserting the value pairs
Now letโs hash nonprime number 18 with modulus 11:
Results: $18 \space \% \space 11 = 7$
This is a problem because 7 already exists in the index and causes an index collision. With a perfect hashing function, there are no collisions. Therefore, there are strategies for handling collisions needed for hash tables which is: Linear Probing, Quadratic Probing, and Double Hashing. Let's see them below. Let's go! (๐ฅ๐ฅ๐ฅ)
Probing (โก๏ธโ๏ธ๐)
To work around collisions, probing finds the next available index in the array. The linear probing technique resolves conflicts by finding the next available index via incremental trials ( $n + 1$ ), while quadratic probing uses quadratic functions to generate incremental trials ( $n^{2}$ ). Don't confuse them for now, we will see more example below! (๐)
Linear Probing (๐ขโก๏ธโก๏ธ๐ก)
Linear probing works by finding the next available index by incrementing one index ( $n + 1$ ). For example, in the case of 18 hashing to the same key of 7, 18 would be hashed into key 8 because thatโs the next empty spot. See the example below:

Figure 114. Hash table 1 after using linear probing
When the get( key ) function is used, it has to start at the original hash and then iterate. We will discuss later what get( key ) function is just below.
Note (๐): The main disadvantage of linear probing is it easily creates clusters(A grouping of a similar number), which are bad because they create more data to iterate through.
Quadratic Probing (๐ขโ๏ธโ๏ธ๐ก)
Quadratic probing is a good technique for addressing the cluster issue (๐). Quadratic probing uses perfect squares instead of incrementing by 1, and this helps to evenly distribute the indices, as shown in Figure 115 below:

Figure 115. Linear probing (on top) and quadratic probing (on bottom)
Double Hashing (โก๏ธ๐๐โฌ ๏ธ)
Another great way to distribute the keys is by having a second hashing function that hashes the result from the original. These are the three primary requirements for a good second hash function:
 Different: It needs to be different
 Efficiency: It should still be $O(1)$ in time.
 Nonzero: It should never evaluate to zero.
A second hashing function is as follows. See below:
Here, $x$ is the result from hashing the first, and $R$ is less than the size of the hash table. Each hash collision is resolved by the following, where $i$ is the iteration trial number:
Hash Table Implementation (๐ข๐จ)
In this section, you will apply three techniques to the same example. The following are the example keyvalue pairs that will be used:
[
{ keys: 7, values: "hi" }, // 0
{ keys: 23, values: "hello" }, // 1
{ keys: 37, values: "sunny" }, // 2
{ keys: 47, values: "weather" }, // 3
{ keys: 59, values: "wow" }, // 4
{ keys: 73, values: "forty" }, // 5
{ keys: 89, values: "happy" }, // 6
{ keys: 97, values: "sad" } // 7
]
Using Linear Probing (๐ขโก๏ธโก๏ธ)
Letโs start the example with simple linear probing:
Example:
function HashTable(size) {
this.size = size;
this.keys = this.initArray(size);
this.values = this.initArray(size);
this.limit = 0;
}
HashTable.prototype.initArray = function (size) {
var array = [];
for (var i = 0; i < size; i++) {
array.push(null);
}
return array;
}
HashTable.prototype.put = function (key, value) {
if (this.limit >= this.size) throw 'hash table is full'
var hashedIndex = this.hash(key);
// Linear probing
while (this.keys[hashedIndex] != null) {
hashedIndex++;
hashedIndex = hashedIndex % this.size;
}
this.keys[hashedIndex] = key;
this.values[hashedIndex] = value;
this.limit++;
}
HashTable.prototype.get = function (key) {
var hashedIndex = this.hash(key);
while (this.keys[hashedIndex] != key) {
hashedIndex++;
hashedIndex = hashedIndex % this.size;
}
return this.values[hashedIndex];
}
HashTable.prototype.log = function () {
return {
keys: this.keys,
values: this.values
};
}
HashTable.prototype.hash = function (key) {
// Check if int
if (!Number.isInteger(key)) throw 'must be int';
return key % this.size;
}
var exampletable = new HashTable(13);
exampletable.put(7, "hi");
exampletable.put(23, "hello");
exampletable.put(37, "sunny");
exampletable.put(47, "weather");
exampletable.put(59, "wow");
exampletable.put(73, "fourty");
exampletable.put(89, "happy");
exampletable.put(97, "sad");
exampletable.log();
Execution:
Here is the result on my computer. Take a look carefully (๐):
Note (๐): I advice, get a piece of paper or a white board, and draw them, I also advice to draw the code on the paper instead on your computer. You are more likely to remember them. Okay?(๐ ๐)
Using Quadratic Probing (๐ขโ๏ธโ๏ธ)
Now, we will just change the put() and get() methods from the linear probing to use quadratic probing. Let's see the example below:
Example:
HashTable.prototype.put = function(key, value) {
if (this.limit >= this.size) throw 'hash table is full'
var hashedIndex = this.hash(key),
squareIndex = 1;
// quadratic probing
while (this.keys[hashedIndex % this.size] != null) {
hashedIndex += Math.pow(squareIndex, 2);
squareIndex++;
}
this.keys[hashedIndex % this.size] = key;
this.values[hashedIndex % this.size] = value;
this.limit++;
}
HashTable.prototype.get = function(key) {
var hashedIndex = this.hash(key),
squareIndex = 1;
while (this.keys[hashedIndex % this.size] != key) {
hashedIndex += Math.pow(squareIndex, 2);
hashedIndex = hashedIndex % this.size;
squareIndex++;
}
return this.values[hashedIndex % this.size];
}
Execution:
Here is the result on my computer. Take a look carefully (๐):
Note (๐): I advice, get a piece of paper or a white board, and draw them, I also advice to draw the code on the paper instead on your computer. You are more likely to remember them. Okay?(๐ ๐)
If you look at the output. This result is more uniform than the result from linear probing. (๐ก)
Using DoubleHashing in Linear Probing (โก๏ธ๐๐)
Finally, letโs combine doublehashing and linear probing. Recall the common second hash function, $hash2(x) \space = \space R \space โ \space (x \space \% \space R)$ , where $x$ is the result from hashing the first time, and $R$ is less than the size of the hash table. Let's look at the example below:
Example:
HashTable.prototype.put = function(key, value) {
if (this.limit >= this.size) throw 'hash table is full'
var hashedIndex = this.hash(key);
while (this.keys[hashedIndex] != null) {
hashedIndex++;
hashedIndex = hashedIndex % this.size;
}
this.keys[hashedIndex] = key;
this.values[hashedIndex] = value;
this.limit++;
}
HashTable.prototype.get = function(key) {
var hashedIndex = this.hash(key);
while (this.keys[hashedIndex] != key) {
hashedIndex++;
hashedIndex = hashedIndex % this.size;
}
return this.values[hashedIndex];
}
HashTable.prototype.hash = function(key) {
if (!Number.isInteger(key)) throw 'must be int'; // check if int
return this.secondHash(key);
}
HashTable.prototype.secondHash = function(hashedKey) {
var R = this.size  2;
return R  hashedKey % R;
}
Execution:
Here is the result on my computer. Take a look carefully (๐):
Note (๐): I advice, get a piece of paper or a white board, and draw them, I also advice to draw the code on the paper instead on your computer. You are more likely to remember them. Okay?(๐ ๐)
Again, doublehashing results in a more uniform distributed array than the result from linear probing. Both quadratic probing and doublehashing are great techniques to reduce the number of collisions in a hash table. Remember: There are collision algorithms far more advanced than these techniques, but they are beyond the scope of this article. (Learn more)
Summary (๐)
A hash table is a fixedsized data structure in which the size is defined. Hash tables are implemented using a hash function to generate an index for the array. A good hash function is deterministic, efficient, and uniformly distributive. Hash collisions should be minimized with a good uniformly distributive hash function, but having some collisions is unavoidable (๐). Hash collisionhandling techniques include: linear probing, quadratic probing, and doublehashing. The next part explores Stacks and Queues, which are dynamically sized data structures. See you soon! (๐)
Discussion
So, hash table is a dictionary in Python?
Good question, yes, they are called hash map library in python instead of hash tables. (๐)