1
0

First commit

This commit is contained in:
Timothy Warren 2019-07-26 16:25:13 -04:00
commit 57cfa8ad19
7 changed files with 565 additions and 0 deletions

4
package.json Normal file
View File

@ -0,0 +1,4 @@
{
"type": "module",
"main": "./src/usage.js"
}

View File

@ -0,0 +1,118 @@
const root = Symbol("root");
class BinarySearchTreeNode {
constructor (value) {
this.value = value;
this.left = null;
this.right = null;
}
}
class BinarySearchTree {
constructor () {
this[root] = null;
}
add (value) {
const node = new BinarySearchTreeNode(value);
let current = null;
// No items in tree
if (this[root] === null) {
this[root] = node;
} else {
current = this[root];
while (true) {
if (value < current.value) {
// If there's no left, insert
if (current.left === null) {
current.left = node;
break;
}
current = current.left;
} else if (value > current.value) {
if (current.right === null) {
current.right = node;
break;
}
current = current.right;
} else {
break;
}
}
}
}
contains (value) {
let found = false;
let current = this[root];
while ( ! found && current !== null) {
if (value < current.value) {
current = current.left;
} else if (value > current.value) {
current = current.right;
} else if (value === current.value) {
found = true;
}
}
return found;
}
remove (value) {
}
size () {
let length = 0;
this.traverse(() => {
length++;
});
return length;
}
traverse (process) {
const inOrder = (node) => {
if ( ! node) {
return;
}
// traverse the left subtree
if (node.left !== null) {
inOrder(node.left);
}
// handle the current node
process.call(this, node);
// traverse the right subtree
if (node.right !== null) {
inOrder(node.right);
}
};
// start with the root
inOrder(this[root]);
}
toArray () {
let result = [];
this.traverse((node) => {
result.push(node.value);
});
return result;
}
toString () {
return this.toArray().toString();
}
}

View File

@ -0,0 +1,131 @@
const head = Symbol("head");
const tail = Symbol("tail");
class CircularDoublyLinkedListNode {
constructor (data) {
this.data = data;
this.next = null;
this.previous = null;
}
}
export class CircularDoublyLinkedList {
constructor () {
this[head] = null;
this[tail] = null;
}
add (data) {
const newNode = new CircularDoublyLinkedListNode(data);
// Special case: no items in the list
if (this[head] === null) {
this[head] = newNode;
newNode.next = newNode;
newNode.previous = newNode;
} else {
const tail = this[head].previous;
tail.next = newNode;
newNode.previous = tail;
newNode.next = this[head];
this[head].previous = newNode;
}
}
get (index) {
if ( ! Number(index) < 0) {
return undefined;
}
let current = this[head];
let i = 0;
do {
if (i === index) {
return current.data;
}
current = current.next;
i++;
} while ((current !== this[head]) && (i <= index));
return undefined;
}
remove (index) {
if ((this[head] === null) || (index < 0)) {
throw new RangeError(`Index ${index} does not exist in the list.`);
}
let current = this[head];
// Removing the first node
if (index === 0) {
if (current.next === this[head]) {
this[head] = null;
} else {
const tail = this[head].previous;
// Set the tail to point to the second item in the list
// and point the new item to the tail
tail.next = current.next;
current.next.previous = tail;
this[head] = tail.next;
}
return current.data;
}
let i = 0;
do {
current = current.next;
i++;
} while ((current !== this[head]) && (i < index));
if (current !== this[head]) {
// skip over the node to remove it
current.previous.next = current.next;
current.next.previous = current.previous;
return current.data;
}
throw new RangeError(`Index ${index} does not exist in the list.`);
}
*values () {
// list is empty
if (this[head] !== null) {
// only one node
if (this[head].next === this[head]) {
yield this[head].data;
} else {
let current = this[head];
do {
yield current.data;
current = current.next;
} while (current !== this[head]);
}
}
}
*circularValues () {
if (this[head] !== null) {
let current = this[head];
// infinite loop
while (true) {
yield current.data;
current = current.next;
}
}
}
[Symbol.iterator] () {
return this.values();
}
}

View File

