By Paul Ryan

Crazy technology house

Original: https://blog.logrocket.com/kn

No reprint without permission

## What are we going to talk about?

In JavaScript, data structures are often ignored or rarely touched. But for many large factories, you need to have a deep understanding of how to manage data. Mastering the data structure can also help you with your work when solving problems.

In this article, we will discuss and implement the data structure as follows:

- Stack
- queue
- Linked list
- Hashtable
- tree

## Stack

The first data structure is stack. It’s very similar to a queue, you’ve probably heard of it before**Call stack**, which is the method JavaScript uses to handle events.

The stack looks like this:

The last item on the stack will be the first one to be removed. This is called LIFO. A good example is the back button in a web browser: add each page you view to the stack, and when you click back, the current page (the last page added) pops up from the stack.

There are enough theories. Let’s look at some code:

```
class Stack {
constructor() {
//Create the stack structure, which is an empty object
this.stack = {}
}
//Push a value into the top of the stack
push(value) {
}
//Pop the value at the top of the stack and return
pop() {
}
//Reads the last value in the stack, but does not delete it
peek() {
}
}
```

I have commented on the above code, now let’s implement it together. The first way is`push`

。

Think about what you need to do in this way:

- We need to accept a value
- Then add the value to the top of the stack
- You should also track the length of the stack so that you know the index of the stack

If you can try it on your own, it’s great. It’s complete`push`

The method is as follows:

```
class Stack {
constructor() {
this._storage = {};
This. _length = 0; // this is the stack size
}
push(value) {
//Add value to top of stack
this._storage[this._length] = value;
//Since a value has been added, the length should also be increased by 1
this._length++;
}
/// .....
}
```

I bet it’s easier than you think. There are many structures like this that sound much more complex than they actually are.

Now is`pop`

Method.`pop`

The goal of the method is to delete the last value added to the stack and return it. If you can, please try to implement it yourself first:

```
class Stack {
constructor() {
this._storage = {};
this._length = 0;
}
pop() {
// we first get the last val so we have it to return
const lastVal = this._storage[--this._length]
// now remove the item which is the length - 1
delete this._storage[--this._length]
// decrement the length
this._length--;
// now return the last value
return lastVal
}
}
```

Cool! It’s almost finished. The last one is`peek`

Function that looks at the last item in the stack. This is the simplest feature: you only need to return the last value. The achievement is:

```
class Stack {
constructor() {
this._storage = {};
this._length = 0;
}
/*
* Adds a new value at the end of the stack
* @param {*} value the value to push
*/
peek() {
const lastVal = this._storage[--this._length]
return lastVal
}
}
```

So it and`pop`

The method is very similar, but does not delete the last item.

Yes! The first data structure has been implemented. Then there is the queue, which is very similar to the stack.

## queue

Next we’ll talk about queues – hopefully the stack will still be clear in your mind, because it’s very similar to queues. The main difference between stacks and queues is that queues are first in, first out (FIFO).

It can be represented graphically as follows:

So the two main approaches are`enqueue`

And`dequeue`

。 Data is added to the end of the team and removed from the head of the team. To better understand it, start to implement queues.

The core code structure is as follows:

```
class Queue {
constructor() {
//Like before, we provide an object for data structure
//And there's a variable to hold the length
this.queue = {}
this.length = 0
//This is a new variable to track the head
this.head = 0
}
enqueue(value) {
}
dequeue() {
}
peek() {
}
}
```

First realize`enqueue`

Method. The goal is to add an item to the end of the team.

```
enqueue(value) {
//Use the value parameter to add the key of length + head to the object
this.queue[this.length + this.head] = value;
this.length++
}
```

This is a very simple way to add a value at the end of the queue, but you may`this.queue[this.length + this.head] = value;`

Confused.

Suppose the queue looks like this`{14 : 'randomVal'}`

。 When adding this content, the next value we want is`15`

