You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
varmyStack=newStack();console.log(myStack.length());// 0console.log(myStack.push('a'));// undefined (push return no value)console.log(myStack.push('b'));// undefinedconsole.log(myStack.push('c'));// undefinedconsole.log(myStack.pop());// cconsole.log(myStack.top());// bconsole.log(myStack.bottom());// aconsole.log(myStack.length());// 2constStack=function(){letcount=0;letcontent={};this.push=function(value){// add value on top of the stackcontent[count]=value;count++;};this.pop=function(){// remove value at top of the stack and return that valueif(count===0){returnundefined}count--;varpopped=content[count];deletecontent[count];returnpopped;};this.length=function(){returncount}// return number of values in stackthis.top=function(){// return the value on top of the stackif(count===0){returnundefined}returncontent[count-1]}this.bottom=function(){// return the value at the bottom of the stackif(count===0){returnundefined}returncontent['0']}}
Javascript array object has all Stack data structure attributes and methods. However, we can always implement a stack data structure by ourself and add more property/method as we want.
Set
constmySet=newSet();console.log(mySet.add('a'));// a is added to set!console.log(mySet.exist('a'));// trueconsole.log(mySet.exist('b'));// falseconsole.log(mySet.list());// [ 'a' ]console.log(mySet.add('b'));// b is added to set!console.log(mySet.add('c'));// c is added to set!console.log(mySet.remove('c'));// c is removed from set!console.log(mySet.list());// [ 'a', 'b' ]console.log(mySet.length());// 2constmySet2=newSet();console.log(mySet2.add('a'));// a is added to set!console.log(mySet2.add('g'));// g is added to set!console.log(mySet2.add('h'));// h is added to set!console.log(mySet2.list());// [ 'a', 'g', 'h' ]console.log(mySet.union(mySet2).list());// [ 'a', 'b', 'g', 'h' ]console.log(mySet.intersect(mySet2).list());// [ 'a' ]console.log(mySet.difference(mySet2).list());// [ 'b', 'g', 'h' ]constSet=function(){letset=[];this.exist=function(element){// check if element is in set return true, else return falsereturn(set.indexOf(element)!==-1)}this.add=function(element){// add element to set if not exist, do not add if it existsif(!this.exist(element)){set.push(element);return`${element} is added to set!`;}}this.list=function(){// list all element in setreturnset;}this.remove=function(element){// remove an element if it's in setif(this.exist(element)){set.splice(set.indexOf(element),1);return`${element} is removed from set!`;}else{return`${element} is not in set!`;}}this.length=function(){// return number of element in setreturnset.length;}this.union=function(setC){// return the union set of two setsletunion=newSet();letsetA=this.list();letsetB=setC.list();for(leti=0;i<setA.length;i++){union.add(setA[i]);}for(letj=0;j<setB.length;j++){union.add(setB[j]);}returnunion;}this.intersect=function(setC){// return a set of intersection of 2 setsletintersect=newSet();letsetA=this;letsetB=setC.list();for(leti=0;i<setB.length;i++){if(setA.exist(setB[i])){intersect.add(setB[i])}}returnintersect;}this.difference=function(setC){// return a set of difference of 2 setsletsetA=this;letdifference=setA.union(setC);letsetB=setA.intersect(setC).list();for(leti=0;i<setB.length;i++){difference.remove(setB[i]);}returndifference;}}
Queue
constmyQueue=newQueue();myQueue.enqueue('a');myQueue.enqueue('b');myQueue.enqueue('c');myQueue.list();// [ 'a', 'b', 'c' ]console.log(myQueue.dequeue());// aconsole.log(myQueue.front());// bconsole.log(myQueue.length());// 2console.log(myQueue.isEmpty());// falsemyQueue.list();// [ 'b', 'c' ]functionQueue(){// first in, first out (FIFO)constcontent=[];this.list=function(){console.log(content)};// list all queue itemthis.enqueue=function(element){content.push(element)};// put item to the queuethis.dequeue=function(){returncontent.shift()};// get the first item in the queue, remove it from the queuethis.front=function(){returncontent[0]};// get the first item in the queue, still let it be in the queuethis.length=function(){returncontent.length};// get queue lengththis.isEmpty=function(){return(content.length==0)}// check if queue is empty}
Priority Queue
constmyQueue=newpriorityQueue();myQueue.enqueue(['a',2]);myQueue.enqueue(['b',3]);myQueue.list();// [ [ 'a', 2 ], [ 'b', 3 ] ]myQueue.enqueue(['c',4]);myQueue.list();// [ [ 'a', 2 ], [ 'b', 3 ], [ 'c', 4 ] ] myQueue.enqueue(['d',3]);myQueue.list();// [ [ 'a', 2 ], [ 'b', 3 ], [ 'd', 3 ], [ 'c', 4 ] ] myQueue.enqueue(['e',1]);myQueue.list();// [ [ 'e', 1 ], [ 'a', 2 ], [ 'b', 3 ], [ 'd', 3 ], [ 'c', 4 ] ] console.log(myQueue.dequeue());// [ 'e', 1 ]console.log(myQueue.front());// [ 'a', 2 ]console.log(myQueue.length());// 4console.log(myQueue.isEmpty());// falsefunctionpriorityQueue(){// Queue where item with highest priority get out first no matter when addedconstcontent=[];this.list=function(){console.log(content)};// list all queue itemthis.dequeue=function(){returncontent.shift()};// get the first item in the queue, remove it from the queuethis.front=function(){returncontent[0]};// get the first item in the queue, still let it be in the queuethis.length=function(){returncontent.length};// get queue lengththis.isEmpty=function(){return(content.length==0)}// check if queue is emptythis.enqueue=function(element){// put item to the queue with priorityif(this.isEmpty()){returncontent.push(element)};varadded=false;for(leti=0;i<content.length;i++){// 1 is highest priorityif(element[1]<content[i][1]){content.splice(i,0,element);added=true;break;}}if(!added){content.push(element)}};}
Binary search tree
Search item in tree fastO(log n), find min and max, inOrder, preOrder, postOrder, levelOrder
preOrder used when need to explore the roots before inspecting any leaves
postOrder used when need to explore all the leaves before any nodes
inOrder used when need to flatten the tree back into its sequence (bottom up)
levelOrder used when need to inspect nodes at height level
constutil=require('util')classNode{constructor(data,left=null,right=null){this.data=data;this.left=left;this.right=right;}}classbinarySearchTree{constructor(){this.root=null}add(data){// add node to binary treeconstnode=this.root;if(this.root===null){this.root=newNode(data)}else{searchLeaf(node);functionsearchLeaf(node){if(data<node.data){if(node.left===null){returnnode.left=newNode(data)}searchLeaf(node.left);}elseif(data>node.data){if(node.right===null){node.right=newNode(data)}searchLeaf(node.right);}else{returnnull}}}}findMin(){// find min value in binary treeletcurrent=this.root;while(current.left!==null){current=current.left}returncurrent.data;}findMax(){// find max value in binary treeletcurrent=this.root;while(current.right!==null){current=current.right}returncurrent.data;}exist(data){// check if a data is in binary treeletcurrent=this.root;while(current){if(current.data===data){returntrue}elseif(current.data>data){current=current.left}else{current=current.right}}returnfalse}remove(data){// remove a node from binary treethis.root=removeNode(this.root,data);functionremoveNode(node,data){if(node==null){returnnull}// root node/tree has nothing in itif(data<node.data){// not match, move to leftnode.left=removeNode(node.left,data);}elseif(data>node.data){// not match, move to rightnode.right=removeNode(node.right,data);}else{// found matching nodeif(node.left===null&&node.right===null){returnnull}// no childrenif(node.left===null){returnnode.right}// has right childif(node.right===null){returnnode.left}// has left childletrightThenFarthestLeft=node.right;// has both left, right childwhile(rightThenFarthestLeft.left!==null){rightThenFarthestLeft=rightThenFarthestLeft.left;}node.data=rightThenFarthestLeft.data;removeNode(node.right,rightThenFarthestLeft.data);}returnnode;}}findMinHeight(node=this.root){// get min height of treeif(node==null){return-1}letleft=this.findMinHeight(node.left);letright=this.findMinHeight(node.right);if(left<right){returnleft+1}else{returnright+1}}findMaxHeight(node=this.root){// get max height of treeif(node==null){return-1}letleft=this.findMaxHeight(node.left);letright=this.findMaxHeight(node.right);if(left<right){returnright+1}else{returnleft+1}}isBalanced(){// check if tree is balancedreturn(this.findMinHeight()>=this.findMaxHeight()-1)}inOrder(){// traverse tree to array min -> maxif(this.root==null){returnnull}else{varresult=newArray();traverseInOrder(this.root);returnresult;functiontraverseInOrder(node){node.left&&traverseInOrder(node.left);result.push(node.data);node.right&&traverseInOrder(node.right);}};}bottomUp(){returnthis.inOrder()}// synonym of inOrder topDown(){// traverse tree to array max -> minif(this.root==null){returnnull;}else{varresult=newArray();traverseInOrder(this.root);returnresult;functiontraverseInOrder(node){node.right&&traverseInOrder(node.right);result.push(node.data);node.left&&traverseInOrder(node.left);}};}preOrder(){if(this.root==null){returnnull}else{varresult=newArray();functiontraversePreOrder(node){result.push(node.data);node.left&&traversePreOrder(node.left);node.right&&traversePreOrder(node.right);};traversePreOrder(this.root);returnresult;};}postOrder(){if(this.root==null){returnnull}else{varresult=newArray();functiontraversePostOrder(node){node.left&&traversePostOrder(node.left);node.right&&traversePostOrder(node.right);result.push(node.data);};traversePostOrder(this.root);returnresult;}}levelOrder(){letresult=[];letQ=[];if(this.root!=null){Q.push(this.root);while(Q.length>0){letnode=Q.shift();result.push(node.data);if(node.left!=null){Q.push(node.left);};if(node.right!=null){Q.push(node.right);};};returnresult;}else{returnnull;};};}varmyBt=newbinarySearchTree();myBt.add(4);myBt.add(1);myBt.add(8);myBt.add(0.5);myBt.add(2);myBt.add(1.6);myBt.add(2.2);myBt.add(1.4);myBt.add(1.7);console.log(util.inspect(myBt,{showHidden: false,depth: null}));// {// root : {// data : 4,// left : {// data : 1,// left : { // data: 0.5, // left: null, // right: null // },// right : {// data : 2,// left : {// data : 1.6,// left : { // data : 1.4, // left : null, // right : null // },// right : { // data : 1.7, // left : null, // right : null // } // },// right: { // data: 2.2, // left: null, // right: null // } // } // },// right : { // data: 8, // left: null, // right: null // } // } // }console.log(myBt.findMin());// 0.5console.log(myBt.findMax());// 8console.log(myBt.exist(5));// falseconsole.log(myBt.exist(2.2));// trueconsole.log(myBt.findMinHeight());// 1console.log(myBt.findMaxHeight());// 4 console.log(myBt.inOrder());// [ 0.5, 1, 1.4, 1.6, 1.7, 2, 2.2, 4, 8 ]console.log(myBt.bottomUp());// [ 0.5, 1, 1.4, 1.6, 1.7, 2, 2.2, 4, 8 ] console.log(myBt.isBalanced());// falseconsole.log(myBt.topDown());// [ 8, 4, 2.2, 2, 1.7, 1.6, 1.4, 1, 0.5 ]console.log(myBt.preOrder());// [ 4, 1, 0.5, 2, 1.6, 1.4, 1.7, 2.2, 8 ]console.log(myBt.postOrder());// [ 0.5, 1.4, 1.7, 1.6, 2.2, 2, 1, 8, 4 ]console.log(myBt.levelOrder());// [ 4, 1, 8, 0.5, 2, 1.6, 2.2, 1.4, 1.7 ]console.log(myBt.remove(1));console.log(util.inspect(myBt,{showHidden: false,depth: null}));// {// root : {// data : 4,// left : {// data : 1.4,// left : { // data : 0.5, // left : null, // right : null // },// right : { // data : 2, // left : {// data : 1.6,// left : null,// right : { // data : 1.7, // left : null, // right : null // }// },// right : { // data : 2.2, // left : null, // right : null // } // } // },// right : { // data : 8, // left : null, // right : null // } // } // }
Hash tables
The average time for each look up is not tied to the number of elements stored in the table
Time complexity for search, insert and delete is O(1)
But time to add an element is longer, vary to table size
varhash=(string,max)=>{// return hash number varhash=0;for(vari=0;i<string.length;i++){hash+=string.charCodeAt(i);}returnhash%max;// simple hash function return value from 0 to max};letHashTable=function(){letstorage=[];conststorageLimit=4;// define hash table sizethis.print=function(){console.log(storage)}this.add=function(key,value){// add [key, value] to hash tablevarindex=hash(key,storageLimit);if(storage[index]===undefined){storage[index]=[[key,value]];}else{varinserted=false;for(vari=0;i<storage[index].length;i++){// collision will be stored in same hash positionif(storage[index][i][0]===key){storage[index][i][1]=value;inserted=true;}}if(inserted===false){storage[index].push([key,value]);}}};this.remove=function(key){// remove [key, value] from hash tablevarindex=hash(key,storageLimit);if(storage[index].length===1&&storage[index][0][0]===key){deletestorage[index];}else{for(vari=0;i<storage[index].length;i++){// check if there is collisionif(storage[index][i][0]===key){deletestorage[index][i];}}}};this.lookup=function(key){// lookup and return [key, value] in hash tablevarindex=hash(key,storageLimit);if(storage[index]===undefined){returnundefined;}else{for(vari=0;i<storage[index].length;i++){// check if there is collisionif(storage[index][i][0]===key){returnstorage[index][i][1];}}}};};console.log(hash('quincy',10))// 5letht=newHashTable();ht.add('beau','person');ht.add('fido','dog');ht.add('rex','dinosour');ht.add('tux','penguin')console.log(ht.lookup('tux'))// penguinht.print();// [ <1 empty item>,[ [ 'beau', 'person' ], [ 'tux', 'penguin' ] ], [ [ 'fido', 'dog' ] ], [ [ 'rex', 'dinosour' ] ] ]
Map
In Javascript, object is map
letmyMap=function(){this.collection={};this.count=0;this.size=function(){// return number of total item in mapreturnthis.count;};this.set=function(key,value){// add (key, value) pair to mapthis.collection[key]=value;this.count++;};this.has=function(key){// check if map contains a given keyreturn(keyinthis.collection);};this.get=function(key){// get value given keyreturn(keyinthis.collection) ? this.collection[key] : null;};this.delete=function(key){// delete value given keyif(keyinthis.collection){deletethis.collection[key];this.count--;}};this.values=function(){// list all values in mapletresult=newArray();for(letkeyofObject.keys(this.collection)){result.push(this.collection[key]);};return(result.length>0) ? result : null;};this.clear=function(){// delete all key value pairs in mapthis.collection={};this.count=0;};this.log=function(){// log the whole map out (for learning purpose)console.log(this.collection);}};letmap=newmyMap();map.set('arms',2);map.set('fingers',10);map.set('eyes',2);map.set('belley button',1);console.log(map.log());// { arms: 2, fingers: 10, eyes: 2, 'belley button': 1 }console.log(map.get('fingers'));// 10console.log(map.size());// 4console.log(map.values());// [ 2, 10, 2, 1 ]letmap2=newmyMap();map2.set('hands','right');console.log(map2.values());// [ 'right' ]console.log(map2.has('hands'));// trueletkeyObj={},keyFunc=function(){};map2.set('hello','string value');map2.set(keyObj,'obj value');map2.set(keyFunc,'func value');map2.set(NaN,'NaN value')console.log(map2.size);// [Function]console.log(map2.get('hello'));// string valueconsole.log(map2.get(keyObj));// obj valueconsole.log(map2.get(keyFunc));// func valueconsole.log(map2.get(NaN));// NaN value
Linked list
constutil=require('util')functionLinkedList(){letlength=0;lethead=null;letNode=function(element){// define a node in the linked listthis.element=element;this.next=null;}this.size=function(){returnlength}// get linked list lengththis.head=function(){returnhead}// return head of the linked listthis.add=function(element){// add element to linked listletnode=newNode(element);if(head===null){head=node}else{letcurrentNode=head;while(currentNode.next){currentNode=currentNode.next;}currentNode.next=node;}length++;}this.remove=function(element){// remove an element from the linked list by its dataletcurrentNode=head;letpreviousNode;if(currentNode.element===element){head=currentNode.next;}else{while(currentNode.element!==element){previousNode=currentNode;currentNode=currentNode.next;}previousNode.next=currentNode.next;}length--;}this.isEmpty=function(){returnlength==0}// check if linked list is emptythis.indexOf=function(element){// get index of an elementletcurrentNode=head;letindex=0;// function return -1 if element is not in the linked listif(currentNode.element===element){returnindex;}else{while(currentNode.element!==element){currentNode=currentNode.next;index++;}if(currentNode!==null){returnindex}else{return-1}}}this.elementAt=function(index){// get element by indexletcurrentNode=head;letcurrentIndex=0;while(currentNode&&index!==currentIndex){currentNode=currentNode.next;currentIndex++;}if(currentNode){returncurrentNode.element}else{return-1;}}this.addAt=function(index,element){// add element at given indexletnode=newNode(element);letcurrentNode=head;letcurrentIndex=0;letpreviousNode;if(index>length-1){return'index out of range!'}else{if(index===0){node.next=head;head=node;length++;return}while(index!==currentIndex){previousNode=currentNode;currentNode=currentNode.next;currentIndex++}previousNode.next=node;node.next=currentNode;length++;}}this.removeAt=function(index){// remove element at indexletcurrentNode=head;letcurrentIndex=0;letpreviousNode;if(index>length-1){return'index out of range!'}else{if(index===0){head=head.next;length--;return}while(index!==currentIndex){previousNode=currentNode;currentNode=currentNode.next;currentIndex++}previousNode.next=currentNode.next;length--;}}}letmyll=newLinkedList();console.log(myll.size());// 0console.log(myll.head());// nullmyll.add(12);console.log(myll.size());// 1myll.add(34);console.log(myll.size());// 2console.log(myll.head());// Node {element:12,next:Node{ element: 34, next: null } }myll.add(76);myll.add(43);console.log(myll.size());// 4myll.remove(76);console.log(myll.size());// 3console.log(myll.indexOf(34));// 1console.log(myll.elementAt(4));// -1console.log(myll.head());// Node {element:12,next:Node{element:34,next Node{element:43,next:null}}}console.log(myll.addAt(7,'lalala'));// index out of range!console.log(myll.addAt(0,'lalala'));// undefinedconsole.log(myll.addAt(2,'lolo'));// undefinedconsole.log(util.inspect(myll.head(),{showHidden: false,depth: null}));// Node {element: 'lalala',next: Node {element: 12,next:Node {element: 'lolo',next: Node { element: 34, next: Node { element: 43, next: null } } } } }console.log(myll.removeAt(2));// undefinedconsole.log(util.inspect(myll.head(),{showHidden: false,depth: null}));// Node {element: 'lalala',next: Node {element: 12,next: Node { element: 34, next: Node { element: 43, next: null } } } }
Trie
An use case is to validate if a word in the dictionary
constNode=function(){this.keys=newMap();this.end=false;this.setEnd=function(){this.end=true};this.isEnd=function(){returnthis.end};}letTrie=function(){this.root=newNode();this.add=function(input,node=this.root){// add word to trieif(input.length==0){node.setEnd();return;}elseif(!node.keys.has(input[0])){node.keys.set(input[0],newNode());returnthis.add(input.substr(1),node.keys.get(input[0]));}else{returnthis.add(input.substr(1),node.keys.get(input[0]));};};this.isWord=function(word){// check if word is in trieletnode=this.root;while(word.length>1){if(!node.keys.has(word[0])){returnfalse;}else{node=node.keys.get(word[0]);word=word.substr(1);};};return(node.keys.has(word)&&node.keys.get(word).isEnd()) ?
true : false;};this.print=function(){letwords=newArray();letsearch=function(node,string){if(node.keys.size!=0){for(letletterofnode.keys.keys()){search(node.keys.get(letter),string.concat(letter));};if(node.isEnd()){words.push(string);};}else{string.length>0 ? words.push(string) : undefined;return;};};search(this.root,newString());returnwords.length>0 ? words : mo;};};myTrie=newTrie()myTrie.add('ball');myTrie.add('bat');myTrie.add('doll');myTrie.add('dork');myTrie.add('do');myTrie.add('dorm')myTrie.add('send')myTrie.add('sense')console.log(myTrie.isWord('doll'));// trueconsole.log(myTrie.isWord('dor'))// falseconsole.log(myTrie.isWord('dorf'))// falseconsole.log(myTrie.print());// [ 'ball', 'bat', 'doll', 'dork', 'dorm', 'do', 'send', 'sense' ]
Heap
Partially ordered binary tree which satisfies the heap property.
Heap property indicates a specific relationship between parent and child node
Max heap: all parent nodes are greater than or equal to child nodes
Min heap: all child nodes are greater than or equal to parent nodes
The order between child nodes in a same level does not matter
Binary heaps are complete binary trees: all levels of the tree are fully filled (if the last level partially filled, it's filled from left to right)
In array representation, index start at 1 so index 0 is null
Node at index k has left child node at index 2*k and right child node at index 2*k+1
Node at index l has parent node at index roundDown(l/2)
varexBFSGraph=[// adjagency representation of a graph[0,1,1,1,0],[0,0,1,0,0],[1,1,0,0,0],[0,0,0,1,0],[0,1,0,0,0]];console.log(bfs(exBFSGraph,1));// distance between node 1 to other nodes// { '0': 2, '1': 0, '2': 1, '3': 3, '4': Infinity }functionbfs(graph,root){varnodesLen={};for(vari=0;i<graph.length;i++){nodesLen[i]=Infinity;}nodesLen[root]=0;varqueue=[root];varcurrent;while(queue.length!=0){current=queue.shift();varcurConnected=graph[current];varneighborIdx=[];varidx=curConnected.indexOf(1);while(idx!=-1){neighborIdx.push(idx);idx=curConnected.indexOf(1,idx+1);}for(varj=0;j<neighborIdx.length;j++){if(nodesLen[neighborIdx[j]]==Infinity){nodesLen[neighborIdx[j]]=nodesLen[current]+1;queue.push(neighborIdx[j]);}}}returnnodesLen;};
x=5+15*20;// O(1) independent of input size (input are constants)x=5+15*20;y=9-6;console.log(x+y)// total time = O(1) + O(1) + O(1) = 3O(1) = O(1) (constants are dropped)for(leti=0;i<N;i++){console.log(i)}// total time = N * O(1) = O(N) (input now is N, not constant)y=32+6for(leti=0;i<N;i++){console.log(i)}// total time = O(1) + N * O(1) = O(N) (low order term is dropped)y=32+6for(leti=0;i<N;i++){console.log(i)}for(leti=0;i<N;i++){for(letj=0;i<N;i++){console.log(j);}}// total time = max(O(1), O(N), O(N^2)) = O(N^2) (O(N^2) dominates)if(x>0){// O(1)}elseif(x<0){// O(logn)}else{// O(n^2)}// total time = O(n^2) (big O considers worst case scenario)