@ -0,0 +1,117 @@
const head = Symbol("head");
const tail = Symbol("tail");
class DoublyLinkedListNode {
constructor (data) {
this.data = data;
this.next = null;
this.previous = null;
}
}
export class DoublyLinkedList {
constructor () {
this[head] = null;
this[tail] = null;
}
add (data) {
const newNode = new DoublyLinkedListNode(data);
// special case: no nodes
if (this[head] === null) {
this[head] = newNode;
} else {
// link the current tail and new tail
this[tail].next = newNode;
newNode.previous = this[tail];
}
// re-assign the tail
this[tail] = newNode;
}
get (index) {
if ( ! Number(index) < 0) {
return undefined;
}
let current = this[head];
let i = 0;
while ((current !== null) && (i < index)) {
current = current.next;
i++;
}
return current !== null
? current.data
: undefined;
}
remove (index) {
if ((this[head] === null) || (index < 0)) {
throw new RangeError(`Index ${index} does not exist in the list.`);
}
// special case: removing the first node
if (index === 0) {
const data = this[head].data;
this[head] = this[head].next;
// Only one node
if (this[head] === null) {
this[tail] = null;
} else {
this[head].previous = null;
}
return data;
}
let current = this[head];
let i = 0;
while ((current !== null) && (i < index)) {
current = current.next;
i++;
}
// If node was found remove it
if (current !== null) {
current.previous.next = current.next;
// last node
if (this[tail] === current) {
this[tail] = current.previous;
} else {
current.next.previous = current.previous;
}
return current.data;
}
throw new RangeError(`Index ${index} does not exist in the list.`);
}
*values () {
let current = this[head];
while (current !== null) {
yield current.data;
current = current.next;
}
}
*reverse () {
let current = this[tail];
while (current !== null) {
yield current.data;
current = current.previous;
}
}
[Symbol.iterator] () {
return this.values();
}
}

9
src/structures/index.js Normal file
View File

@ -0,0 +1,9 @@
import { CircularDoublyLinkedList } from "./circular-doubly-linked-list";
import { DoublyLinkedList } from "./doubly-linked-list";
import { LinkedList } from "./linked-list";
export {
CircularDoublyLinkedList,
DoublyLinkedList,
LinkedList,
};

View File

@ -0,0 +1,103 @@
const head = Symbol("head");
class LinkedListNode {
constructor (data) {
this.data = data;
this.next = null;
}
}
export class LinkedList {
constructor () {
this[head] = null;
}
add (data) {
const newNode = new LinkedListNode(data);
if (this[head] === null) {
this[head] = newNode;
} else {
let current = this[head];
// Go to the end of the list
while (current.next !== null) {
current = current.next;
}
// On the last node, add the new node
current.next = newNode;
}
}
get (index) {
if ( ! Number(index) < 0) {
return undefined;
}
let current = this[head];
let i = 0;
while ((current !== null) && (i < index)) {
current = current.next;
i++;
}
return current !== null
? current.data
: undefined;
}
remove (index) {
// Invalid index?
if ((this[head] === null) || (index < 0)) {
throw new RangeError(`Index ${index} does not exist in the list.`);
}
// Remove the first node
if (index === 0) {
const data = this[head].data;
// Replace the head with the next node
this[head] = this[head].next;
return data;
}
let current = this[head];
let previous = null;
let i = 0;
while ((current !== null) && (i < index)) {
// Save the current value
previous = current;
current = current.next;
i++;
}
// Remove the node if found
if (current !== null) {
// skip over the node to "remove" it
previous.next = current.next;
return current.data;
}
throw new RangeError(`Index ${index} does not exist in the list.`);
}
*values () {
let current = this[head];
while (current !== null) {
yield current.data;
current = current.next;
}
}
[Symbol.iterator] () {
return this.values();
}
}

83
src/usage.js Normal file
View File

@ -0,0 +1,83 @@
import {
CircularDoublyLinkedList,
DoublyLinkedList,
LinkedList,
} from "./structures/index.js";
function useLinkedList () {
console.log('-----------------------------------------------------------------------------------------------------');
console.log('Linked List');
console.log('-----------------------------------------------------------------------------------------------------');
const list = new LinkedList();
list.add("red");
list.add("orange");
list.add("yellow");
// get the second item in the list
console.log('Index 1 in list', list.get(1));
// print out all the items
for (const color of list) {
console.log(color);
}
// remove the second item in the list
console.log('Removing list item with index 1', list.remove(1));
// get the item now with index 1
console.log('New list item with index 1', list.get(1));
}
function useDoublyLinkedList () {
console.log('-----------------------------------------------------------------------------------------------------');
console.log('Doubly-Linked List');
console.log('-----------------------------------------------------------------------------------------------------');
const list = new DoublyLinkedList();
list.add("red");
list.add("orange");
list.add("yellow");
console.log('Index 1 in list',list.get(1));
for (const color of list.reverse()) {
console.log(color);
}
// remove the second item in the list
console.log('Removing list item with index 1', list.remove(1));
// get the item now with index 1
console.log('New list item with index 1', list.get(1));
}
function useCircularDoublyLinkedList () {
console.log('-----------------------------------------------------------------------------------------------------');
console.log('Circular Doubly-Linked List');
console.log('-----------------------------------------------------------------------------------------------------');
const list = new CircularDoublyLinkedList();
list.add("red");
list.add("orange");
list.add("yellow");
// get the second item in the list
console.log('Index 1 in list', list.get(1)); // "orange"
for (const color of list.values()) {
console.log(color);
}
// remove the second item in the list
console.log('Removing list item with index 1', list.remove(1));
// get the item now with index 1
console.log('New list item with index 1', list.get(1));
}
(() => {
useLinkedList();
console.log('');
useDoublyLinkedList();
console.log('');
useCircularDoublyLinkedList();
})();