First commit
This commit is contained in:
commit
57cfa8ad19
4
package.json
Normal file
4
package.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"type": "module",
|
||||
"main": "./src/usage.js"
|
||||
}
|
118
src/structures/binary-search-tree.js
Normal file
118
src/structures/binary-search-tree.js
Normal 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();
|
||||
}
|
||||
}
|
131
src/structures/circular-doubly-linked-list.js
Normal file
131
src/structures/circular-doubly-linked-list.js
Normal 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();
|
||||
}
|
||||
}
|
117
src/structures/doubly-linked-list.js
Normal file
117
src/structures/doubly-linked-list.js
Normal 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
9
src/structures/index.js
Normal 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,
|
||||
};
|
103
src/structures/linked-list.js
Normal file
103
src/structures/linked-list.js
Normal 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
83
src/usage.js
Normal 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();
|
||||
})();
|
Loading…
Reference in New Issue
Block a user