Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: LinkedList is in fact a Deque #222

Draft
wants to merge 53 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
64faf18
feat: add ESM support for default exports
Jan 2, 2024
7f1890a
fix: fix set ops exports
Jan 2, 2024
0dcfb1d
fix: add missing export
Jan 2, 2024
90213ff
fix: add missing module field in package.json
Jan 3, 2024
2e442de
test: add initial ESM and CommonJS import infrastructure
Jan 8, 2024
3ca8235
test: make named require test works
Jan 8, 2024
6e2a9f6
Merge branch 'master' of https://github.com/Yomguithereal/mnemonist i…
Jan 8, 2024
9103a18
build(ci): disable some eslint rules in import test files
Jan 8, 2024
7fc278e
test: make CommonJS import works
Jan 8, 2024
78a942c
refactor: code cleanup
Jan 8, 2024
815e0bb
test: add module import tests to CI
Jan 8, 2024
837ae22
refactor: code cleanups
Jan 9, 2024
76179e8
build(ci): remove non LTS node release
Jan 9, 2024
fbdaaa2
refactor: cleanup exports in package.json by using wildcards
Jan 9, 2024
e69fbe4
fix: add missing constructor to InverseMap type
Jan 9, 2024
d4ecdb9
test: improve a bit Heap coverage
Jan 9, 2024
4f8d31d
refactor: import cleanup
Jan 9, 2024
2888ac3
Merge branch 'master' of https://github.com/Yomguithereal/mnemonist i…
Jan 10, 2024
d3e9f6b
fix: use named CJS exports to improve tree shaking
Jan 10, 2024
c178c41
refactor: consistent coding style
Jan 10, 2024
5c8a49f
refactor: cleanup named exports mixed usage
Jan 15, 2024
4a7d98e
test: cleanup default require test
Jan 15, 2024
b6a96d9
refactor: indentation cleanup
Jan 15, 2024
e4556e1
refactor: LinkedList is in fact a Deque
Jan 15, 2024
0242b60
fix: fix import usage in cjs file
Jan 15, 2024
017e951
docs: fix Deque code comments
Jan 15, 2024
2ef2f6c
refactor: cleanup deque type definition
Jan 15, 2024
c095aa5
refactor: make the Deque API similar to FixedDeque
Jan 15, 2024
95da864
test: consodidate exports testing code
Jan 15, 2024
89bd465
build(deps-dev): remove unneeded typescript dependencies
Jan 15, 2024
019592a
build(ci): avoid exports testing on node 12.x
Jan 15, 2024
c0c8f82
build(ci): avoid error > 0 with node 12.x
Jan 15, 2024
aba2f6b
refactor: trivial code cleanup
Jan 15, 2024
3c9eac4
docs: refine code comment
Jan 15, 2024
616b3ae
build: refine eslint ignore
Jan 15, 2024
e78f662
Merge branch 'esm-support' of github.com:jerome-benoit/mnemonist into…
Jan 15, 2024
4a44c92
feat: add pop() to Deque
Jan 15, 2024
51a4b55
docs: add changelog entries
Jan 15, 2024
724fa26
docs: refine changelog entries
Jan 15, 2024
199f2d9
docs: fix typo in changelog
Jan 15, 2024
0715851
build(deps): bump obliterator to latest patch version
Jan 15, 2024
4805c56
Merge branch 'esm-support' of github.com:jerome-benoit/mnemonist into…
Jan 16, 2024
8558118
docs: update README.md
Jan 16, 2024
aef0a91
refactor: deprecated some Deque API
Jan 16, 2024
9326651
docs: align syntax for members
Jan 16, 2024
1ea9152
test: improve Deque pop()/shift() tests
Jan 16, 2024
e492dea
test: add missing node types for exports test
Jan 16, 2024
fbdc822
test: add package-lock.json for strict test exports version
Jan 16, 2024
6a2010e
fix: add missing PointerVector TS export
Jan 16, 2024
507288e
Merge branch 'esm-support' of github.com:jerome-benoit/mnemonist into…
Jan 17, 2024
36f03f3
Merge branch 'master' into linkedlist2deque
Feb 2, 2024
b66cb81
Merge branch 'master' of https://github.com/Yomguithereal/mnemonist i…
Feb 6, 2024
60559b2
fix: fix mismerge
Feb 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ Full documentation for the library can be found [here](https://yomguithereal.git
**Classics**

* [Heap](https://yomguithereal.github.io/mnemonist/heap)
* [Linked List](https://yomguithereal.github.io/mnemonist/linked-list)
* [LRUCache](https://yomguithereal.github.io/mnemonist/lru-cache), [LRUMap](https://yomguithereal.github.io/mnemonist/lru-map)
* [MultiMap](https://yomguithereal.github.io/mnemonist/multi-map)
* [MultiSet](https://yomguithereal.github.io/mnemonist/multi-set)
Expand All @@ -39,6 +38,7 @@ Full documentation for the library can be found [here](https://yomguithereal.git
**Low-level & structures for very specific use cases**

* [Circular Buffer](https://yomguithereal.github.io/mnemonist/circular-buffer)
* [Deque](https://yomguithereal.github.io/mnemonist/linked-list)
* [Fixed Deque](https://yomguithereal.github.io/mnemonist/fixed-deque)
* [Fibonacci Heap](https://yomguithereal.github.io/mnemonist/fibonacci-heap)
* [Fixed Reverse Heap](https://yomguithereal.github.io/mnemonist/fixed-reverse-heap)
Expand Down
39 changes: 39 additions & 0 deletions deque.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* Mnemonist Deque Typings
* ========================
*/

export default class Deque<T> implements Iterable<T> {

// Members
size: number;

// Constructor
constructor();

// Methods
clear(): void;
peekFirst(): T | undefined;
/** @deprecated: use #.peekFirst() instead. */
first(): T | undefined;
peekLast(): T | undefined;
/** @deprecated: use #.peekLast() instead. */
peek(): T | undefined;
/** @deprecated: use #.peekLast() instead. */
last(): T | undefined;
push(value: T): number;
unshift(value: T): number;
pop(): T | undefined;
shift(): T | undefined;
forEach(callback: (value: T, index: number, list: this) => void, scope?: any): void;
toArray(): Array<T>;
values(): IterableIterator<T>;
entries(): IterableIterator<[number, T]>;
[Symbol.iterator](): IterableIterator<T>;
toString(): string;
toJSON(): Array<T>;
inspect(): any;

// Statics
static from<I>(iterable: Iterable<I> | {[key: string]: I}): Deque<I>;
}
295 changes: 295 additions & 0 deletions deque.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,295 @@
/**
* Mnemonist Deque
* ================
*
* Double-ended queue implemented with a doubly linked list using raw JavaScript objects
* as nodes as benchmarks proved it was the fastest thing to do.
*/
var Iterator = require('obliterator/iterator'),
forEach = require('obliterator/foreach');

/**
* Deque.
*
* @constructor
*/
function Deque() {
this.clear();
}

/**
* Method used to clear the deque.
*
* @return {undefined}
*/
Deque.prototype.clear = function() {

// Properties
this.head = null;
this.tail = null;
this.size = 0;
};

/**
* Method used to get the first item of the deque.
*
* @return {any}
*/
Deque.prototype.peekFirst = function() {
return this.head ? this.head.item : undefined;
};
/**
* @deprecated: use #.peekFirst() instead.
*/
Deque.prototype.peek = Deque.prototype.peekFirst;
/**
* @deprecated: use #.peekFirst() instead.
*/
Deque.prototype.first = Deque.prototype.peekFirst;

/**
* Method used to get the last item of the deque.
*
* @return {any}
*/
Deque.prototype.peekLast = function() {
return this.tail ? this.tail.item : undefined;
};
/**
* @deprecated: use #.peekLast() instead.
*/
Deque.prototype.last = Deque.prototype.peekLast;

/**
* Method used to add an item at the end of the deque.
*
* @param {any} item - The item to add.
* @return {number}
*/
Deque.prototype.push = function(item) {
var node = {item, prev: null, next: null};

if (!this.tail) {
this.head = this.tail = node;
} else {
node.prev = this.tail;
this.tail = this.tail.next = node;
}

this.size++;

return this.size;
};

/**
* Method used to add an item at the beginning of the deque.
*
* @param {any} item - The item to add.
* @return {number}
*/
Deque.prototype.unshift = function(item) {
var node = {item, prev: null, next: null};

if (!this.head) {
this.head = this.tail = node;
} else {
node.next = this.head;
this.head = this.head.prev = node;
}

this.size++;

return this.size;
};

/**
* Method used to retrieve & remove the last item of the deque.
*
* @return {any}
*/
Deque.prototype.pop = function() {
if (!this.size)
return undefined;

var node = this.tail;

this.tail = node.prev;
if (!this.tail) {
this.head = null;
} else {
this.tail.next = null;
}

this.size--;

return node.item;
};

/**
* Method used to retrieve & remove the first item of the deque.
*
* @return {any}
*/
Deque.prototype.shift = function() {
if (!this.size)
return undefined;

var node = this.head;

this.head = node.next;
if (!this.head) {
this.tail = null;
} else {
this.head.prev = null;
}

this.size--;

return node.item;
};

/**
* Method used to iterate over the deque.
*
* @param {function} callback - Function to call for each item.
* @param {object} scope - Optional scope.
* @return {undefined}
*/
Deque.prototype.forEach = function(callback, scope) {
if (!this.size)
return;

scope = arguments.length > 1 ? scope : this;

var node = this.head,
i = 0;

while (node) {
callback.call(scope, node.item, i, this);
node = node.next;
i++;
}
};

/**
* Method used to convert the deque into an array.
*
* @return {array}
*/
Deque.prototype.toArray = function() {
if (!this.size)
return [];

var array = new Array(this.size);

for (var i = 0, l = this.size, node = this.head; i < l; i++) {
array[i] = node.item;
node = node.next;
}

return array;
};

/**
* Method used to create an iterator over a deque's values.
*
* @return {Iterator}
*/
Deque.prototype.values = function() {
var node = this.head;

return new Iterator(function() {
if (!node)
return {
done: true
};

var value = node.item;
node = node.next;

return {
value: value,
done: false
};
});
};

/**
* Method used to create an iterator over a deque's entries.
*
* @return {Iterator}
*/
Deque.prototype.entries = function() {
var node = this.head,
i = 0;

return new Iterator(function() {
if (!node)
return {
done: true
};

var value = node.item;
node = node.next;
i++;

return {
value: [i - 1, value],
done: false
};
});
};

/**
* Attaching the #.values method to Symbol.iterator if possible.
*/
if (typeof Symbol !== 'undefined')
Deque.prototype[Symbol.iterator] = Deque.prototype.values;

/**
* Convenience known methods.
*/
Deque.prototype.toString = function() {
return this.toArray().join(',');
};

Deque.prototype.toJSON = function() {
return this.toArray();
};

Deque.prototype.inspect = function() {
var array = this.toArray();

// Trick so that node displays the name of the constructor
Object.defineProperty(array, 'constructor', {
value: Deque,
enumerable: false
});

return array;
};

if (typeof Symbol !== 'undefined')
Deque.prototype[Symbol.for('nodejs.util.inspect.custom')] = Deque.prototype.inspect;

/**
* Static @.from function taking an arbitrary iterable & converting it into
* a deque.
*
* @param {Iterable} iterable - Target iterable.
* @return {Deque}
*/
Deque.from = function(iterable) {
var list = new Deque();

forEach(iterable, function(value) {
list.push(value);
});

return list;
};

/**
* Exporting.
*/
module.exports = Deque;
1 change: 1 addition & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export {default as Heap, MinHeap, MaxHeap} from './heap';
export {default as InvertedIndex} from './inverted-index';
export {default as KDTree} from './kd-tree';
export {default as LinkedList} from './linked-list';
export {default as Deque} from './deque';
export {default as LRUCache} from './lru-cache';
export {default as LRUCacheWithDelete} from './lru-cache-with-delete';
export {default as LRUMap} from './lru-map';
Expand Down
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ module.exports = {
InvertedIndex: require('./inverted-index.js'),
KDTree: require('./kd-tree.js'),
LinkedList: require('./linked-list.js'),
Deque: require('./deque.js'),
LRUCache: require('./lru-cache.js'),
LRUCacheWithDelete: require('./lru-cache-with-delete.js'),
LRUMap: require('./lru-map.js'),
Expand Down
1 change: 1 addition & 0 deletions index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export {default as StaticIntervalTree} from './static-interval-tree.js';
export {default as InvertedIndex} from './inverted-index.js';
export {default as KDTree} from './kd-tree.js';
export {default as LinkedList} from './linked-list.js';
export {default as Deque} from './deque.js';
export {default as LRUCache} from './lru-cache.js';
export {default as LRUCacheWithDelete} from './lru-cache-with-delete.js';
export {default as LRUMap} from './lru-map.js';
Expand Down
Loading