, so it should be length (1) + head (14), that is`15`

。

The next thing to do is`dequeue`

：

```
dequeue() {
//Gets a reference to the first value to return
const firstVal = this.queue[this.head]
//Now remove it from the queue
delete this.queue[this.head]
this.length--;
//And eventually add our head to the next node
this.head++;
}
```

The last thing to do is`peek`

Method, very simple:

```
peek() {
//Just return the value
return this.queue[this.head];
}
```

Queue implementation completed.

## Linked list

Let’s talk about powerful lists first. This is much more complicated than the structure above.

Maybe your first question is why do you use linked lists? Linked list is mainly used for languages without dynamic resizing arrays. Linked lists organize items in order, with one item pointing to the next.

Each node in the list has one`data`

Value and one`next`

Value. In the following figure`5`

yes`data`

Value,`next`

The value points to the next node, that is, the value is`10`

Node.

Visually, it looks like this:

In an object, the`LinkedList`

It looks like the following

You will see the last value`1`

Of`next`

The value is`null`

Because this is`LinkedList`

At the end.

So how to achieve it?

Let’s create a value with`1`

、 `2`

and`37`

Of`LinkedList`

。

```
const myLinkedList = {
head: {
value: 1
next: {
value: 2
next: {
value: 37
next: null
}
}
}
};
```

Now we know how to create it manually`LinkedList`

, but coding is needed`LinkedList`

Method.

The first thing to note is,`LinkedList`

Just a bunch of nested objects!

When constructing a`LinkedList`

We need a`head`

And one`tail`

