first commit

This commit is contained in:
s.golasch
2023-08-01 13:49:46 +02:00
commit 1fc239fd54
20238 changed files with 3112246 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
# Javascript Node CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-javascript/ for more details
#
version: 2
jobs:
build:
docker:
# specify the version you desire here
- image: circleci/node:7.10
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
# - image: circleci/mongo:3.4.4
working_directory: ~/projects/doubly-linked-list
steps:
- checkout
# Download and cache dependencies
- restore_cache:
keys:
- v1-dependencies-{{ checksum "package.json" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
- run: yarn install
- save_cache:
paths:
- node_modules
key: v1-dependencies-{{ checksum "package.json" }}
# run tests!
- run: yarn test

7
build/node_modules/dbly-linked-list/.eslintrc.json generated vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"extends": "eslint:recommended",
"env": {
"node": true,
"mocha": true
}
}

22
build/node_modules/dbly-linked-list/LICENSE-MIT generated vendored Normal file
View File

@@ -0,0 +1,22 @@
Doubly Linked List: Javascript implementation of doubly linked list data
structure
Copyright (C) 2015 Jason S. Jones
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

246
build/node_modules/dbly-linked-list/README.md generated vendored Normal file
View File

@@ -0,0 +1,246 @@
[![npm pkg][npm-image]][npm-url]
[![Build Status][circleci-image]][circleci-url]
[![dependency status][dm-image]][dm-url]
[![devDependency status][devdep-image]][devdep-url]
[![npm](https://img.shields.io/npm/l/dbly-linked-list.svg?style=flat-square)]()
# Doubly Linked List
## Description
This is a javascript implementation of a [doubly linked
list](http://en.wikipedia.org/wiki/Linked_list) data structure.
In simple terms, a doubly linked list consists of one or more 'nodes'. Each
node has a data field (which can contain any data--a primitive value or complex
object) and a pointer to the next 'node' and the previous 'node'. This
additional pointer to the previous node is what distinguishes a doubly linked
list from a singly linked list--a singly linked list only contains a pointer,
or reference, to the next node. The major advantage to having pointers to
both the next and previous node is that the list can be traversed in both
directions, as well as making operations that operate on the 'middle' of
the list a bit more efficient since each node has a reference the one
before it and the one after it. The idea of having a links to the
previous and next nodes is where this data structure got its descriptive
name.
This implementation provides basic functionality of adding nodes to the front
or back of the list, as well as the ability to insert a node at a given
position in the list. It also provides the ability to remove nodes at the
front or back of the list, or from any given position.
The find, or search, functionality provides the ability to find the first node
containing specified data. It also provides the ability to find a node given a
specific position, or index, in the list.
### Advantages
- List will grow dynamically with each node added; no requirement to
'resize' list when it reaches a certain size, saving considerable overhead
in 'house-keeping' operations.
- Flexibility to add or remove nodes at the beginning or end of the list in
O(1) time. This is a significant improvement over its
[singly linked list](https://github.com/jasonsjones/singly-linked-list)
counterpart.
### Disadvantages
- All 'find' operations take O(n) time to iterate over the list to find the
requested node. This is the case for both the singly and doubly linked
list.
*For specific examples and documentation, see the below sections*
### Motivation:
The main purpose of this project is revisit the basics, and focus on the
development process.
*I wholehearedly acknowledge that the basic data structure space is populated
with well-written code and efficient implementations, and one could easily grab
one of those libraries and integrate it in their project. However, the main
difference between those libraries/implementations and this one is that this is
the best implementation I have ever written. My hope is that someone else will
find this useful, but understand, this code is not the goal; this will simply
be a useful bi-product of the journey. The underlying motivation is to
understand and, more importantly, learn from the process to get to the desired
end-state—for me it is all about the joy of the journey.*
#### Environment:
Although this implementation is designed to be used with
[Node.js](http://www.nodejs.org), it could be used in other contexts with minor
modifications. This implementation does not have any external dependencies that
would preclude it from being used in the browser--just include it with a
`<script>` tag and it should be good to go. _Disclaimer: I have not tested
this implementation in any other context/environment; only tested with node.js_
----
## Basic Usage
Install with npm :
```sh
npm install dbly-linked-list --save
```
Install with yarn :
```sh
yarn add dbly-linked-list
```
Basic usage example below. _Note: it does not cover all the available
methods, rather just highlights the main functionality to get up and running
with this data structure. For a description of all the methods, see the
API section._
```javascript
var LinkedList = require('dbly-linked-list');
var list = new LinkedList();
list.isEmpty();
// --> true
list.insert('data item 1');
list.insert('data item 2');
list.insert('data item 3');
list.insert('data item 4');
// list contains:
// 'data item 1', ... ,'data item 4'
list.isEmpty();
// --> false
list.getSize();
// --> 4
list.insertFirst('data item 0');
// list contains:
// 'data item 0', ... ,'data item 4'
list.getHeadNode().getData();
// --> 'data item 0'
list.remove();
// --> removes 'data item 4'
list.removeFirst();
// --> removes 'data item 0'
list.getHeadNode().getData();
// --> 'data item 1'
list.clear();
list.isEmpty();
// --> true
```
## API
**Available methods for a doubly-linked-list instance:**
* ### getHeadNode()
Returns the first node in the list
* ### getTailNode()
Returns the last node in the list
* ### isEmpty()
Determines if the list is empty or not. Returns true if is empty, false
otherwise.
* ### getSize()
Returns the size of the list, or number of nodes
* ### clear()
Clears the list of all nodes/data
* ### insert(data)
Inserts a node (with the provided `data`) to the end of the list
* ### insertFirst(data)
Inserts a node (with the provided `data`) to the front of the list
* ### insertAt(index, data)
Inserts a node (with the provided `data`) at the `index` indicated.
* ### insertBefore(nodeData, dataToInsert)
Inserts a node (with the `dataToInsert`) _before_ the first node containing
`nodeData`
* ### insertAfter(nodeData, dataToInsert)
Inserts a node (with the `dataToInsert`) _after_ the first node containing
`nodeData`
* ### remove()
Removes the tail node from the list
* ### removeFirst()
Removes the head node from the list
* ### removeAt(index)
Removes the node at the `index` provided
* ### removeNode(nodeData)
Removes the first node that contains the `nodeData` provided
* ### indexOf(nodeData)
Returns the index of the first node containing the provided `nodeData`. If
a node cannot be found containing the provided data, -1 is returned.
* ### contains(nodeData)
Determines whether or not the list contains the provided `nodeData`
* ### find(nodeData)
Returns the fist node containing the provided `nodeData`. If a node
cannot be found containing the provided data, -1 is returned.
* ### findAt(index)
Returns the node at the location provided by `index`
* ### forEach(fn, reverse)
Utility function to iterate over the list and call the `fn` provided
on each node, or element, of the list. The optional `reverse` parameter
is a boolean used to specify the direction of iteration
(true: tail -> head, false: head -> tail, default: false)
* ### toArray()
Returns an array of all the data contained in the list
* ### printList()
Prints to the console the data property of each node in the list
* ### interruptEnumeration()
Interrupts and breaks out of the loop induced by `forEach()`, making partial iterations possible. An iteration cannot be resumed after having been interrupted.
**Available methods for an individual node instance:**
* ### getData()
Returns the data of the the node
* ### hasNext()
Returns whether or not the node has a pointer to the next node
* ### hasPrev()
Returns whether or not the node has a pointer to the previous node
* ### toString()
Returns a string represenation of the node. If the data is an object,
it returns the JSON.stringify version of the object. Otherwise, it
simply returns the data
----
## License
MIT &copy; Jason Jones
[npm-image]: https://img.shields.io/npm/v/dbly-linked-list.svg?style=flat-square
[npm-url]: http://npmjs.org/package/dbly-linked-list
[circleci-image]: https://img.shields.io/circleci/project/github/jasonsjones/doubly-linked-list.svg?style=flat-square
[circleci-url]: https://circleci.com/gh/jasonsjones/doubly-linked-list
[dm-image]: https://img.shields.io/david/jasonsjones/doubly-linked-list.svg?style=flat-square
[dm-url]: https://david-dm.org/jasonsjones/doubly-linked-list
[devdep-image]: https://img.shields.io/david/dev/jasonsjones/doubly-linked-list.svg?style=flat-square
[devdep-url]: https://david-dm.org/jasonsjones/doubly-linked-list?type=dev

474
build/node_modules/dbly-linked-list/index.js generated vendored Normal file
View File

@@ -0,0 +1,474 @@
/**
* @fileOverview Implementation of a doubly linked-list data structure
* @author Jason S. Jones
* @license MIT
*/
(function() {
'use strict';
var isEqual = require('lodash.isequal');
var Node = require('./lib/list-node');
var Iterator = require('./lib/iterator');
/**************************************************
* Doubly linked list class
*
* Implementation of a doubly linked list data structure. This
* implementation provides the general functionality of adding nodes to
* the front or back of the list, as well as removing node from the front
* or back. This functionality enables this implemention to be the
* underlying data structure for the more specific stack or queue data
* structure.
*
***************************************************/
/**
* Creates a LinkedList instance. Each instance has a head node, a tail
* node and a size, which represents the number of nodes in the list.
*
* @constructor
*/
function DoublyLinkedList() {
this.head = null;
this.tail = null;
this.size = 0;
// add iterator as a property of this list to share the same
// iterator instance with all other methods that may require
// its use. Note: be sure to call this.iterator.reset() to
// reset this iterator to point the head of the list.
this.iterator = new Iterator(this);
}
/* Functions attached to the Linked-list prototype. All linked-list
* instances will share these methods, meaning there will NOT be copies
* made for each instance. This will be a huge memory savings since there
* may be several different linked lists.
*/
DoublyLinkedList.prototype = {
/**
* Creates a new Node object with 'data' assigned to the node's data
* property
*
* @param {object|string|number} data The data to initialize with the
* node
* @returns {object} Node object intialized with 'data'
*/
createNewNode: function(data) {
return new Node(data);
},
/**
* Returns the first node in the list, commonly referred to as the
* 'head' node
*
* @returns {object} the head node of the list
*/
getHeadNode: function() {
return this.head;
},
/**
* Returns the last node in the list, commonly referred to as the
* 'tail'node
*
* @returns {object} the tail node of the list
*/
getTailNode: function() {
return this.tail;
},
/**
* Determines if the list is empty
*
* @returns {boolean} true if the list is empty, false otherwise
*/
isEmpty: function() {
return (this.size === 0);
},
/**
* Returns the size of the list, or number of nodes
*
* @returns {number} the number of nodes in the list
*/
getSize: function() {
return this.size;
},
/**
* Clears the list of all nodes/data
*/
clear: function () {
while (!this.isEmpty()) {
this.remove();
}
},
//################## INSERT methods ####################
/**
* Inserts a node with the provided data to the end of the list
*
* @param {object|string|number} data The data to initialize with the
* node
* @returns {boolean} true if insert operation was successful
*/
insert: function(data) {
var newNode = this.createNewNode(data);
if (this.isEmpty()) {
this.head = this.tail = newNode;
} else {
this.tail.next = newNode;
newNode.prev = this.tail;
this.tail = newNode;
}
this.size += 1;
return true;
},
/**
* Inserts a node with the provided data to the front of the list
*
* @param {object|string|number} data The data to initialize with the
* node
* @returns {boolean} true if insert operation was successful
*/
insertFirst: function(data) {
if (this.isEmpty()) {
this.insert(data);
} else {
var newNode = this.createNewNode(data);
newNode.next = this.head;
this.head.prev = newNode;
this.head = newNode;
this.size += 1;
}
return true;
},
/**
* Inserts a node with the provided data at the index indicated.
*
* @param {number} index The index in the list to insert the new node
* @param {object|string|number} data The data to initialize with the node
*/
insertAt: function (index, data) {
var current = this.getHeadNode(),
newNode = this.createNewNode(data),
position = 0;
// check for index out-of-bounds
if (index < 0 || index > this.getSize() - 1) {
return false;
}
// if index is 0, we just need to insert the first node
if (index === 0) {
this.insertFirst(data);
return true;
}
while (position < index) {
current = current.next;
position += 1;
}
current.prev.next = newNode;
newNode.prev = current.prev;
current.prev = newNode;
newNode.next = current;
this.size += 1;
return true;
},
/**
* Inserts a node before the first node containing the provided data
*
* @param {object|string|number} nodeData The data of the node to
* find to insert the new node before
* @param {object|string|number} dataToInsert The data to initialize with the node
* @returns {boolean} true if insert operation was successful
*/
insertBefore: function (nodeData, dataToInsert) {
var index = this.indexOf(nodeData);
return this.insertAt(index, dataToInsert);
},
/**
* Inserts a node after the first node containing the provided data
*
* @param {object|string|number} nodeData The data of the node to
* find to insert the new node after
* @param {object|string|number} dataToInsert The data to initialize with the node
* @returns {boolean} true if insert operation was successful
*/
insertAfter: function (nodeData, dataToInsert) {
var index = this.indexOf(nodeData);
var size = this.getSize();
// check if we want to insert new node after the tail node
if (index + 1 === size) {
// if so, call insert, which will append to the end by default
return this.insert(dataToInsert);
} else {
// otherwise, increment the index and insert there
return this.insertAt(index + 1, dataToInsert);
}
},
//################## REMOVE methods ####################
/**
* Removes the tail node from the list
*
* There is a significant performance improvement with the operation
* over its singly linked list counterpart. The mere fact of having
* a reference to the previous node improves this operation from O(n)
* (in the case of singly linked list) to O(1).
*
* @returns the node that was removed
*/
remove: function() {
if (this.isEmpty()) {
return null;
}
// get handle for the tail node
var nodeToRemove = this.getTailNode();
// if there is only one node in the list, set head and tail
// properties to null
if (this.getSize() === 1) {
this.head = null;
this.tail = null;
// more than one node in the list
} else {
this.tail = this.getTailNode().prev;
this.tail.next = null;
}
this.size -= 1;
return nodeToRemove;
},
/**
* Removes the head node from the list
*
* @returns the node that was removed
*/
removeFirst: function() {
if (this.isEmpty()) {
return null;
}
var nodeToRemove;
if (this.getSize() === 1) {
nodeToRemove = this.remove();
} else {
nodeToRemove = this.getHeadNode();
this.head = this.head.next;
this.head.prev = null;
this.size -= 1;
}
return nodeToRemove;
},
/**
* Removes the node at the index provided
*
* @param {number} index The index of the node to remove
* @returns the node that was removed
*/
removeAt: function (index) {
var nodeToRemove = this.findAt(index);
// check for index out-of-bounds
if (index < 0 || index > this.getSize() - 1) {
return null;
}
// if index is 0, we just need to remove the first node
if (index === 0) {
return this.removeFirst();
}
// if index is size-1, we just need to remove the last node,
// which remove() does by default
if (index === this.getSize() - 1) {
return this.remove();
}
nodeToRemove.prev.next = nodeToRemove.next;
nodeToRemove.next.prev = nodeToRemove.prev;
nodeToRemove.next = nodeToRemove.prev = null;
this.size -= 1;
return nodeToRemove;
},
/**
* Removes the first node that contains the data provided
*
* @param {object|string|number} nodeData The data of the node to remove
* @returns the node that was removed
*/
removeNode: function (nodeData) {
var index = this.indexOf(nodeData);
return this.removeAt(index);
},
//################## FIND methods ####################
/**
* Returns the index of the first node containing the provided data. If
* a node cannot be found containing the provided data, -1 is returned.
*
* @param {object|string|number} nodeData The data of the node to find
* @returns the index of the node if found, -1 otherwise
*/
indexOf: function(nodeData) {
this.iterator.reset();
var current;
var index = 0;
// iterate over the list (keeping track of the index value) until
// we find the node containg the nodeData we are looking for
while (this.iterator.hasNext()) {
current = this.iterator.next();
if (isEqual(current.getData(), nodeData)) {
return index;
}
index += 1;
}
// only get here if we didn't find a node containing the nodeData
return -1;
},
/**
* Returns the fist node containing the provided data. If a node
* cannot be found containing the provided data, -1 is returned.
*
* @param {object|string|number} nodeData The data of the node to find
* @returns the node if found, -1 otherwise
*/
find: function(nodeData) {
// start at the head of the list
this.iterator.reset();
var current;
// iterate over the list until we find the node containing the data
// we are looking for
while (this.iterator.hasNext()) {
current = this.iterator.next();
if (isEqual(current.getData(), nodeData)) {
return current;
}
}
// only get here if we didn't find a node containing the nodeData
return -1;
},
/**
* Returns the node at the location provided by index
*
* @param {number} index The index of the node to return
* @returns the node located at the index provided.
*/
findAt: function(index) {
// if idx is out of bounds or fn called on empty list, return -1
if (this.isEmpty() || index > this.getSize() - 1) {
return -1;
}
// else, loop through the list and return the node in the
// position provided by idx. Assume zero-based positions.
var node = this.getHeadNode();
var position = 0;
while (position < index) {
node = node.next;
position += 1;
}
return node;
},
/**
* Determines whether or not the list contains the provided nodeData
*
* @param {object|string|number} nodeData The data to check if the list
* contains
* @returns the true if the list contains nodeData, false otherwise
*/
contains: function (nodeData) {
if (this.indexOf(nodeData) > -1) {
return true;
} else {
return false;
}
},
//################## UTILITY methods ####################
/**
* Utility function to iterate over the list and call the fn provided
* on each node, or element, of the list
*
* @param {object} fn The function to call on each node of the list
* @param {bool} reverse Use or not reverse iteration (tail to head), default to false
*/
forEach: function(fn, reverse) {
reverse = reverse || false;
if (reverse) {
this.iterator.reset_reverse();
this.iterator.each_reverse(fn)
} else {
this.iterator.reset();
this.iterator.each(fn);
}
},
/**
* Returns an array of all the data contained in the list
*
* @returns {array} the array of all the data from the list
*/
toArray: function() {
var listArray = [];
this.forEach(function(node) {
listArray.push(node.getData());
});
return listArray;
},
/**
* Interrupts iteration over the list
*/
interruptEnumeration: function() {
this.iterator.interrupt();
}
};
module.exports = DoublyLinkedList;
}());

195
build/node_modules/dbly-linked-list/lib/iterator.js generated vendored Normal file
View File

@@ -0,0 +1,195 @@
/**
* @fileOverview Implementation of an iterator for a linked list
* data structure
* @author Jason S. Jones
* @license MIT
*/
(function () {
'use strict';
/**************************************************
* Iterator class
*
* Represents an instantiation of an iterator to be used
* within a linked list. The iterator will provide the ability
* to iterate over all nodes in a list by keeping track of the
* postition of a 'currentNode'. This 'currentNode' pointer
* will keep state until a reset() operation is called at which
* time it will reset to point the head of the list.
*
* Even though this iterator class is inextricably linked
* (no pun intended) to a linked list instatiation, it was removed
* from within the linked list code to adhere to the best practice
* of separation of concerns.
*
***************************************************/
/**
* Creates an iterator instance to iterate over the linked list provided.
*
* @constructor
* @param {object} theList the linked list to iterate over
*/
function Iterator(theList) {
this.list = theList || null;
this.stopIterationFlag = false;
// a pointer the current node in the list that will be returned.
// initially this will be null since the 'list' will be empty
this.currentNode = null;
}
/* Functions attached to the Iterator prototype. All iterator instances
* will share these methods, meaning there will NOT be copies made for each
* instance.
*/
Iterator.prototype = {
/**
* Returns the next node in the iteration.
*
* @returns {object} the next node in the iteration.
*/
next: function() {
var current = this.currentNode;
// a check to prevent error if randomly calling next() when
// iterator is at the end of the list, meaining the currentNode
// will be pointing to null.
//
// When this function is called, it will return the node currently
// assigned to this.currentNode and move the pointer to the next
// node in the list (if it exists)
if (this.currentNode !== null) {
this.currentNode = this.currentNode.next;
}
return current;
},
/**
* Determines if the iterator has a node to return
*
* @returns true if the iterator has a node to return, false otherwise
*/
hasNext: function() {
return this.currentNode !== null;
},
/**
* Resets the iterator to the beginning of the list.
*/
reset: function() {
this.currentNode = this.list.getHeadNode();
},
/**
* Returns the first node in the list and moves the iterator to
* point to the second node.
*
* @returns the first node in the list
*/
first: function() {
this.reset();
return this.next();
},
/**
* Sets the list to iterate over
*
* @param {object} theList the linked list to iterate over
*/
setList: function(theList) {
this.list = theList;
this.reset();
},
/**
* Iterates over all nodes in the list and calls the provided callback
* function with each node as an argument.
* Iteration will break if interrupt() is called
*
* @param {function} callback the callback function to be called with
* each node of the list as an arg
*/
each: function(callback) {
this.reset();
var el;
while (this.hasNext() && !this.stopIterationFlag) {
el = this.next();
callback(el);
}
this.stopIterationFlag = false;
},
/*
* ### REVERSE ITERATION (TAIL -> HEAD) ###
*/
/**
* Returns the first node in the list and moves the iterator to
* point to the second node.
*
* @returns the first node in the list
*/
last: function() {
this.reset_reverse();
return this.next_reverse();
},
/**
* Resets the iterator to the tail of the list.
*/
reset_reverse: function() {
this.currentNode = this.list.getTailNode();
},
/**
* Returns the next node in the iteration, when iterating from tail to head
*
* @returns {object} the next node in the iteration.
*/
next_reverse: function() {
var current = this.currentNode;
if (this.currentNode !== null) {
this.currentNode = this.currentNode.prev;
}
return current;
},
/**
* Iterates over all nodes in the list and calls the provided callback
* function with each node as an argument,
* starting from the tail and going towards the head.
* The iteration will break if interrupt() is called.
*
* @param {function} callback the callback function to be called within
* each node as an arg
*/
each_reverse: function(callback) {
this.reset_reverse();
var el;
while (this.hasNext() && !this.stopIterationFlag) {
el = this.next_reverse();
callback(el);
}
this.stopIterationFlag = false;
},
/*
* ### INTERRUPT ITERATION ###
*/
/**
* Raises interrupt flag (that will stop each() or each_reverse())
*/
interrupt: function() {
this.stopIterationFlag = true;
}
};
module.exports = Iterator;
}());

83
build/node_modules/dbly-linked-list/lib/list-node.js generated vendored Normal file
View File

@@ -0,0 +1,83 @@
(function () {
'use strict';
/**************************************************
* Linked list node class
*
* Internal private class to represent a node within
* a linked list. Each node has a 'data' property and
* a pointer the previous node and the next node in the list.
*
* Since the 'Node' function is not assigned to
* module.exports it is not visible outside of this
* file, therefore, it is private to the LinkedList
* class.
*
***************************************************/
/**
* Creates a node object with a data property and pointer
* to the next node
*
* @constructor
* @param {object|number|string} data The data to initialize with the node
*/
function Node(data) {
this.data = data || null;
this.next = null;
this.prev = null;
}
/* Functions attached to the Node prototype. All node instances will
* share these methods, meaning there will NOT be copies made for each
* instance. This will be a huge memory savings since there will likely
* be a large number of individual nodes.
*/
Node.prototype = {
/**
* Returns whether or not the node has a pointer to the next node
*
* @returns {boolean} true if there is a next node; false otherwise
*/
hasNext: function() {
return (this.next !== null);
},
/**
* Returns whether or not the node has a pointer to the previous node
*
* @returns {boolean} true if there is a previous node; false otherwise
*/
hasPrev: function() {
return (this.prev !== null);
},
/**
* Returns the data of the the node
*
* @returns {object|string|number} the data of the node
*/
getData: function() {
return this.data;
},
/**
* Returns a string represenation of the node. If the data is an
* object, it returns the JSON.stringify version of the object.
* Otherwise, it simply returns the data
*
* @return {string} the string represenation of the node data
*/
toString: function() {
if (typeof this.data === 'object') {
return JSON.stringify(this.data);
} else {
return String(this.data);
}
}
};
module.exports = Node;
}());

64
build/node_modules/dbly-linked-list/package.json generated vendored Normal file
View File

@@ -0,0 +1,64 @@
{
"_from": "dbly-linked-list@0.2.0",
"_id": "dbly-linked-list@0.2.0",
"_inBundle": false,
"_integrity": "sha512-Ool7y15f6JRDs0YKx7Dh9uiTb1jS1SZLNdT3Y2q16DlaEghXbMsmODS/XittjR2xztt1gJUpz7jVxpqAPF8VGg==",
"_location": "/dbly-linked-list",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "dbly-linked-list@0.2.0",
"name": "dbly-linked-list",
"escapedName": "dbly-linked-list",
"rawSpec": "0.2.0",
"saveSpec": null,
"fetchSpec": "0.2.0"
},
"_requiredBy": [
"/queue-fifo"
],
"_resolved": "https://registry.npmjs.org/dbly-linked-list/-/dbly-linked-list-0.2.0.tgz",
"_shasum": "d30f5225dc1ce72220d7931489b0c5703b1aa8aa",
"_spec": "dbly-linked-list@0.2.0",
"_where": "/Users/asciidisco/Desktop/asciidisco.com/build/node_modules/queue-fifo",
"author": {
"name": "Jason Jones"
},
"bugs": {
"url": "https://github.com/jasonsjones/doubly-linked-list/issues"
},
"bundleDependencies": false,
"dependencies": {
"lodash.isequal": "^4.5.0"
},
"deprecated": false,
"description": "Javascript implementation of a doubly linked-list data structure",
"devDependencies": {
"eslint": "^4.12.0",
"mocha": "^4.0.1",
"nyc": "^11.3.0",
"should": "^13.1.3"
},
"directories": {
"test": "test"
},
"homepage": "https://github.com/jasonsjones/doubly-linked-list#readme",
"keywords": [
"doubly linked-list",
"linked list",
"data structure"
],
"license": "MIT",
"main": "index.js",
"name": "dbly-linked-list",
"repository": {
"type": "git",
"url": "git+https://github.com/jasonsjones/doubly-linked-list.git"
},
"scripts": {
"lint": "eslint index.js lib/*.js test/*.js",
"test": "nyc mocha"
},
"version": "0.2.0"
}

400
build/node_modules/dbly-linked-list/test/list.spec.js generated vendored Normal file
View File

@@ -0,0 +1,400 @@
/* globals describe it beforeEach afterEach */
var should = require('should');
var LinkedList = require('../');
describe('Linked List', function() {
var list = null;
// Utility function to populate the list with dummy data.
// The number of nodes added will be specified by the 'numNodes'
// parameter.
var populateList = function (aList, numNodes) {
for (var i = 0; i < numNodes; i++) {
aList.insert('test item ' + (i + 1));
}
};
beforeEach(function() {
list = new LinkedList();
});
afterEach(function() {
list = null;
});
it('should have a working test environment', function() {
true.should.equal(true);
});
it('should initially contain zero items', function() {
list.isEmpty().should.equal(true);
list.getSize().should.equal(0);
});
it('should clear the list and set head and tail to null', function () {
populateList(list, 10);
list.getSize().should.equal(10);
list.clear();
list.getSize().should.equal(0);
should.not.exist(list.getHeadNode());
should.not.exist(list.getTailNode());
});
it('should return an array of all the data in the list', function() {
list.insert({
id: 1,
name: 'test item 1'
});
list.insert({
id: 2,
name: 'test item 2'
});
list.insert({
id: 3,
name: 'test item 3'
});
var listArray = list.toArray();
listArray.should.be.an.Array;
listArray.should.have.length(3);
});
describe('iterator functionality', function() {
it('should exist when a list is instantiated', function() {
list.iterator.should.be.ok;
});
it('should have iterator currentNode be null when first instantiated',
function() {
should.not.exist(list.iterator.next());
});
it('should return the tail node when iterator.last() is called', function() {
populateList(list, 10);
var last = list.iterator.last();
last.should.equal(list.getTailNode());
})
it('should return the head node when iterator.first() is called',
function() {
populateList(list, 10);
var first = list.iterator.first();
first.should.equal(list.getHeadNode());
});
it('should return correct boolean value for hasNext()', function() {
populateList(list, 3);
list.iterator.reset();
list.iterator.hasNext().should.equal(true);
// get first element
list.iterator.next();
list.iterator.hasNext().should.equal(true);
// get second element
list.iterator.next();
list.iterator.hasNext().should.equal(true);
// get third element
list.iterator.next();
// should be no more element in list
list.iterator.hasNext().should.equal(false);
});
it('should return correct boolean value for hasNext() in reverse order', function() {
populateList(list, 3);
list.iterator.reset_reverse();
list.iterator.hasNext().should.equal(true);
list.iterator.next_reverse();
list.iterator.hasNext().should.equal(true);
list.iterator.next_reverse();
list.iterator.hasNext().should.equal(true);
list.iterator.next_reverse();
list.iterator.hasNext().should.equal(false);
});
it('should go through elements from head to tail when calling iterator.each()', function() {
populateList(list, 3);
var array = [];
//expected result
var expectedArray = ["test item 1", "test item 2", "test item 3"];
var dummyCallback = function(node) {
array.push(node.getData());
}
list.iterator.reset()
list.iterator.each(dummyCallback);
array.should.be.eql(expectedArray);
});
it('should go through elements from tail to head when calling iterator.each_reverse()', function() {
populateList(list, 3);
var array = [];
var expectedArray = ["test item 3", "test item 2", "test item 1"];
var dummyCallback = function(node) {
array.push(node.getData());
};
list.iterator.reset_reverse();
list.iterator.each_reverse(dummyCallback);
array.should.be.eql(expectedArray);
});
it('should stop in the middle of iteration if iterator.interrupt() is called', function() {
populateList(list, 5);
var count = 0;
var dummyCallback = function() {
count += 1;
if (count === 3) {
list.iterator.interrupt();
}
};
// head to tail
list.iterator.reset();
list.iterator.each(dummyCallback);
count.should.be.equal(3);
// tail to head
count = 0;
list.iterator.reset_reverse();
list.iterator.each_reverse(dummyCallback);
count.should.be.equal(3);
})
});
describe('insert functionality', function() {
it('should set the head node equal to the tail node when first item ' +
'is inserted', function() {
list.insert('test item 1');
list.getHeadNode().should.equal(list.getTailNode());
list.getSize().should.equal(1);
});
it('should insert items to the back of the list', function() {
populateList(list, 5);
list.isEmpty().should.equal(false);
list.getSize().should.equal(5);
var tail = list.getTailNode();
tail.getData().should.equal('test item 5');
});
it('should insert items to the front of the list', function() {
list.insert('test item 1');
list.insert('test item 2');
list.insertFirst('new item 0');
list.getHeadNode().data.should.equal('new item 0');
list.getHeadNode().hasPrev().should.equal(false);
list.getSize().should.equal(3);
});
it('should insert item at a particular index', function() {
populateList(list, 3);
list.insert('test item 5');
list.getSize().should.equal(4);
var success = list.insertAt(3, 'test item 4');
success.should.equal(true);
list.getSize().should.equal(5);
var node = list.findAt(3);
node.getData().should.equal('test item 4');
});
it('should insert new head node when inserting at index 0', function() {
populateList(list, 3);
list.getSize().should.equal(3);
var success = list.insertAt(0, 'test item 0');
success.should.equal(true);
list.getSize().should.equal(4);
var node = list.getHeadNode();
node.getData().should.equal('test item 0');
});
it('should return false when trying to insert at index out of bounds', function() {
populateList(list, 3);
var success = list.insertAt(5, 'test item 4');
success.should.equal(false);
});
it('should insert item before a particular node', function () {
populateList(list, 3);
list.insert('test item 5');
list.getSize().should.equal(4);
list.insertBefore('test item 5', 'test item 4');
list.getSize().should.equal(5);
var node = list.findAt(3);
node.getData().should.equal('test item 4');
// test for inserting before the head node
list.insertBefore('test item 1', 'test item 0');
list.getSize().should.equal(6);
node = list.getHeadNode();
node.getData().should.equal('test item 0');
});
it('should insert item after a particular node', function () {
populateList(list, 3);
list.insert('test item 5');
list.getSize().should.equal(4);
list.insertAfter('test item 3', 'test item 4');
list.getSize().should.equal(5);
var node = list.findAt(3);
node.getData().should.equal('test item 4');
// test for inserting after the tail node
list.insertAfter('test item 5', 'test item 6');
list.getSize().should.equal(6);
node = list.getTailNode();
node.getData().should.equal('test item 6');
});
});
describe('remove functionality', function() {
it('should return null if remove is called on an empty list',
function() {
var node = list.remove();
should.not.exist(node);
});
it('should remove items from the back of the list', function() {
populateList(list, 3);
list.isEmpty().should.equal(false);
list.getSize().should.equal(3);
var node = list.remove();
node.getData().should.equal('test item 3');
list.getSize().should.equal(2);
var last = list.getTailNode();
last.getData().should.equal('test item 2');
last.hasNext().should.equal(false);
});
it('should return null if removeFirst is called on an empty list',
function() {
var node = list.removeFirst();
should.not.exist(node);
});
it('should remove items from the front of the list', function() {
populateList(list, 3);
list.isEmpty().should.equal(false);
list.getSize().should.equal(3);
var node = list.removeFirst();
node.getData().should.equal('test item 1');
list.getSize().should.equal(2);
var first = list.getHeadNode();
first.getData().should.equal('test item 2');
first.hasPrev().should.equal(false);
});
it('should remove item from the front of a list with only one node', function () {
list.insert('test item 1');
var node = list.removeFirst();
node.getData().should.equal('test item 1');
list.getSize().should.equal(0);
});
it('should remove item at a particulary index', function() {
populateList(list, 4);
list.getSize().should.equal(4);
var node = list.removeAt(1);
node.getData().should.equal('test item 2');
list.getSize().should.equal(3);
});
it('should remove a node with given data', function() {
populateList(list, 4);
list.getSize().should.equal(4);
var node = list.removeNode('test item 3');
node.getData().should.equal('test item 3');
list.getSize().should.equal(3);
});
});
describe('find functionality', function() {
it('should find a node with the data provided', function() {
populateList(list, 3);
var node = list.find('test item 2');
node.should.be.an.Object;
node.getData().should.equal('test item 2');
});
it('should find a node with a complex obj', function () {
list.insert({key: 'key', value: 'value123'});
var node = list.find({key: 'key', value: 'value123'});
node.getData().should.be.an.Object;
node.getData().should.have.properties(['key', 'value']);
});
it('should return -1 if a node does not exist with the given data',
function() {
populateList(list, 3);
var node = list.find('not found...');
node.should.not.be.an.Object;
node.should.equal(-1);
});
it('should return -1 if find() is called on an empty list',
function() {
var node = list.find('not found...');
node.should.not.be.an.Object;
node.should.equal(-1);
});
it('should return the index of node containing the provided data',
function() {
populateList(list, 3);
var index = list.indexOf('test item 1');
index.should.equal(0);
index = list.indexOf('test item 2');
index.should.equal(1);
index = list.indexOf('test item 3');
index.should.equal(2);
});
it('should return -1 for the index of node with the given data if the' +
'node does not exist',
function() {
populateList(list, 3);
var index = list.indexOf('not found');
index.should.equal(-1);
});
it('should return node at given index', function() {
list.insert('test item 1');
list.insert('test item 2');
var node = list.findAt(0);
node.should.be.an.Object;
node.getData().should.equal('test item 1');
node = list.findAt(1);
node.should.be.an.Object;
node.getData().should.equal('test item 2');
});
it('should return -1 when findAt() is called w/ index > than list size',
function() {
var node = list.findAt(0);
node.should.not.be.an.Object;
node.should.equal(-1);
});
it('should return true if list contains specified data,' +
'false otherwise',
function () {
populateList(list, 3);
var result = list.contains('test item 2');
result.should.equal(true);
result = list.contains('not found');
result.should.equal(false);
});
});
});

72
build/node_modules/dbly-linked-list/test/node.spec.js generated vendored Normal file
View File

@@ -0,0 +1,72 @@
/* globals describe it beforeEach before afterEach */
var should = require('should');
var LinkedList = require('../');
describe('List Node', function() {
var list = null;
before(function() {
list = new LinkedList();
});
it('should have a working test environment', function() {
true.should.equal(true);
});
it('should exist when instantiated', function() {
var node = list.createNewNode('test data');
should.exist(node);
node.should.be.ok;
});
it('should return the correct (primitive) data', function() {
var node = list.createNewNode('test data');
var data = node.getData();
data.should.not.be.an.Object;
data.should.be.a.String;
data.should.equal('test data');
node.data = 42;
data = node.getData();
data.should.not.be.an.Object;
data.should.be.a.Number;
data.should.equal(42);
});
it('should return the correct (object) data', function() {
var node = list.createNewNode({
name: 'test item',
number: 1
});
var data = node.getData();
data.should.be.an.Object;
node.toString().should.equal('{"name":"test item","number":1}');
});
it('should return whether or not it has a next node', function() {
var firstNode = list.createNewNode('first node');
var secondNode = list.createNewNode('second node');
firstNode.next = secondNode;
firstNode.hasNext().should.equal(true);
});
it('should return whether or not it has a previous node', function() {
var firstNode = list.createNewNode('first node');
var secondNode = list.createNewNode('second node');
secondNode.prev = firstNode;
secondNode.hasPrev().should.equal(true);
});
it('should return a proper string representation of its data', function() {
var node = list.createNewNode({name: 'test item', number: 1});
node.toString().should.equal('{"name":"test item","number":1}');
node.data = 'string data';
node.toString().should.equal('string data');
node.data = 42;
node.toString().should.equal('42');
});
});

1833
build/node_modules/dbly-linked-list/yarn.lock generated vendored Normal file

File diff suppressed because it is too large Load Diff