data structure
array
Method
//I. array var arr = []; // Additive elements arr.push(1, 2); // [1,2] // Insert first arr.unshift(0); // [0, 1, 3] // Tail deletion arr.pop(); // [0, 1] // Head deletion arr.shift(); // [1] // Array merging [1].concat([2]) // [1,2]
iterator
- every every method iterates over each element in the array until it returns false.
- Some is similar to each other, but some iterates over each element of the array until the function returns true
- The results of forEach and for loops are the same
- Map returns a new array [1,2]. map (o = > o * 2) / [2,4]
- Filter returns a new array [1,2]. filter (o = O > O > 1) / [2]
- reduce [1,2].reduce((result, current) => result + current) // 3
- for of for (let n of numbers) { console.log((n % 2 === 0) ? 'even' : 'odd')};
-
entries
const numbers = [1,2,3]; let aEntries = numbers.entries(); // Iterator for Getting Key-Value Pairs console.log(aEntries.next().value); // The value of position 0 at [0, 1] is 1 console.log(aEntries.next().value); // The value of [1, 2] position 1 is 2 console.log(aEntries.next().value); // The value of [2, 3] position 2 is 3
-
keys
const numbers = [1,2,3]; console.log(Object.keys(numbers)); // ['0','1','2'];
-
values
const numbers = [1,2,3]; console.log(Object.values(numbers)); // [1,2,3]
- Array.from
- Array.of
- fill
- copyWithin
- sort
- find
- findIndex
- includes
Stack
A stack is an ordered set that follows the principle of last-in, first-out.
Realization
function Stack() { let items = []; // Adding elements to the stack this.push = function(element) { items.push(element); } // Remove elements from stack this.pop = function() { return items.pop(); }; // View stack top elements this.peek = function() { return items[item.length - 1]; } // Check if the stack is empty this.isEmpty = function() { return items.length == 0; } this.size = function() { return items.length; }; // Empty and print stack elements this.clear = function() { items = []; }; this.print = function() { console.log(items.toString()); }; }
Using stack to solve problems
Store accessed tasks or paths, undo operations, etc.
queue
The queue follows FIFO(First In First Out), also known as First In First Out (FIFO).
Realization
function Queue() { let items = []; // Adding elements to the queue this.enqueue = function(element) { items.push(element); }; // Remove elements from queues this.dequeue = function() { return items.shift(); }; // View Queue Header Elements this.front = function() { return items[0]; }; // Check if the queue is empty this.isEmpty = function() { return items.length == 0; }; this.size = function() { return items.length; }; // Print queue elements this.print = function() { console.log(items.toString()); }; }
linked list
A rough and orderly set of elements in a list village, but unlike arrays, elements in a list are not placed continuously in memory. Each element consists of a node that stores the element itself and a reference to the next element (also known as a pointer or link).
One advantage of linked lists over traditional arrays is that no other elements need to be moved when adding or removing elements. However, linked lists require pointers, so extra attention is needed to implement linked lists. Another detail of the array is that you can access any element directly anywhere, and to access an element in the middle of the list, you need to iterate through the list from the start (the header) until you find the required element.
Realization
function LinkedList() { let Node = function(element) { this.element = element; this.next = null; }; let length = 0; let head = null; // Adding elements to the end of the list this.append = function(element) { let node = new Node(element), current; if (head === null) { head = node; } else { current = head; // Loop through the list until you find the last item while (current.next) { current = current.next; } // Find the last item, assign its next to a node, and establish a link current.next = node; } length++; // Length of update list } // Remove elements from the list this.removeAt = function() { // Check the crossover value if (position > -1 && position < length) { let current = head, previous, index = 0; // Remove the first item if (position === 0) { head = current.next; } else { while (index++ < position) { previous = current; current = current.next; } // Link previous to the next item of current: skip current and remove it previous.next = current.next; } length--; return current.element; } else { return null; } } // Insert elements anywhere this.insert = function(position, element) { // Check the crossover value if (position >= 0 && position <= length) { let node = new Node(element), current = head, previous, index = 0; if (position === 0) { // Add in the first place node.next = current; head = node; } else { while (index++ < position) { previous = current; current = current.next; } node.next = current; previous.next = node; } length++; // Length of update list return true; } else { return false; } } // toString method this.toString = function() { let current = head, string = ''; while (current) { string += current.element + (current.next ? 'n' : ''); current = current.next; } return string; } // indexOf method this.indexOf = function(elment) { let current = head, index = 0; while(current) { if (element === current.element) { return index; } index++; current = current.next; } return -1; } // Remote method this.remove = function(elment) { let index = this.indexOf(element); return this.removeAt(index); } // isEmpty method this.isEmpty = function() { return length == 0; } // size method this.size = function() { return length; } // getHead method this.getHead = function() { return head; } }
Two-way Link List (for your own reflection)
aggregate
Sets are composed of a set of disorderly and unique (i.e., non-repeatable) items. This data structure uses the same mathematical concepts as the finite set, but it is applied in the data structure of computer science.
function Set() { let items = {}; // has method this.has = function(value) { return items.hasOwnProperty(value); }; // add method this.add = function(value) { if (!this.has(value)) { items[value] = value; return true; } return false; } // Remote method this.remove = function(value) { if (this.has(value)) { delete items[value]; return true; } return false; } // clear method this.clear = function() { items = {}; } // size method this.size = function() { return Object.keys(items).length; } // values method this.values = function() { let values = []; for (let i = 0, keys = Object.keys(items); i< keys.length; i++) { values.push(items[keys[i]]); } return values; } // Union this.union = function(otherSet) { let unionSet = new Set(); let values = this.values(); for (let i = 0; i < values.length; i++) { unionSet.add(values[i]); } values = otherSet.values(); for (let i = 0; i < values.length; i++) { unionSet.add(values[i]); } return unionSet; } // intersection this.intersection = function(otherSet) { let intersectionSet = new Set(); let values = this.values(); for (let i = 0;i<values.length; i++) { if (otherSet.has(values[i])) { intersectionSet.add(values[i]); } } return intersectionSet; } // Difference set this.difference = function(otherSet) { let differenceSet = new Set(); let values = this.values(); for (let i = 0; i< values.length; i++) { if (!otherSet.has(values[i])) { differenceSet.add(values[i]); } } return differenceSet; } // subset this.subset = function(otherSet) { if (this.size() > otherSet.size()) { return false; } else { let values = this.values(); for (let i = 0;i< values.length;i++) { if (!otherSet.has(values[i])) { return false; } } return true; } } }
Dictionaries and hash tables
Realization
function Dictionary() { var items = {}; // has and set methods this.has = function(key) { return items.hasOwnProperty(key); } this.set = function(key, value) { item[key] = value; } // delete method this.delete = function(key) { if (this.has(key)) { delete items[key]; return true; } return false; } // get and values methods this.get = function(key) { return this.has(key) ? items[key] : undefined; } this.values = function() { var values = []; for(var k in items) { if (this.has(k)) { values.push(items[k]); } } return values; } // clear method this.clear = function() { items = {}; } // size method this.size = function() { return Object.keys(items).length; } // keys method this.keys = function() { return Object.keys(items); } // getItems method this.getItems = function() { return items; } }
Hash table
The HashTable class, also known as the HashMap class, is a hash table implementation of the Dictionary class.
The purpose of hashing algorithm is to find a value in the data structure as quickly as possible.
function HashTable() { var table = []; var loseloseHashCode = function(key) { var hash = 0; for (var i = 0; i< key.length; i++) { hash += key.charCodeAt(i); } return hash % 37; } this.put = function(key, value) { var position = loseloseHashCode(key); console.log(position + ' - ' + key); table[position] = value; } this.get = function(key) { return table[loseloseHashCode(key)]; } this.remove = function(key) { table[loseloseHashCode(key)] = undefined; } }
Class Map
Adding Map Class to es6
var map = new Map(); map.set('a', 'b'); console.log(map.has('a')); // true console.log(map.size()); // Output 1 console.log(map.keys()); // ['a'] console.log(map.values()); // ['b']; // Unlike the Dictionary class, the values and keys methods of the Map class of es6 return Iterator instead of an array of values or keys.
ES6 - - WeakMap class and WeakSet class
- WeakMap and WeakSet classes do not have entries keys values and other methods
- Only objects can be used as keys
var map = new WeakMap(); var obj = {name: 'a'}; map.set(obj, 'b'); console.log(map.has(obj)); // Output true console.log(map.get(obj)); // Input'b' map.delete(obj);
tree
A tree structure consists of a series of nodes with parent-child relationship. Each node has a parent (except the first node at the top) and zero or more children.
Binary Tree and Binary Search Tree
function BinarySearchTree() { var Node = function(key) { this.key = key; this.left = null; this.right = null; } var root = null; var insertNode = function(node, newNode) { if (newNode.key < node.key) { if (node.left === null) { node.left = newNode; } else { insertNode(node.left, newNode); } } else { if (node.right === null) { node.right = newNode; } else { insertNode(node.right, newNode); } } } // Insert a key into the tree this.insert = function(key) { var newNode = new Node(key); if (root = null) { root = newNode; } else { insertNode(root, newNode); } } var inOrderTraverseNode = function(node, callback) { if (node !== null) { inOrderTraverseNode(node.left, callback); callback(node.key); inOrderTraverseNode(node.right, callback); } } // Sequential traversal this.inOrderTraverse = function(callback) { inOrderTraverseNode(root, callback); } var preOrderTraverseNode = function(node, callback) { if (node !== null) { callback(node.key); preOrderTraverseNode(node.left, callback); preOrderTraverseNode(node.right, callback); } } // Preorder traversal this.preOrderTraverse = function(callback) { preOrderTraverseNode(root, callback); } var postOrderTraverseNode = function(node, callback) { if (node !== null) { postOrderTraverseNode(node.left, callback); postOrderTraverseNode(node.right, callback); callback(node.key); } } // Post order traversal this.postOrderTraverse = function(callback) { postOrderTraverseNode(root, callback); } // Search for Minimum Value this.min = function() { return minNode(root); } var minNode = function(node) { if (node) { while( node && node.left !== null) { node = node.left; } return node.key; } return null; } // Search for maximum this.max = function() { return maxNode(root); } var maxNode = function(node) { if (node) { while(node && node.right !== null) { node = node.right; } return node.key; } return null; } // Search for a specific value this.search = function(key) { return searchNode(root, key); } var searchNode = function(node, key) { if (node === null) { return false; } if (key < node.key) { return searchNode(node.left, key); } else if (key > node.key) { return searchNode(node.right, key); } else { return true; } } // Remove a node this.remove = function(key) { root = removeNode(root, key); } var removeNode = function(node, key) { if (node === null) { return null; } if (key < node.key) { node.left = removeNode(node.left,key); return node; } else if (key > node.key) { node.right = removeNode(node.right,key); return node; } else { // Key equals node.key // The first case -- a leaf node if (node.left === null && node.right === null) { node = null; return node; } // The second case -- a node with only one child node if (node.left === null) { node = node.right; return node; } else if (node.right === null) { node = node.left; return node; } // The third case - a node with two subnodes var aux = findMinNode(node.right); node.key = aux.key; node.right = removeNode(node.rihgt, aux.key); return node; } var findMinNode = function(node) { while (node && node.left !== null) { node = node.left; } return node; } } }
Self-balanced Tree (AVL)
When the tree is deep, adding removal and searching for a node causes some performance problems.
var heightNode = function(node) { if (node === null) { return -1; } else { return Math.max(heightNode(node.left), heightNode(node.right)) + 1; } } var rotationRR = function(node) { var tmp = node.right; node.right = tmp.left; tmp.left = node; return tmp; } var rotationLL = function(node) { var tmp = node.left; node.left = tmp.right; tmp.right = node; return tmp; } var rotationLR = function(node) { node.left = rotationRR(node.left); return rotationLL(node); } var rotationRL = function(node) { node.right = rotationLL(node.right); return rotationRR(node); } var insertNode = function(node, element) { if (node === null) { node = new Node(element); } else if (element < node.key) { node.left = insertNode(node.left, element); if (node.left !== null) { // Confirm whether there is a need for balance if ((heightNode(node.left) - heightNode(node.right) > 1)) { if (element < node.left.key) { node = rotationLL(node); } else { node = rotationLR(node); } } } } else if (element > node.key) { node.right = insertNode(node.right, element); if (node.right !== null) { // Confirm whether there is a need for balance if ((heightNode(node.right) - heightNode(node.left) > 1)) { if (element > node.right.key) { node = rotationRR(node); } else { node = rotationRL(node); } } } } return node; }
chart
Graph is an abstract model of network structure. Graph is a group of nodes (or vertices) connected by edges. Learning graphs is important because any relationship can be represented by graphs.
function Graph() { var vertices = []; var adjList = new Dictionary(); this.addVertex = function(v) { vartices.push(v); adjList.set(v, []); } this.addEdge = function(v, w) { addList.get(v).push(w); addList.get(w).push(v); } this.toString = function() { var s = ''; for (var i = 0; i< vertices.length;i++) { s += vertices[i] + ' -> '; var neighbors = adjList.get(vertices[i]); for (var j = 0;j<neighbors.length;j++) { s += neighbors[j] + ' '; } s += '\n'; } return s; } // Breadth-first search var initializeColor = function() { var color = []; for( var i = 0;i< vertices.length; i++) { color[vertices[i]] = 'white'; } return color; } this.bfs = function(v, callback) { var color = initializeColor(), queue = new Queue(); queue.enqueue(v); while(!queue.isEmpty()) { var u = queue.dequeue(), neighbors = adjList.get(u); color[u] = 'grey'; for(var i = 0;i<neighbors.length;i++) { var w = neighbors[i]; if (color[w] === 'white') { color[w] = 'grey'; queue.enqueue(w); } } color[u] = 'black'; if (callback) { callback(); } } } // Using BFS to Find the Shortest Path this.BFS = function(v) { var color = initializeColor(), queue = new Queue(), d = []; pred = []; queue.enqueue(v); for( var i = 0;i< vertices.length;i++) { d[vertices[i]] = 0; pred[vertices[i]] = null; } while(!queue.isEmpty()) { var u = queue.dequeue(), neighbors = adjList.get(u); color[u] = 'grey'; for( i = 0;i<neighbors.length;i++) { var w = neighbors[i]; if (color[w] === 'white') { color[w] = 'grey'; d[w] = d[u] + 1; pred[w] = u; queue.enqueue(w); } } color[u] = 'black'; } return { distances: d, predecessors: pred } } // dfs var dfsVisit = function(u, color, callback) { color[u] = 'grey'; if (callback) { callback(u); } var neighbors = adjList.get(u); for(var i = 0;i<neighbors.length;i++) { var w = neighbors[i]; if (color[w] === 'white') { dfsVisit(w, color, callback); } } color[u] = 'black'; } this.dfs = function(callback) { var color = initializeColor(); for(var i = 0; i< vertices.length; i++) { if (color[vertices[i]] === 'white') { dfsVisit(vertices[i], color, callback); } } } // Exploring depth-first algorithm var time = 0; this.DFS = function() { var color = nitializeColor(), d = [], f = [], p = [], time = 0; for( var i = 0; i< vertices.length; i++) { f[vertices[i]] = 0; d[vertices[i]] = 0; p[vertices[i]] = null; } for (i = 0; i< vertices.length; i++) { if (color[vertices[i]] === 'white') { DFSVisit(vertices[i], color, d, f, p); } } return { discovery: d, finished: f, predecessors: p } } var DFSVisit = function(u, color, d, f, p) { console.log('discovered ' + u); color[u] = 'grey'; d[u] = ++time; var neighbors = adjList.get(u); for(var i = 0;i<neighbors.length; i++) { var w = neighbors[i]; if (color[w] === 'white') { p[w] = u; DFSVisit(w, color, d, f, p); } } color[u] = 'black'; f[u] = ++time; console.log('explored ' + u); } }