diff --git a/Data-Structures/LinkList/__tests__/linked-list.test.js b/Data-Structures/LinkList/__tests__/linked-list.test.js new file mode 100644 index 0000000..b4cfe02 --- /dev/null +++ b/Data-Structures/LinkList/__tests__/linked-list.test.js @@ -0,0 +1,8 @@ +const LinkList = require('../linked-list.js'); + +xdescribe('Test', () => { + // How might we repeat this to check on types? + it('true', ()=>{ + expect(LinkList).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/Data-Structures/LinkList/linked-list.js b/Data-Structures/LinkList/linked-list.js new file mode 100644 index 0000000..e69de29 diff --git a/Data-Structures/LinkList/readme.md b/Data-Structures/LinkList/readme.md new file mode 100644 index 0000000..4da3d71 --- /dev/null +++ b/Data-Structures/LinkList/readme.md @@ -0,0 +1,22 @@ +# Singly Linked List + + + +## Challenge +Write tests to prove the following functionality: + +* Can successfully instantiate an empty linked list +* Can properly insert into the linked list +* The head property will properly point to the first node in the linked list +* Can properly insert multiple nodes into the linked list +* Will return true when finding a value within the linked list that exists +* Will return false when searching for a value in the linked list that does not exist +* Can properly return a collection of all the values that exist in the linked list + +## Approach & Efficiency + + + +## API + + \ No newline at end of file diff --git a/Data-Structures/ll-Insertions/__tests__/linked-list.test.js b/Data-Structures/ll-Insertions/__tests__/linked-list.test.js new file mode 100644 index 0000000..0146148 --- /dev/null +++ b/Data-Structures/ll-Insertions/__tests__/linked-list.test.js @@ -0,0 +1,150 @@ +const LinkedList = require('../linked-list.js'); + +xdescribe('Test', () => { + it('true', ()=>{ + expect(true).toBeTruthy(); + }); +}); + +// * Can successfully instantiate an empty linked list +xdescribe('instantiate an empty linked list', ()=>{ + let list = new LinkedList(); + it('empty list',()=>{ + expect(list).toBeTruthy(); + }); +}); + +// * Can properly insert into the linked list +xdescribe('insert into the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + + it('successfully inserts into list', ()=>{ + expect(list.head.data).toBe('yellow'); + + }); + +}); +// * The head property will properly point to the first node in the linked list +xdescribe('The head property will properly point to the first node in the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.insert('blue'); + + it('first node is correct', ()=>{ + expect(list.head.data).toBe('blue'); + }); + +}); +// * Can properly insert multiple nodes into the linked list +xdescribe('Can properly insert multiple nodes into the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.insert('blue'); + + it('successfully added head', ()=>{ + expect(list.head.data).toBe('blue'); + }); + it('successfully added 2nd value', ()=>{ + expect(list.head.next.data).toBe('yellow'); + }); +}); + +xdescribe('Will return true when finding a value within the linked list that exists', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.insert('blue'); + let searchResult = list.includes('yellow'); + let badSearchResult = list.includes('apple'); + + // Will return true when finding a value within the linked list that exists + it('Returns true for items that exist', ()=>{ + expect(searchResult).toBeTruthy(); + }); + // * Will return false when searching for a value in the linked list that does not exist + it('Returns false for items that do not exist', ()=>{ + expect(badSearchResult).toBeFalsy(); + }); +}); + + +// * Can properly return a collection of all the values that exist in the linked list +xdescribe('Can properly return a collection of all the values that exist in the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.insert('blue'); + list.insert('green'); + let allItems = list.toString(); + it('returns a collection', ()=>{ + expect(allItems).toBe('green,blue,yellow'); + }); + +}); + +// Can successfully add a node to the end of the linked list +xdescribe('Can successfully add a node to the end of the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('green'); + list.append('blue'); + + it('Items should be added to the end of the list', ()=>{ + expect(list.head.next.data).toBe('green'); + }); + // Can successfully add multiple nodes to the end of a linked list + it('Can add multiple nodes to the end of a list',()=>{ + expect(list.head.next.next.data).toBe('blue'); + }); + +}); + +// Can successfully insert a node before a node located in the middle of a linked list + +xdescribe('Can successfully insert a node before a node located in the middle of a linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('blue'); + list.insertBefore('green', 'blue'); + it('inserts in middle', ()=>{ + expect(list.head.next.data).toBe('green'); + }); + it('blue should be at the end', ()=>{ + expect(list.head.next.next.data).toBe('blue'); + }); + it('head should stay the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); +}); +// Can successfully insert a node before the first node of a linked list +xdescribe('Can successfully insert a node before a node located in the middle of a linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('blue'); + list.insertBefore('green', 'yellow'); + it('inserts at the head', ()=>{ + expect(list.head.data).toBe('green'); + }); + it('blue should be at the end', ()=>{ + expect(list.head.next.next.data).toBe('blue'); + }); + it('head should move over', ()=>{ + expect(list.head.next.data).toBe('yellow'); + }); +}); +// Can successfully insert after a node in the middle of the linked list +xdescribe('Can successfully insert a node after a node located in the middle of a linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('blue'); + list.insertAfter('green', 'yellow'); + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('blue should be at the end', ()=>{ + expect(list.head.next.next.data).toBe('blue'); + }); + it('new node should be in the middle', ()=>{ + expect(list.head.next.data).toBe('green'); + }); +}); +// Can successfully insert a node after the last node of the linked list \ No newline at end of file diff --git a/Data-Structures/ll-Insertions/linked-list.js b/Data-Structures/ll-Insertions/linked-list.js new file mode 100644 index 0000000..2ad5141 --- /dev/null +++ b/Data-Structures/ll-Insertions/linked-list.js @@ -0,0 +1,89 @@ +const Node = require('./node.js'); + +// instantiate an empty linked list +class LinkedList { + constructor(){ + this.head = null; + } + // insert item into the beginning of the list + insert(data){ + let inserted = new Node(data); + inserted.next = this.head; + this.head = inserted; + return this.head; + } + // A function called includes which takes in a value and returns a boolean if that value exists in the linked list + includes(searchValue) { + let currentNode = this.head; + while(currentNode) { + if (currentNode.data === searchValue){ + return true; + } + currentNode = currentNode.next; + } + return false; + } + // A function called toString which takes in no arguments and returns a string representing all the values in the linked list + toString(){ + let stringList = []; + let currentNode = this.head; + while(currentNode){ + stringList.push(currentNode.data); + currentNode = currentNode.next; + } + return stringList.toString(); + + } + // A function called append which adds a Node to the end of the list + append(data){ + let appendedItem = new Node(data); + let currentNode = this.head; + if(this.head === null){ + this.head = appendedItem; + return this.head; + } else{ + while(currentNode.next){ + currentNode = currentNode.next; + } + currentNode.next = appendedItem; + } + } + insertBefore(data, before){ + let insertedItem = new Node(data); + let currentNode = this.head; + if(currentNode.data === before){ + this.insert(data); + return; + } + + while(currentNode.next){ + if(currentNode.next.data === before){ + insertedItem.next = currentNode.next; + currentNode.next = insertedItem; + return; + } + currentNode = currentNode.next; + } + + } + + insertAfter(data, after){ + let insertedItem = new Node(data); + let currentNode = this.head; + + while(currentNode){ + if(currentNode.data === after){ + insertedItem.next = currentNode.next; + currentNode.next = insertedItem; + return; + } + currentNode = currentNode.next; + } + + } + + +} + + +module.exports = LinkedList; \ No newline at end of file diff --git a/Data-Structures/ll-Insertions/node.js b/Data-Structures/ll-Insertions/node.js new file mode 100644 index 0000000..ae7d7e9 --- /dev/null +++ b/Data-Structures/ll-Insertions/node.js @@ -0,0 +1,10 @@ +'use strict'; + +class Node { + constructor(value){ + this.data = value; + this.next = null; + } +} + +module.exports = Node; \ No newline at end of file diff --git a/Data-Structures/ll-Insertions/readme.md b/Data-Structures/ll-Insertions/readme.md new file mode 100644 index 0000000..a2c5d28 --- /dev/null +++ b/Data-Structures/ll-Insertions/readme.md @@ -0,0 +1,43 @@ +# Singly Linked List + +More complex functions for singly linked lists + +## Challenge +* Have a class named Node. This class should contain: + A variable to hold data (i.e. this.data) + A variable to hold the next Node object (i.e. this.next) +* Have a class named LinkedList. This class should contain: + A variable named head which holds the Node object that starts the list + A constructor that instantiates head as an empty linked list + A function called insert which takes in a value. This function will then create a new Node object, sets the object’s data property equal to the value. The function then appends this new Node object to the beginning of the linked list (i.e. it sets a new head) + A function called includes which takes in a value and returns a boolean if that value exists in the linked list + A function called toString whcih takes in no arguments and returns a string representing all the values in the linked list + A function called append which adds a Node to the end of the list + A function called insertBefore which adds a Node before a certain Node in the list + A function called insertAfter which adds a Node after a certain Node in the list +Implement good error checking throughout your code. Create custom errors that describe what went wrong. +Structure and Testing +Any functions you write should be clean, reusable and independent component parts to the whole program. + +#### Write tests to prove the following functionality: + +* Can successfully add a node to the end of the linked list +* Can successfully add multiple nodes to the end of a linked list +* Can successfully insert a node before a node located in the middle of a linked list +* Can successfully insert a node before the first node of a linked list +* Can successfully insert after a node in the middle of the linked list +* Can successfully insert a node after the last node of the linked list + +## Approach & Efficiency + +O(n) +We never go deeper than one interation of the list so Big O(n) is still applicable + +## API + +insert(data) - Creates a new Node Object. Appends the new Node object to the beginning of the linked list +includes(searchValue) - Takes in a value as a paramenter and returns a boolean if the value exists in the linked list +toString() - Returns a string with all the values in the linked list +append(data) - Adds a node to the end of the list +insertBefore(data, before) - Adds a Node before a certain Node in the list +insertAfter(data, after) - Adds a Node after a certain Node in the list \ No newline at end of file diff --git a/Data-Structures/ll-kth-from-end/__tests__/linked-list.test.js b/Data-Structures/ll-kth-from-end/__tests__/linked-list.test.js new file mode 100644 index 0000000..dabe330 --- /dev/null +++ b/Data-Structures/ll-kth-from-end/__tests__/linked-list.test.js @@ -0,0 +1,235 @@ +const LinkedList = require('../linked-list.js'); + +describe('Test', () => { + it('true', ()=>{ + expect(true).toBeTruthy(); + }); +}); + +// * Can successfully instantiate an empty linked list +describe('instantiate an empty linked list', ()=>{ + let list = new LinkedList(); + it('empty list',()=>{ + expect(list).toBeTruthy(); + }); +}); + +// * Can properly insert into the linked list +describe('insert into the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + + it('successfully inserts into list', ()=>{ + expect(list.head.data).toBe('yellow'); + + }); + +}); +// * The head property will properly point to the first node in the linked list +describe('The head property will properly point to the first node in the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.insert('blue'); + + it('first node is correct', ()=>{ + expect(list.head.data).toBe('blue'); + }); + +}); +// * Can properly insert multiple nodes into the linked list +describe('Can properly insert multiple nodes into the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.insert('blue'); + + it('successfully added head', ()=>{ + expect(list.head.data).toBe('blue'); + }); + it('successfully added 2nd value', ()=>{ + expect(list.head.next.data).toBe('yellow'); + }); +}); + +describe('Will return true when finding a value within the linked list that exists', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.insert('blue'); + let searchResult = list.includes('yellow'); + let badSearchResult = list.includes('apple'); + + // Will return true when finding a value within the linked list that exists + it('Returns true for items that exist', ()=>{ + expect(searchResult).toBeTruthy(); + }); + // * Will return false when searching for a value in the linked list that does not exist + it('Returns false for items that do not exist', ()=>{ + expect(badSearchResult).toBeFalsy(); + }); +}); + + +// * Can properly return a collection of all the values that exist in the linked list +describe('Can properly return a collection of all the values that exist in the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.insert('blue'); + list.insert('green'); + let allItems = list.toString(); + it('returns a collection', ()=>{ + expect(allItems).toBe('green,blue,yellow'); + }); + +}); + +// Can successfully add a node to the end of the linked list +describe('Can successfully add a node to the end of the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('green'); + list.append('blue'); + + it('Items should be added to the end of the list', ()=>{ + expect(list.head.next.data).toBe('green'); + }); + // Can successfully add multiple nodes to the end of a linked list + it('Can add multiple nodes to the end of a list',()=>{ + expect(list.head.next.next.data).toBe('blue'); + }); + +}); + +// Can successfully insert a node before a node located in the middle of a linked list + +describe('Can successfully insert a node before a node located in the middle of a linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('blue'); + list.insertBefore('green', 'blue'); + it('inserts in middle', ()=>{ + expect(list.head.next.data).toBe('green'); + }); + it('blue should be at the end', ()=>{ + expect(list.head.next.next.data).toBe('blue'); + }); + it('head should stay the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); +}); +// Can successfully insert a node before the first node of a linked list +describe('Can successfully insert a node before a node located in the middle of a linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('blue'); + list.insertBefore('green', 'yellow'); + it('inserts at the head', ()=>{ + expect(list.head.data).toBe('green'); + }); + it('blue should be at the end', ()=>{ + expect(list.head.next.next.data).toBe('blue'); + }); + it('head should move over', ()=>{ + expect(list.head.next.data).toBe('yellow'); + }); +}); +// Can successfully insert after a node in the middle of the linked list +describe('Can successfully insert a node after a node located in the middle of a linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('blue'); + list.insertAfter('green', 'yellow'); + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('blue should be at the end', ()=>{ + expect(list.head.next.next.data).toBe('blue'); + }); + it('new node should be in the middle', ()=>{ + expect(list.head.next.data).toBe('green'); + }); +}); +// Can successfully insert a node after the last node of the linked list +describe('Can successfully insert a node after last node of a linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('blue'); + list.insertAfter('green', 'blue'); + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('green should be at the end', ()=>{ + expect(list.head.next.next.data).toBe('green'); + }); + it('blue should be in the middle', ()=>{ + expect(list.head.next.data).toBe('blue'); + }); +}); + +// Where k is greater than the length of the linked list +describe(' Where k is greater than the length of the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + let k = list.kthFromEnd(3); + + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('k should return error', ()=>{ + expect(k).toBe('error'); + }); +}); + + +// Where k and the length of the list are the same +describe('Where k and the length of the list are the same', ()=>{ + let list = new LinkedList(); + list.insert('green'); + list.insert('yellow'); + let k = list.kthFromEnd(2); + + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('k should return error', ()=>{ + expect(k).toBe('error'); + }); +}); + +// Where k is not a positive integer +describe('Where k is not a positive integer', ()=>{ + let list = new LinkedList(); + list.insert('green'); + list.insert('yellow'); + let k = list.kthFromEnd(-3); + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('k should return an error message', ()=>{ + expect(k).toBe('k needs to be a postive integer'); + }); +}); +// Where the linked list is of a size 1 +describe('Where the linked list is of a size 1', ()=>{ + let list = new LinkedList(); + list.insert('green'); + let k = list.kthFromEnd(0); + it('head stays the same', ()=>{ + expect(list.head.data).toBe('green'); + }); + it('k should return green', ()=>{ + expect(k).toBe('green'); + }); +}); +// Where k is not at the end, but somewhere in the middle of the linked list +describe('Where k is not at the end, but somewhere in the middle of the linked list', ()=>{ + let list = new LinkedList(); + list.insert('green'); + list.insert('blue'); + list.insert('yellow'); + let k = list.kthFromEnd(1); + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('k should return blue', ()=>{ + expect(k).toBe('blue'); + }); +}); \ No newline at end of file diff --git a/Data-Structures/ll-kth-from-end/linked-list.js b/Data-Structures/ll-kth-from-end/linked-list.js new file mode 100644 index 0000000..c92ec34 --- /dev/null +++ b/Data-Structures/ll-kth-from-end/linked-list.js @@ -0,0 +1,107 @@ +const Node = require('./node.js'); + +// instantiate an empty linked list +class LinkedList { + constructor(){ + this.head = null; + } + // insert item into the beginning of the list + insert(data){ + let inserted = new Node(data); + inserted.next = this.head; + this.head = inserted; + return this.head; + } + // A function called includes which takes in a value and returns a boolean if that value exists in the linked list + includes(searchValue) { + let currentNode = this.head; + while(currentNode) { + if (currentNode.data === searchValue){ + return true; + } + currentNode = currentNode.next; + } + return false; + } + // A function called toString which takes in no arguments and returns a string representing all the values in the linked list + toString(){ + let stringList = []; + let currentNode = this.head; + while(currentNode){ + stringList.push(currentNode.data); + currentNode = currentNode.next; + } + return stringList.toString(); + + } + // A function called append which adds a Node to the end of the list + append(data){ + let appendedItem = new Node(data); + let currentNode = this.head; + if(this.head === null){ + this.head = appendedItem; + return this.head; + } else{ + while(currentNode.next){ + currentNode = currentNode.next; + } + currentNode.next = appendedItem; + } + } + insertBefore(data, before){ + let insertedItem = new Node(data); + let currentNode = this.head; + if(currentNode.data === before){ + this.insert(data); + return; + } + + while(currentNode.next){ + if(currentNode.next.data === before){ + insertedItem.next = currentNode.next; + currentNode.next = insertedItem; + return; + } + currentNode = currentNode.next; + } + + } + + insertAfter(data, after){ + let insertedItem = new Node(data); + let currentNode = this.head; + + while(currentNode){ + if(currentNode.data === after){ + insertedItem.next = currentNode.next; + currentNode.next = insertedItem; + return; + } + currentNode = currentNode.next; + } + + } + + kthFromEnd(k){ + let listArray = []; + let currentNode = this.head; + while(currentNode){ + listArray.push(currentNode.data); + currentNode = currentNode.next; + } + if(k < 0){ + return 'k needs to be a postive integer'; + } + let kIndex = ((listArray.length - 1) - k); + if(kIndex < 0){ + return 'error'; + } else { + return listArray[kIndex]; + } + } + + +} + + +module.exports = LinkedList; \ No newline at end of file diff --git a/Data-Structures/ll-kth-from-end/node.js b/Data-Structures/ll-kth-from-end/node.js new file mode 100644 index 0000000..ae7d7e9 --- /dev/null +++ b/Data-Structures/ll-kth-from-end/node.js @@ -0,0 +1,10 @@ +'use strict'; + +class Node { + constructor(value){ + this.data = value; + this.next = null; + } +} + +module.exports = Node; \ No newline at end of file diff --git a/Data-Structures/ll-kth-from-end/readme.md b/Data-Structures/ll-kth-from-end/readme.md new file mode 100644 index 0000000..6e5631d --- /dev/null +++ b/Data-Structures/ll-kth-from-end/readme.md @@ -0,0 +1,31 @@ +# Singly Linked List with K-th Search Method + +More complex functions for singly linked lists + +## Challenge + +Write a method for the LinkedList class which takes a number, k, as a parameter. Return the node’s value that is k from the end of the linked list. You have access to the Node class and all the properties on the LinkedList class as well as the methods created in previous challenges. + +#### Write tests to prove the following functionality: + +* Can successfully add a node to the end of the linked list +* Can successfully add multiple nodes to the end of a linked list +* Can successfully insert a node before a node located in the middle of a linked list +* Can successfully insert a node before the first node of a linked list +* Can successfully insert after a node in the middle of the linked list +* Can successfully insert a node after the last node of the linked list + +## Approach & Efficiency + +O(n) +We never go deeper than one interation of the list so Big O(n) is still applicable + +## API + +insert(data) - Creates a new Node Object. Appends the new Node object to the beginning of the linked list +includes(searchValue) - Takes in a value as a paramenter and returns a boolean if the value exists in the linked list +toString() - Returns a string with all the values in the linked list +append(data) - Adds a node to the end of the list +insertBefore(data, before) - Adds a Node before a certain Node in the list +insertAfter(data, after) - Adds a Node after a certain Node in the list +kthFromEnd(k) - returns the value of a node at the kth index \ No newline at end of file diff --git a/Data-Structures/ll-merge/__tests__/ll-merge.test.js b/Data-Structures/ll-merge/__tests__/ll-merge.test.js new file mode 100644 index 0000000..600449c --- /dev/null +++ b/Data-Structures/ll-merge/__tests__/ll-merge.test.js @@ -0,0 +1,313 @@ +const LinkedList = require('../ll-merge.js'); + +xdescribe('Test', () => { + it('true', ()=>{ + expect(true).toBeTruthy(); + }); +}); + +// * Can successfully instantiate an empty linked list +xdescribe('instantiate an empty linked list', ()=>{ + let list = new LinkedList(); + it('empty list',()=>{ + expect(list).toBeTruthy(); + }); +}); + +// * Can properly insert into the linked list +xdescribe('insert into the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + + it('successfully inserts into list', ()=>{ + expect(list.head.data).toBe('yellow'); + + }); + +}); +// * The head property will properly point to the first node in the linked list +xdescribe('The head property will properly point to the first node in the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.insert('blue'); + + it('first node is correct', ()=>{ + expect(list.head.data).toBe('blue'); + }); + +}); +// * Can properly insert multiple nodes into the linked list +xdescribe('Can properly insert multiple nodes into the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.insert('blue'); + + it('successfully added head', ()=>{ + expect(list.head.data).toBe('blue'); + }); + it('successfully added 2nd value', ()=>{ + expect(list.head.next.data).toBe('yellow'); + }); +}); + +xdescribe('Will return true when finding a value within the linked list that exists', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.insert('blue'); + let searchResult = list.includes('yellow'); + let badSearchResult = list.includes('apple'); + + // Will return true when finding a value within the linked list that exists + it('Returns true for items that exist', ()=>{ + expect(searchResult).toBeTruthy(); + }); + // * Will return false when searching for a value in the linked list that does not exist + it('Returns false for items that do not exist', ()=>{ + expect(badSearchResult).toBeFalsy(); + }); +}); + + +// * Can properly return a collection of all the values that exist in the linked list +xdescribe('Can properly return a collection of all the values that exist in the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.insert('blue'); + list.insert('green'); + let allItems = list.toString(); + it('returns a collection', ()=>{ + expect(allItems).toBe('green,blue,yellow'); + }); + +}); + +// Can successfully add a node to the end of the linked list +xdescribe('Can successfully add a node to the end of the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('green'); + list.append('blue'); + + it('Items should be added to the end of the list', ()=>{ + expect(list.head.next.data).toBe('green'); + }); + // Can successfully add multiple nodes to the end of a linked list + it('Can add multiple nodes to the end of a list',()=>{ + expect(list.head.next.next.data).toBe('blue'); + }); + +}); + +// Can successfully insert a node before a node located in the middle of a linked list + +xdescribe('Can successfully insert a node before a node located in the middle of a linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('blue'); + list.insertBefore('green', 'blue'); + it('inserts in middle', ()=>{ + expect(list.head.next.data).toBe('green'); + }); + it('blue should be at the end', ()=>{ + expect(list.head.next.next.data).toBe('blue'); + }); + it('head should stay the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); +}); +// Can successfully insert a node before the first node of a linked list +xdescribe('Can successfully insert a node before a node located in the middle of a linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('blue'); + list.insertBefore('green', 'yellow'); + it('inserts at the head', ()=>{ + expect(list.head.data).toBe('green'); + }); + it('blue should be at the end', ()=>{ + expect(list.head.next.next.data).toBe('blue'); + }); + it('head should move over', ()=>{ + expect(list.head.next.data).toBe('yellow'); + }); +}); +// Can successfully insert after a node in the middle of the linked list +xdescribe('Can successfully insert a node after a node located in the middle of a linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('blue'); + list.insertAfter('green', 'yellow'); + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('blue should be at the end', ()=>{ + expect(list.head.next.next.data).toBe('blue'); + }); + it('new node should be in the middle', ()=>{ + expect(list.head.next.data).toBe('green'); + }); +}); +// Can successfully insert a node after the last node of the linked list +xdescribe('Can successfully insert a node after last node of a linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('blue'); + list.insertAfter('green', 'blue'); + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('green should be at the end', ()=>{ + expect(list.head.next.next.data).toBe('green'); + }); + it('blue should be in the middle', ()=>{ + expect(list.head.next.data).toBe('blue'); + }); +}); + +// Where k is greater than the length of the linked list +xdescribe(' Where k is greater than the length of the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + let k = list.kthFromEnd(3); + + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('k should return error', ()=>{ + expect(k).toBe('error'); + }); +}); + + +// Where k and the length of the list are the same +xdescribe('Where k and the length of the list are the same', ()=>{ + let list = new LinkedList(); + list.insert('green'); + list.insert('yellow'); + let k = list.kthFromEnd(2); + + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('k should return error', ()=>{ + expect(k).toBe('error'); + }); +}); + +// Where k is not a positive integer +xdescribe('Where k is not a positive integer', ()=>{ + let list = new LinkedList(); + list.insert('green'); + list.insert('yellow'); + let k = list.kthFromEnd(-3); + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('k should return an error message', ()=>{ + expect(k).toBe('k needs to be a postive integer'); + }); +}); +// Where the linked list is of a size 1 +xdescribe('Where the linked list is of a size 1', ()=>{ + let list = new LinkedList(); + list.insert('green'); + let k = list.kthFromEnd(0); + it('head stays the same', ()=>{ + expect(list.head.data).toBe('green'); + }); + it('k should return green', ()=>{ + expect(k).toBe('green'); + }); +}); +// Where k is not at the end, but somewhere in the middle of the linked list +xdescribe('Where k is not at the end, but somewhere in the middle of the linked list', ()=>{ + let list = new LinkedList(); + list.insert('green'); + list.insert('blue'); + list.insert('yellow'); + let k = list.kthFromEnd(1); + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('k should return blue', ()=>{ + expect(k).toBe('blue'); + }); +}); + +// Where list1 is the same length as list2 +xdescribe('Where list1 is the same length as list2', ()=>{ + let list1 = new LinkedList(); + let list2 = new LinkedList(); + list1.insert('1'); + list1.append('2'); + list2.insert('a'); + list2.append('b'); + let merged = new LinkedList(); + merged = merged.mergeLists(list1, list2); + + it('should return an alternating list', ()=>{ + expect(merged.head.data).toBe('1'); + expect(merged.head.next.data).toBe('a'); + expect(merged.head.next.next.data).toBe('2'); + expect(merged.head.next.next.next.data).toBe('b'); + }); +}); +// Where list1 is shorter than list2 +xdescribe('Where list1 is shorter than list2', ()=>{ + let list1 = new LinkedList(); + let list2 = new LinkedList(); + list1.insert('1'); + list2.insert('a'); + list2.append('b'); + let merged = new LinkedList(); + merged = merged.mergeLists(list1, list2); + + it('should return an alternating list', ()=>{ + expect(merged.head.data).toBe('a'); + expect(merged.head.next.data).toBe('1'); + expect(merged.head.next.next.data).toBe('b'); + }); +}); +// Where list1 is longer than list2 +xdescribe('Where list1 is longer than list2', ()=>{ + let list1 = new LinkedList(); + let list2 = new LinkedList(); + list1.insert('1'); + list1.append('2'); + list2.insert('a'); + let merged = new LinkedList(); + merged = merged.mergeLists(list1, list2); + + it('should return an alternating list', ()=>{ + expect(merged.head.data).toBe('1'); + expect(merged.head.next.data).toBe('a'); + expect(merged.head.next.next.data).toBe('2'); + }); +}); +// Where list1 is null +xdescribe('Where list1 is null', ()=>{ + let list1 = null; + let list2 = new LinkedList(); + list2.insert('a'); + list2.insert('b'); + let merged = new LinkedList(); + merged = merged.mergeLists(list1, list2); + + it('should return an alternating list', ()=>{ + expect(merged).toBe('Not valid Linked List'); + }); +}); +// Where both lists are of length 1 +xdescribe('Where both lists are of length 1', ()=>{ + let list1 = new LinkedList(); + let list2 = new LinkedList(); + list1.insert('1'); + list2.insert('a'); + let merged = new LinkedList(); + merged = merged.mergeLists(list1, list2); + + it('should return an alternating list', ()=>{ + expect(merged.head.data).toBe('1'); + expect(merged.head.next.data).toBe('a'); + }); +}); \ No newline at end of file diff --git a/Data-Structures/ll-merge/ll-merge.js b/Data-Structures/ll-merge/ll-merge.js new file mode 100644 index 0000000..9f5cd64 --- /dev/null +++ b/Data-Structures/ll-merge/ll-merge.js @@ -0,0 +1,141 @@ +const Node = require('./node.js'); + +// instantiate an empty linked list +class LinkedList { + constructor(){ + this.head = null; + } + // insert item into the beginning of the list + insert(data){ + let inserted = new Node(data); + inserted.next = this.head; + this.head = inserted; + return this.head; + } + // A function called includes which takes in a value and returns a boolean if that value exists in the linked list + includes(searchValue) { + let currentNode = this.head; + while(currentNode) { + if (currentNode.data === searchValue){ + return true; + } + currentNode = currentNode.next; + } + return false; + } + // A function called toString which takes in no arguments and returns a string representing all the values in the linked list + toString(){ + let stringList = []; + let currentNode = this.head; + while(currentNode){ + stringList.push(currentNode.data); + currentNode = currentNode.next; + } + return stringList.toString(); + + } + // A function called append which adds a Node to the end of the list + append(data){ + let appendedItem = new Node(data); + let currentNode = this.head; + if(this.head === null){ + this.head = appendedItem; + return this.head; + } else{ + while(currentNode.next){ + currentNode = currentNode.next; + } + currentNode.next = appendedItem; + } + } + insertBefore(data, before){ + let insertedItem = new Node(data); + let currentNode = this.head; + if(currentNode.data === before){ + this.insert(data); + return; + } + + while(currentNode.next){ + if(currentNode.next.data === before){ + insertedItem.next = currentNode.next; + currentNode.next = insertedItem; + return; + } + currentNode = currentNode.next; + } + + } + + insertAfter(data, after){ + let insertedItem = new Node(data); + let currentNode = this.head; + + while(currentNode){ + if(currentNode.data === after){ + insertedItem.next = currentNode.next; + currentNode.next = insertedItem; + return; + } + currentNode = currentNode.next; + } + + } + + kthFromEnd(k){ + let listArray = []; + let currentNode = this.head; + while(currentNode){ + listArray.push(currentNode.data); + currentNode = currentNode.next; + } + if(k < 0){ + return 'k needs to be a postive integer'; + } + let kIndex = ((listArray.length - 1) - k); + if(kIndex < 0){ + return 'error'; + } else { + return listArray[kIndex]; + } + } + mergeLists(list1, list2){ + if(list1 === null || list2 === null){ + return 'Not valid Linked List'; + } + let array1 = list1.toString().split(','); + let array2 = list2.toString().split(','); + let final = new LinkedList; + if (array1.length - array2.length > 1 || array2.length - array1.length > 1){ + return 'Linked Lists are not close enough in length'; + } + if (array1.length >= array2.length) { + let answer = []; + for(let i = 0; i < array1.length; i++) { + answer.push([array1[i], array2[i]]); + answer = [].concat.apply([], answer); + } + answer.forEach(item=>{ + final.append(item); + }); + return final; + } + if (array1.length < array2.length){ + let answer = []; + for(let i = 0; i < array2.length+1; i++){ + answer.push([array2[i], array1[i]]); + answer = [].concat.apply([], answer); + } + answer.forEach(item=>{ + final.append(item); + }); + return final; + } + return null; + } + + +} + + +module.exports = LinkedList; \ No newline at end of file diff --git a/Data-Structures/ll-merge/node.js b/Data-Structures/ll-merge/node.js new file mode 100644 index 0000000..ae7d7e9 --- /dev/null +++ b/Data-Structures/ll-merge/node.js @@ -0,0 +1,10 @@ +'use strict'; + +class Node { + constructor(value){ + this.data = value; + this.next = null; + } +} + +module.exports = Node; \ No newline at end of file diff --git a/Data-Structures/ll-merge/readme.md b/Data-Structures/ll-merge/readme.md new file mode 100644 index 0000000..b3d3bf3 --- /dev/null +++ b/Data-Structures/ll-merge/readme.md @@ -0,0 +1,18 @@ +# Merging two Singly Linked Lists + + + +## Challenge + +* Write a method called mergeLists which takes two linked lists as arguments +* Merge the two lists together such that the final linked list has nodes that alternate between the nodes from each source list +* Return the head of the new merged list +* You have access to the Node class and all the properties on the Linked List class as well as the methods created in previous challenges. + +## Approach & Efficiency + + + +## API + + diff --git a/README.md b/README.md index f2dd06e..540b532 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,20 @@ # data-structures-and-algorithms ## Table of Contents - -[Array-Reverse](./challenges/arrayReverse) \ No newline at end of file +#### Challenge 1 +[1. Array-Reverse](./challenges/arrayReverse) +#### Challenge 2 +[2. Array-Shift](./challenges/ArrayShift) +#### Challenge 3 +[Array-Binary-Search](./challenges/arrayBinarySearch) +#### Challenge 5 +[Link-List](./Data-Structures/LinkList) +#### Challenge 6 +[ll-Insertions](./Data-Structures/ll-Insertions) +#### Challenge 7 +[ll-kth-from-end](./Data-Structures/ll-kth-from-end) +#### Challenge 8 +[ll-merge](./Data-Structures/ll-merge) +#### Challenge 9 +[Stack-And-Queue](./stacksAndQueues/) +### Challenge 11 +[Queues-With-Stacks](./queueWithStacks) \ No newline at end of file diff --git a/assets/AWS-1.png b/assets/AWS-1.png new file mode 100644 index 0000000..fdccb7a Binary files /dev/null and b/assets/AWS-1.png differ diff --git a/assets/ArrayShift.jpg b/assets/ArrayShift.jpg new file mode 100644 index 0000000..af68296 Binary files /dev/null and b/assets/ArrayShift.jpg differ diff --git a/assets/CodeChallenge3.jpg b/assets/CodeChallenge3.jpg new file mode 100644 index 0000000..01dea63 Binary files /dev/null and b/assets/CodeChallenge3.jpg differ diff --git a/assets/aws terminal.png b/assets/aws terminal.png new file mode 100644 index 0000000..7336956 Binary files /dev/null and b/assets/aws terminal.png differ diff --git a/challenges/ArrayShift/README.md b/challenges/ArrayShift/README.md new file mode 100644 index 0000000..243916b --- /dev/null +++ b/challenges/ArrayShift/README.md @@ -0,0 +1,11 @@ +# Challenge Summary +insertShiftArray is a function which takes in an array and the value to be added. Without utilizing any of the built-in methods available to javascript, it return an array with the new value added at the middle index. + +## Challenge Description +Write a function called insertShiftArray which takes in an array and the value to be added. Without utilizing any of the built-in methods available to your language, return an array with the new value added at the middle index. + +## Approach & Efficiency +O(N) + +## Solution +![UML](../../assets/ArrayShift.jpg) diff --git a/challenges/ArrayShift/__tests__/array-shift.test.js b/challenges/ArrayShift/__tests__/array-shift.test.js new file mode 100755 index 0000000..5bd253c --- /dev/null +++ b/challenges/ArrayShift/__tests__/array-shift.test.js @@ -0,0 +1,19 @@ +'use strict'; + +const arrayShift = require('../array-shift.js'); + + +xdescribe('Testing challenge', () => { + it('return an array with the new value added at the middle index', () => { + expect(arrayShift([2,4,6,8], 5)).toStrictEqual([2, 4, 5, 6, 8]); + expect(arrayShift([4,8,15,23,42], 16).length).toStrictEqual(4,8,15,16, 23,42); + }); + +}); + +xdescribe('Test', () => { + // How might we repeat this to check on types? + it('true', ()=>{ + expect(true).toBeTruthy(); + }); +}); diff --git a/challenges/ArrayShift/array-shift.js b/challenges/ArrayShift/array-shift.js new file mode 100644 index 0000000..a53a1a9 --- /dev/null +++ b/challenges/ArrayShift/array-shift.js @@ -0,0 +1,32 @@ +'use strict'; +const arrayShift = {}; + +arrayShift.insertShiftArray = (a, b)=>{ + let answer = []; + let middle = 0; + if(a.length % 2 === 0){ + middle = (a.length / 2); + } else { + middle = ((a.length + 1) / 2); + } + for (let i=0; i< middle; i++){ + answer[i] = a[i]; + } + answer[middle]= b; + for (let i=middle; i< a.length; i++){ + answer[i+1] = a[i]; + } + return answer; +}; + + + +// let test1 = [2,4,6,8]; +// let test1Insert = 5; + +// let test2 = [4,8,15,23,42]; +// let test2Insert = 16; +// console.log('test 1 ', insertShiftArray(test1, test1Insert)); +// console.log('test 2 ', insertShiftArray(test2, test2Insert)); + +module.exports = arrayShift; \ No newline at end of file diff --git a/challenges/arrayBinarySearch/README.md b/challenges/arrayBinarySearch/README.md new file mode 100644 index 0000000..196a990 --- /dev/null +++ b/challenges/arrayBinarySearch/README.md @@ -0,0 +1,18 @@ +# Author: +Morgan Shaw +Nadya Ilinskaya +James Dunn + +# Binary Search +A function called BinarySearch which takes in 2 parameters: a sorted array and the search key. It returns the index of the array’s element that is equal to the search key, or -1 if the element does not exist. + +## Challenge +Write a function called BinarySearch which takes in 2 parameters: a sorted array and the search key. Without utilizing any of the built-in methods available to your language, return the index of the array’s element that is equal to the search key, or -1 if the element does not exist. + +## Approach & Efficiency +While loop through the array: Find the middle of the array. Compare the value that is located at the index = middle to the search key. Because the array is sorted we can determine to change our search parameters to the left or the right of the array. Once the index is found return the index, if the key does not exist in the array return -1. + +## Solution +[link](./array-binary-search.js) +[Repl.it](https://repl.it/repls/OrneryCurlyDividend) +![UML Diagram](../../assets/CodeChallenge3.jpg) \ No newline at end of file diff --git a/challenges/arrayBinarySearch/__tests__/arrayBinary.test.js b/challenges/arrayBinarySearch/__tests__/arrayBinary.test.js new file mode 100755 index 0000000..e069e4a --- /dev/null +++ b/challenges/arrayBinarySearch/__tests__/arrayBinary.test.js @@ -0,0 +1,16 @@ +'use strict'; +const BinarySearch = require('../array-binary-search.js'); +xdescribe('Testing challenge', () => { + it('it should return the index of the array’s element that is equal to the search key', () => { + expect(BinarySearch([4,8,15,16,23], 15)).toStrictEqual(2); + }); + it('it should return -1 if the search key does not exist', () => { + expect(BinarySearch([11,22,33,44,55,66,77], 90)).toStrictEqual(-1); + }); + it('it should return the index of the array’s element that is equal to the search key', () => { + expect(BinarySearch([4,8,15,16,23,42,90], 8)).toStrictEqual(1); + }); + it('it should return the index of the array’s element that is equal to the search key', () => { + expect(BinarySearch([4,8,15,16,23,42], 42)).toStrictEqual(5); + }); +}); \ No newline at end of file diff --git a/challenges/arrayBinarySearch/array-binary-search.js b/challenges/arrayBinarySearch/array-binary-search.js new file mode 100644 index 0000000..cb87de5 --- /dev/null +++ b/challenges/arrayBinarySearch/array-binary-search.js @@ -0,0 +1,25 @@ +'Use Strict'; + +//this is the function that will search an array for a given input +const BinarySearch = (arr, search)=>{ + //check if middle index matches key + let firstIndex = 0; + let lastIndex = arr.length - 1; + while (firstIndex <= lastIndex) { + let middle = Math.floor((firstIndex + lastIndex) / 2); + if (arr[middle] === search) { + return middle; + } + if (arr[middle] > search) { + // if search is less, then firstIndex stays same + // and lastIndex changes to middle minus 1 + lastIndex = --middle; + // divide that by two, and make that new middle + } else if (arr[middle] < search) { + firstIndex = ++middle; + } + } + return -1; +}; + +module.exports = BinarySearch; diff --git a/package.json b/package.json index b42cee4..628ee97 100644 --- a/package.json +++ b/package.json @@ -4,13 +4,17 @@ "description": "", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "start": "node index.js", + "lint": "eslint \"**/*.js\"", + "test": "jest --verbose --coverage", + "test-watch": "jest --watchAll --verbose --coverage", + "jsdoc": "jsdoc -c ./docs/config/jsdoc.config.json" }, "repository": { "type": "git", "url": "git+https://github.com/morgan-401-advanced-javascript/data-structures-and-algorithms.git" }, - "author": "", + "author": "Morgan T Shaw", "license": "ISC", "bugs": { "url": "https://github.com/morgan-401-advanced-javascript/data-structures-and-algorithms/issues" diff --git a/queueWithStacks/README.md b/queueWithStacks/README.md new file mode 100644 index 0000000..1456d8d --- /dev/null +++ b/queueWithStacks/README.md @@ -0,0 +1,29 @@ +# Pseudo Queue + +## Links + +- [ Link to your Pull Request](https://github.com/morgan-401-advanced-javascript/data-structures-and-algorithms/pull/9) +- [Link to your Travis](https://travis-ci.com/morgan-401-advanced-javascript/data-structures-and-algorithms/jobs/252463737) + +Implement a Queue using two Stacks. + +## Challenge +Create a brand new PseudoQueue class. Do not use an existing Queue. Instead, this PseudoQueue class will implement our standard queue interface (the two methods listed below), but will internally only utilize two Stack objects. Ensure that you create your class with the following methods: + +* enqueue(value) which inserts value into the PseudoQueue, using a last-in, last-out approach. +* dequeue() which extracts a value from the PseudoQueue, using a first-in, first-out approach. + +The Stack instances have only push, pop, and peek methods. You should use your own Stack implementation. Instantiate these Stack objects in your PseudoQueue constructor. + +## Approach & Efficiency + + enqueue(value) - O(1) This function simply adds a single value to the queue. Because it only does one action and no more it is Big O(1) + dequeue() - O(n) This will have to shift the items in the queue between two stacks inorder to pop the first item off the queue. Because it will need to traverse through the entire queue it is Big O(n) + + +## API +class PsuedoQueue{ + + `enqueue(value) `which inserts value into the PseudoQueue, using a last-in, last-out approach. + `dequeue()` which extracts a value from the PseudoQueue, using a first-in, first-out approach. +} \ No newline at end of file diff --git a/queueWithStacks/__tests__/queue-with-stacks.test.js b/queueWithStacks/__tests__/queue-with-stacks.test.js new file mode 100644 index 0000000..2a6f9e4 --- /dev/null +++ b/queueWithStacks/__tests__/queue-with-stacks.test.js @@ -0,0 +1,46 @@ +const PsuedoQueue = require('../queue-with-stacks.js'); + +describe('Test Queue With Stacks', () => { + // Can successfully enqueue into your pseudo queue + it('Can successfully enqueue into your pseudo queue', ()=>{ + let queue = new PsuedoQueue(); + queue.enqueue('a'); + expect(queue.stackOne.top.data).toBe('a'); + }); + // Can successfully enqueue multiple values into your queue + it('Can successfully enqueue multiple values into your queue', ()=>{ + let queue = new PsuedoQueue(); + queue.enqueue('a'); + queue.enqueue('b'); + expect(queue.stackOne.top.data).toBe('b'); + expect(queue.stackOne.top.next.data).toBe('a'); + }); + // Can successfully dequeue out of a queue the expected value + it('Can successfully dequeue out of a queue the expected value', ()=>{ + let queue = new PsuedoQueue(); + queue.enqueue('a'); + queue.enqueue('b'); + queue.enqueue('c'); + // queue.dequeue(); + // expect(queue).toBe('b'); + expect(queue.dequeue()).toBe('a'); + }); + // Can successfully empty a queue after multiple dequeues + it('Can successfully empty a queue after multiple dequeues', ()=>{ + let queue = new PsuedoQueue(); + queue.enqueue('a'); + queue.enqueue('b'); + queue.enqueue('c'); + queue.dequeue(); + queue.dequeue(); + queue.dequeue(); + // expect(queue).toBe('b'); + expect(queue.stackOne.top).toBe(null); + }); + // Can successfully instantiate an empty queue + it('Can successfully instantiate an empty queue', ()=>{ + let queue = new PsuedoQueue(); + // expect(queue).toBe('b'); + expect(queue).toBeTruthy(); + }); +}); diff --git a/queueWithStacks/node.js b/queueWithStacks/node.js new file mode 100644 index 0000000..ae7d7e9 --- /dev/null +++ b/queueWithStacks/node.js @@ -0,0 +1,10 @@ +'use strict'; + +class Node { + constructor(value){ + this.data = value; + this.next = null; + } +} + +module.exports = Node; \ No newline at end of file diff --git a/queueWithStacks/queue-with-stacks.js b/queueWithStacks/queue-with-stacks.js new file mode 100644 index 0000000..7ec9949 --- /dev/null +++ b/queueWithStacks/queue-with-stacks.js @@ -0,0 +1,25 @@ +'Use Strict'; +const Stack = require('./stacks.js'); + + + +class PsuedoQueue{ + constructor(){ + this.stackOne = new Stack(); + this.stackTwo = new Stack(); + } + enqueue(value){ + this.stackOne.push(value); + } + dequeue(){ + + while(this.stackOne.top !== null){ + let current = this.stackOne.pop(); + this.stackTwo.push(current); + } + return this.stackTwo.pop(); + } +} + + +module.exports = PsuedoQueue; \ No newline at end of file diff --git a/queueWithStacks/stacks.js b/queueWithStacks/stacks.js new file mode 100644 index 0000000..bad9549 --- /dev/null +++ b/queueWithStacks/stacks.js @@ -0,0 +1,41 @@ +'Use Strict'; +const Node = require('./node.js'); + +class Stack { + constructor(){ + this.top = null; + } + push(value){ + if(value !== null){ + let newItem = new Node(value); + if(this.top !== null){ + newItem.next = this.top; + this.top = newItem; + } else { + this.top = newItem; + } + + } else { + return 'bad value'; + } + } + pop(){ + if(this.top !== null){ + this.temp = this.top; + this.top = this.temp.next; + return this.temp.data; + } else { + return 'null'; + } + } + peek(){ + if(this.top !== null){ + return this.top.data; + }else{ + return 'no data!'; + } + + } +} + +module.exports = Stack; \ No newline at end of file diff --git a/stacksAndQueues/__tests__/stacks-and-queues.test.js b/stacksAndQueues/__tests__/stacks-and-queues.test.js new file mode 100644 index 0000000..04e6a63 --- /dev/null +++ b/stacksAndQueues/__tests__/stacks-and-queues.test.js @@ -0,0 +1,144 @@ +const StackAndQueues = require('../stacks-and-queues.js'); + +describe('Test', () => { + console.log('\x1b[36m\x1b[34m%s\x1b[0m', ` + ______ _ + | _ \\ | | + | | | | ___ _ __ ___ ___ | | + | | | | / _ \\| '_ \` _ \\ / _ \\ | | + | |/ / | __/| | | | | || (_) ||_| + |___/ \\___||_| |_| |_| \\___/ (_)`); + it('true', ()=>{ + expect(true).toBeTruthy(); + }); +}); + +// Can successfully push onto a stack +describe('Can successfully push onto a stack', ()=>{ + let stack = new StackAndQueues.Stack(); + stack.push('a'); + it('adds to the stack', ()=>{ + expect(stack.top.data).toBe('a'); + }); + +}); +// Can successfully push multiple values onto a stack +describe('Can successfully push multiple values onto a stack', ()=>{ + let stack = new StackAndQueues.Stack(); + stack.push('a'); + stack.push('b'); + it('should be b', ()=>{ + expect(stack.top.data).toBe('b'); + }); + it('should be a', ()=>{ + expect(stack.top.next.data).toBe('a'); + }); +}); +// Can successfully pop off the stack +describe('Can successfully pop off the stack', ()=>{ + let stack = new StackAndQueues.Stack(); + stack.push('a'); + stack.push('b'); + stack.pop(); + it('should be a', ()=>{ + expect(stack.top.data).toBe('a'); + }); + it('returns pop value', ()=>{ + expect(stack.pop()).toBe('a'); + }); +}); + +// Can successfully empty a stack after multiple pops +describe('Can successfully empty a stack after multiple pops', ()=>{ + let stack = new StackAndQueues.Stack(); + stack.push('a'); + stack.push('b'); + stack.pop(); + stack.pop(); + it('should be a', ()=>{ + expect(stack.top).toBe(null); + }); +}); +// Can successfully peek the next item on the stack +describe('Can successfully peek the next item on the stack', ()=>{ + let stack = new StackAndQueues.Stack(); + stack.push('a'); + stack.push('b'); + let peekItem= stack.peek(); + + it('should be b', ()=>{ + expect(stack.top.data).toBe('b'); + }); + it('should be a', ()=>{ + expect(stack.top.next.data).toBe('a'); + }); + it('Peeked item should be b', ()=>{ + expect(peekItem).toBe('b'); + }); +}); +// Can successfully instantiate an empty stack +describe('Can successfully instantiate an empty stack', ()=>{ + let stack = new StackAndQueues.Stack(); + it('empty stack', ()=>{ + expect(stack.top).toBe(null); + }); +}); +// Can successfully enqueue into a queue +describe('Can successfully enqueue into a queue', ()=>{ + let queue = new StackAndQueues.Queue(); + queue.enqueue('a'); + queue.enqueue('b'); + queue.enqueue('c'); + it('Can successfully enqueue into a queue', ()=>{ + expect(queue.front.data).toBe('a'); + }); + // Can successfully enqueue multiple values into a queue + it('Can successfully enqueue multiple values into a queue', ()=>{ + expect(queue.front.data).toBe('a'); + expect(queue.front.next.data).toBe('b'); + expect(queue.rear.data).toBe('c'); + }); +}); + +// Can successfully dequeue out of a queue the expected value +describe('Can successfully dequeue out of a queue the expected value', ()=>{ + let queue = new StackAndQueues.Queue(); + queue.enqueue('a'); + queue.enqueue('b'); + queue.enqueue('c'); + + it('Can successfully dequeue', ()=>{ + expect(queue.dequeue()).toBe('a'); + }); +}); +// Can successfully peek into a queue, seeing the expected value +describe('Can successfully dequeue out of a queue the expected value', ()=>{ + let queue = new StackAndQueues.Queue(); + queue.enqueue('a'); + queue.enqueue('b'); + queue.enqueue('c'); + + it('Can successfully dequeue', ()=>{ + expect(queue.peek()).toBe('a'); + }); +}); +// Can successfully empty a queue after multiple dequeues +describe('Can successfully empty a queue after multiple dequeues', ()=>{ + let queue = new StackAndQueues.Queue(); + queue.enqueue('a'); + queue.enqueue('b'); + queue.dequeue(); + queue.dequeue(); + + it('Can successfully dequeue', ()=>{ + expect(queue.front).toBe(null); + }); +}); +// Can successfully instantiate an empty queue +describe('Can successfully instantiate an empty queue', ()=>{ + let queue = new StackAndQueues.Queue(); + + it('ITS ALIVE!', ()=>{ + expect(queue.front).toBe(null); + }); +}); \ No newline at end of file diff --git a/stacksAndQueues/linked-list.js b/stacksAndQueues/linked-list.js new file mode 100644 index 0000000..0c095b6 --- /dev/null +++ b/stacksAndQueues/linked-list.js @@ -0,0 +1,141 @@ +const Node = require('./node.js.js'); + +// instantiate an empty linked list +class LinkedList { + constructor(){ + this.head = null; + } + // insert item into the beginning of the list + insert(data){ + let inserted = new Node(data); + inserted.next = this.head; + this.head = inserted; + return this.head; + } + // A function called includes which takes in a value and returns a boolean if that value exists in the linked list + includes(searchValue) { + let currentNode = this.head; + while(currentNode) { + if (currentNode.data === searchValue){ + return true; + } + currentNode = currentNode.next; + } + return false; + } + // A function called toString which takes in no arguments and returns a string representing all the values in the linked list + toString(){ + let stringList = []; + let currentNode = this.head; + while(currentNode){ + stringList.push(currentNode.data); + currentNode = currentNode.next; + } + return stringList.toString(); + + } + // A function called append which adds a Node to the end of the list + append(data){ + let appendedItem = new Node(data); + let currentNode = this.head; + if(this.head === null){ + this.head = appendedItem; + return this.head; + } else{ + while(currentNode.next){ + currentNode = currentNode.next; + } + currentNode.next = appendedItem; + } + } + insertBefore(data, before){ + let insertedItem = new Node(data); + let currentNode = this.head; + if(currentNode.data === before){ + this.insert(data); + return; + } + + while(currentNode.next){ + if(currentNode.next.data === before){ + insertedItem.next = currentNode.next; + currentNode.next = insertedItem; + return; + } + currentNode = currentNode.next; + } + + } + + insertAfter(data, after){ + let insertedItem = new Node(data); + let currentNode = this.head; + + while(currentNode){ + if(currentNode.data === after){ + insertedItem.next = currentNode.next; + currentNode.next = insertedItem; + return; + } + currentNode = currentNode.next; + } + + } + + kthFromEnd(k){ + let listArray = []; + let currentNode = this.head; + while(currentNode){ + listArray.push(currentNode.data); + currentNode = currentNode.next; + } + if(k < 0){ + return 'k needs to be a postive integer'; + } + let kIndex = ((listArray.length - 1) - k); + if(kIndex < 0){ + return 'error'; + } else { + return listArray[kIndex]; + } + } + mergeLists(list1, list2){ + if(list1 === null || list2 === null){ + return 'Not valid Linked List'; + } + let array1 = list1.toString().split(','); + let array2 = list2.toString().split(','); + let final = new LinkedList; + if (array1.length - array2.length > 1 || array2.length - array1.length > 1){ + return 'Linked Lists are not close enough in length'; + } + if (array1.length >= array2.length) { + let answer = []; + for(let i = 0; i < array1.length; i++) { + answer.push([array1[i], array2[i]]); + answer = [].concat.apply([], answer); + } + answer.forEach(item=>{ + final.append(item); + }); + return final; + } + if (array1.length < array2.length){ + let answer = []; + for(let i = 0; i < array2.length+1; i++){ + answer.push([array2[i], array1[i]]); + answer = [].concat.apply([], answer); + } + answer.forEach(item=>{ + final.append(item); + }); + return final; + } + return null; + } + + +} + + +module.exports = LinkedList; \ No newline at end of file diff --git a/stacksAndQueues/node.js b/stacksAndQueues/node.js new file mode 100644 index 0000000..ae7d7e9 --- /dev/null +++ b/stacksAndQueues/node.js @@ -0,0 +1,10 @@ +'use strict'; + +class Node { + constructor(value){ + this.data = value; + this.next = null; + } +} + +module.exports = Node; \ No newline at end of file diff --git a/stacksAndQueues/readme.md b/stacksAndQueues/readme.md new file mode 100644 index 0000000..8543423 --- /dev/null +++ b/stacksAndQueues/readme.md @@ -0,0 +1,49 @@ +# Stacks and Queues + +Implement a Stack and a Queue Data Structure +[Travis](https://travis-ci.com/morgan-401-advanced-javascript/data-structures-and-algorithms/builds/134682110) + +## Challenge + +* Can successfully push onto a stack +* Can successfully push multiple values onto a stack +* Can successfully pop off the stack +* Can successfully empty a stack after multiple pops +* Can successfully peek the next item on the stack +* Can successfully instantiate an empty stack +* Can successfully enqueue into a queue +* Can successfully enqueue multiple values into a queue +* Can successfully dequeue out of a queue the expected value +* Can successfully peek into a queue, seeing the expected value +* Can successfully empty a queue after multiple dequeues +* Can successfully instantiate an empty queue + +## Approach & Efficiency +Stack: +* push O(1) we only manipulate the first item in the stack +* pop O(1) we only manipulate the first item in the stack +* peek O(1) we only manipulate the first item in the stack + +Queue: +* enqueue O(1) we only manipulate one item in the stack +* dequeue O(1) we only manipulate one item in the stack +* peek O(1) we only manipulate one item in the stack +## API +`class Stack { + constructor(){ + this.top = null; + } + push(value) + pop() + peek() +}` + +`class Queue { + constructor(){ + this.front = null; + this.rear = null; + } + enqueue(value) + dequeue() + peek() +}` diff --git a/stacksAndQueues/stacks-and-queues.js b/stacksAndQueues/stacks-and-queues.js new file mode 100644 index 0000000..53d7d8b --- /dev/null +++ b/stacksAndQueues/stacks-and-queues.js @@ -0,0 +1,78 @@ +'use strict'; +const Node = require('./node.js'); + +class Stack { + constructor(){ + this.top = null; + } + push(value){ + if(value !== null){ + let newItem = new Node(value); + if(this.top !== null){ + newItem.next = this.top; + this.top = newItem; + } else { + this.top = newItem; + } + + } else { + return 'bad value'; + } + } + pop(){ + if(this.top !== null){ + this.temp = this.top; + this.top = this.temp.next; + return this.temp.data; + } else { + return 'null'; + } + } + peek(){ + if(this.top !== null){ + return this.top.data; + }else{ + return 'no data!'; + } + + } +} + +class Queue { + constructor(){ + this.front = null; + this.rear = null; + } + enqueue(value){ + if(value !== null){ + let newItem = new Node(value); + if(this.rear === null){ + this.rear = newItem; + this.front = newItem; + }else{ + this.rear.next = newItem; + this.rear = newItem; + } + }else{ + return 'bad value'; + } + } + dequeue(){ + if(this.front !== null){ + this.temp = this.front; + this.front = this.temp.next; + return this.temp.data; + }else{ + return 'null'; + } + } + peek(){ + if(this.front !== null){ + return this.front.data; + }else{ + return 'empty queue'; + } + } +} + +module.exports = { Stack, Queue}; \ No newline at end of file