, they all point to the head at first (because`head`

It’s the first and last one.

```
class LinkedList {
constructor(value) {
this.head = {value, next: null}
this.tail = this.head
}
}
```

The first way to do this is to`insert`

, which is used to insert a value at the end of the list.

```
//Insert will be added to the end of the list of links
insert(value) {
/*Create a node*/
const node = {value, next: null}
/*Set the next property of tail to the reference of the new node*/
this.tail.next = node;
/*The new node is now the tail node*/
this.tail = node;
}
```

The most confusing line up there might be`this.tail.next = node`

。 This is because when we add a new node, we also want the current`tail`

Pointing to the new`node`

, the node will become a new`tail`

。 First insert`node`

Of the head`next`

The pointer will point to the new node, as in the constructor, where the`this.tail = this.head`

。

You can also go to this website to view the graphical presentation, which will help you understand the insertion process (press`esc`

Get rid of annoying pop ups).

The next method is to delete the node. The first thing we have to decide is that the parameter is a value（`value`

）Or to nodes（`node`

）In an interview, it’s best to ask the interviewer first. We passed a “value” in our code. Removing nodes from the list by value is a slow process because you have to traverse the entire list to find the value.

I do this:

```
removeNode(val) {
/*Start with head*/
let currentNode = this.head
/*We need to keep references to the previous node*/
let previousNode
/*When there is a node, it means that the tail is not reached*/
while(currentNode) {
/*If you find the value you want, exit the loop*/
if(currentNode.value === val) {
break;
}
/*Set currentnode to previousnode without finding a value*/
previousNode = currentNode
/*Get the next node and assign it to the currentnode*/
currentNode = currentNode.next
}
/*Undefined returned because no node with this value was found*/
if (currentNode=== null) {
return false;
}
//If the node is head, set head to the next value
Head node
if (currentNode === this.head) {
this.head = this.head.next;
return;
}
/*Delete a node by setting it to the previous node*/
previousNode.next = currentNode.next
}
```

`removeNode`

How to make us`LinkedList`

We have a good understanding of the way we work.

So again, let’s start with variables`currentNode`

Set to`LinkedList`

Of`head`

Because this is the first node. Then create a file named`previousNode`

Placeholder variable that will be`while`

Used in a loop. Condition from`currentNode`

start`while`

Loop, as long as it exists`currentNode`

, it will run all the time.

stay`while`

The first step in the loop is to check for values. If not, the`previousNode`

Set to`currentNode`

And will`currentNode`

Set to the next node in the list. Continue this process until you find the value I need to find or traverse the node.

stay`while`

After the loop, if not`currentNode`

Then return`false`

, which means no nodes were found. If there is one`currentNode`

, the`currentNode`

Whether it is`head`

。 If so, put`LinkedList`

Of`head`

Set to the second node, which will become`head`

。

Finally, if`currentNode`

Not the head, just`previousNode`

Set to point`currentNode`

Ahead`node`

, which will be removed from the object`currentNode`

。

Another common method (the interviewer may also ask you) is`removeTail`

。 This method is as it says, but it’s removed`LinkedList`

The tail node of. This is much easier than the above method, but it works in a similar way.

I suggest you try it on your own, and then look at the following code (to make it more complicated, we don’t use it in the constructor`tail`

）：

```
removeTail() {
let currentNode = this.head;
let previousNode;
while (currentNode) {
/*Tail is the only node without the next value, so if there is no next value, then the node is tail*/
if (!currentNode.next) {
break;
}
//Get reference to previous node
previousNode = currentNode;
//Move to next node
currentNode = currentNode.next;
}
//To remove the tail, set previousnode.next to null
previousNode.next = null;
}
```

These are`LinkedList`

Some of the main methods. There are various ways to link lists, but with the knowledge learned above, you should be able to implement them yourself.

## Hashtable

Next comes a powerful hash table.

A hash table is a data structure that implements associative arrays, which means it maps keys to values. A JavaScript object is a “hash table” because it stores key value pairs.

Visually, it can be expressed as follows:

Before we discuss how to implement hash tables, we need to discuss*The importance of hash functions.*The core concept of a hash function is that it accepts input of any size and returns a fixed length hash value.

`hashThis('i want to hash this') => 7`

Hash functions can be very complex or straightforward. Each file on GitHub is hashed, which makes the search of each file very fast. The core idea behind hash functions is that given the same input, the same output will be returned.

After introducing the hash function, it’s time to discuss how to implement the hash table.

The three actions to be discussed are`insert`

、`get`

Last but not least`remove`

。

The core code to implement the hash table is as follows:

```
class HashTable {
constructor(size) {
//Defines the size of the hash table, which will be used in the hash function
this.size = size;
this.storage = [];
}
insert(key, value) { }
get() {}
remove() {}
//This is how the hash key is calculated
myHashingFunction(str, n) {
let sum = 0;
for (let i = 0; i < str.length; i++) {
sum += str.charCodeAt(i) * 3;
}
return sum % n;
}
}
```

Now the first solution is`insert`

。`insert`

The code to the hash table is as follows (for simplicity, this method will simply handle conflicts):

```
insert(key, value) {
//Get the index in the array
const index = this.myHashingFunction(key, this.size);
//Handling conflicts - if the hash function returns the same index for different keys,
//In complex hash functions, conflicts are likely to occur
if (!this.storage[index]) {
this.storage[index] = [];
}
//Push new key value pair
this.storage[index].push([key, value]);
}
```

Call like this`insert`

Method:

```
const myHT = new HashTable(5);
myHT.insert("a", 1);
myHT.insert("b", 2);
```

What do you think our hash table will look like?

You can see that the key value pair is inserted into the index of the table`1`

and`4`

Place.

Now remove from hash table

```
remove(key) {
//First, get the index of the key. Remember,
//Hash function will always return the same index for the same key
const index = this.myHashingFunction(key, this.size);
//Remember that we can have multiple arrays at an index (unlikely)
let arrayAtIndex = this.storage[index];
if (arrayAtIndex) {
//Traverse all arrays at this index
for (let i = 0; i < arrayAtIndex.length; i++) {
// get the pair (a, 1)
let pair = arrayAtIndex[i];
//Check whether the key matches the parameter key
if (pair[0] === key) {
delete arrayAtIndex[i];
//Work is done, so exit the loop
break;
}
}
}
}
```

Last but not least`get`

Method. This sum`remove`

The method is the same, but this time, let’s go back`pair`

Instead of deleting it.

```
get(key) {
const index = this.myHashingFunction(key, this.size);
let arrayAtIndex = this.storage[index];
if (arrayAtIndex) {
for (let i = 0; i < arrayAtIndex.length; i++) {
const pair = arrayAtIndex[i];
if (pair[0] === key) {
return pair[1];
}
}
}
}
```

I don’t think it’s necessary to perform this operation because it’s related to`remove`

The method is the same.

You can think of it as not as complicated as it initially seemed. This is a kind of data structure used everywhere, and also a well understood structure!

## Binary search tree

The last data structure is the infamous binary search tree.

In a binary search tree, each node has zero, one, or two child nodes. The left is called the left child node, and the right is called the right child node. In a binary search tree, the children on the left must be smaller than the children on the right.

You can describe a binary search tree like this:

The core classes of the tree are as follows:

```
class Tree {
constructor(value) {
this.root = null
}
add(value) {
//We will implement it below
}
}
```

We will also create a`Node`

Class to represent each node.

```
class Node {
constructor(value, left = null, right = null) {
this.value = value;
this.left = left;
this.right = right;
}
}
```

Implementation below`add`

Method. I’ve commented on the code, but if you find it confusing, remember that all we have to do is start at the root and check each node’s`left`

and`right`

。

```
add(value) {
//If there is no root, create a
if (this.root === null) {
this.root = new Node(value);
return;
}
let current = this.root;
// keep looping
while (true) {
//Left if the current value is greater than the passed in value
if (current.value > value) {
//If there are left child nodes, loop again
if (current.left) {
current = current.left;
} else {
current.left = new Node(value);
return;
}
}
//Less value, so we're on the right track
else {
// right
//If there are left child nodes, run the loop again
if (current.right) {
current = current.right;
} else {
current.right = new Node(value);
return;
}
}
}
}
```

New testing`add`

Method:

```
const t = new Tree();
t.add(2);
t.add(5);
t.add(3);
```

Now the tree looks like this:

For better understanding, let’s implement a method to check whether the tree contains values.

```
contains(value) {
//Get root node
let current = this.root;
//When nodes exist
while (current) {
//Check whether the current node is the value
if (value === current.value) {
Return true; // exit the function
}
//Determine the next current node by comparing our value with current.value
//Left if small, right otherwise
current = value < current.value ? current.left : current.right;
}
return false;
}
```

`Add`

and`Contains`

It is the two core methods of binary search tree. Understanding these two methods can help you to solve problems in your daily work better.

## summary

I’ve covered a lot in this article, and mastering this knowledge will put you in a good position for an interview. I hope you can learn something and pass the technical interview easily (especially the annoying white board interview).

#### This article starts with WeChat official account: front-end pioneer.

#### Welcome to scan the two-dimensional code to pay attention to the official account, and push you every day to send fresh front-end technical articles.

### Welcome to other great articles in this column:

- Deep understanding of shadow DOM v1
- Step by step to teach you how to use webvr to realize virtual reality games
- 13 modern CSS frameworks to improve your development efficiency
- Get started bootstrap Vue
- How does the JavaScript engine work? Everything you need to know from call stack to promise
- Websocket practice: real time communication between node and react
- 20 interview questions about Git
- In depth analysis of console.log of node.js
- What is node.js?
- Build an API server with node.js in 30 minutes
- Object copy of JavaScript
- Programmers can’t earn 30K a month before they are 30 years old. Where to go
- 14 best JavaScript data visualization Libraries
- 8 top level vs code extensions for the front end
- Node.js multithreading full guide
- Four schemes and implementation of transforming HTML into PDF

- More articles