|
const nodeFrom = value => ({ value, next: null, prev: null });
|
|
|
|
const add = ( prev, node, next, list ) => {
|
|
if( prev !== null ){
|
|
prev.next = node;
|
|
} else {
|
|
list.head = node;
|
|
}
|
|
|
|
if( next !== null ){
|
|
next.prev = node;
|
|
} else {
|
|
list.tail = node;
|
|
}
|
|
|
|
node.prev = prev;
|
|
node.next = next;
|
|
|
|
list.length++;
|
|
|
|
return node;
|
|
};
|
|
|
|
const remove = ( node, list ) => {
|
|
let { prev, next } = node;
|
|
|
|
if( prev !== null ){
|
|
prev.next = next;
|
|
} else {
|
|
list.head = next;
|
|
}
|
|
|
|
if( next !== null ){
|
|
next.prev = prev;
|
|
} else {
|
|
list.tail = prev;
|
|
}
|
|
|
|
node.prev = node.next = null;
|
|
|
|
list.length--;
|
|
|
|
return node;
|
|
};
|
|
|
|
class LinkedList {
|
|
constructor( vals ){
|
|
this.length = 0;
|
|
this.head = null;
|
|
this.tail = null;
|
|
|
|
if( vals != null ){
|
|
vals.forEach( v => this.push(v) );
|
|
}
|
|
}
|
|
|
|
size(){
|
|
return this.length;
|
|
}
|
|
|
|
insertBefore( val, otherNode ){
|
|
return add( otherNode.prev, nodeFrom(val), otherNode, this );
|
|
}
|
|
|
|
insertAfter( val, otherNode ){
|
|
return add( otherNode, nodeFrom(val), otherNode.next, this );
|
|
}
|
|
|
|
insertNodeBefore( newNode, otherNode ){
|
|
return add( otherNode.prev, newNode, otherNode, this );
|
|
}
|
|
|
|
insertNodeAfter( newNode, otherNode ){
|
|
return add( otherNode, newNode, otherNode.next, this );
|
|
}
|
|
|
|
push( val ){
|
|
return add( this.tail, nodeFrom(val), null, this );
|
|
}
|
|
|
|
unshift( val ){
|
|
return add( null, nodeFrom(val), this.head, this );
|
|
}
|
|
|
|
remove( node ){
|
|
return remove( node, this );
|
|
}
|
|
|
|
pop(){
|
|
return remove( this.tail, this ).value;
|
|
}
|
|
|
|
popNode(){
|
|
return remove( this.tail, this );
|
|
}
|
|
|
|
shift(){
|
|
return remove( this.head, this ).value;
|
|
}
|
|
|
|
shiftNode(){
|
|
return remove( this.head, this );
|
|
}
|
|
|
|
get_object_at( index ){
|
|
if(index <= this.length()){
|
|
var i = 1;
|
|
var current = this.head;
|
|
while(i < index){
|
|
current = current.next;
|
|
i++;
|
|
}
|
|
return current.value;
|
|
}
|
|
}
|
|
|
|
set_object_at( index, value){
|
|
if(index <= this.length()) {
|
|
var i = 1;
|
|
var current = this.head;
|
|
while (i < index) {
|
|
current = current.next;
|
|
i++;
|
|
}
|
|
current.value = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = LinkedList;
|
|
|