/* --JavaScript LinkedList Object - this is doubly linked-- */ function LinkedList(name) { /* --LinkedList Constructor - properties/methods-- */ var lsize, firstNode, lastNode; this.name = (name == null? 'list': name); lsize = 0; this.addFirst = _addFirst; this.addLast = _addLast; this.removeFirst = _removeFirst; this.removeLast = _removeLast; this.getFirst = _getFirst; this.getLast = _getLast; this.insert = _insert; this.isEmpty = _isEmpty; this.size = _size; this.get = _get; this.getNode = _getNode; this.set = _set; this.clear = _clear; this.clone = _clone; this.contains = _contains; this.remove = _remove; this.toArray = _toArray; this.moveUp = _moveUp; this.moveDown = _moveDown; /* --define methods-- */ function _addFirst(newItem) { /* --adds an item to the front of a list-- */ if (lsize == 0) firstNode = lastNode = new _ListNode(newItem,null,null); else { var tempNode = new _ListNode(newItem, firstNode, null); firstNode.previousNode = tempNode; firstNode = tempNode; } lsize++; } function _addLast(newItem) { /* --adds an item to the end of a list-- */ if (lsize == 0) firstNode = lastNode = new _ListNode(newItem,null,null); else lastNode = lastNode.nextNode = new _ListNode(newItem,null,lastNode); lsize++; } function _removeFirst() { /* --removes/returns an item from the front of list-- */ if (firstNode == null) return null; var removeItem = firstNode.data; switch (lsize) { case 0: return; break; case 1: firstNode = lastNode = null; break; default: firstNode = firstNode.nextNode; firstNode.previousNode = null; break; } lsize--; return removeItem; } function _removeLast(newItem) { /* --removes/returns an item from the back of list-- */ if (firstNode == null) return null; var removeItem = lastNode.data; switch (lsize) { case 1: firstNode = lastNode = null; break; default: /* --reset last node-- */ lastNode = lastNode.previousNode; lastNode.nextNode = null; break; } lsize--; return removeItem; } function _moveUp(index) { if (index < 1 || index > lsize - 1) return; swap(moveToNode(index)); } function _moveDown(index) { if (index < 0 || index > lsize - 2) return; swap(moveToNode(index+1)); } function swap(currentNode) { /* --swaps currentNode with its previousNode-- */ if ( lsize == 0 || currentNode == firstNode ) return; if ( lsize == 1) return; if ( lsize == 2) { lastNode = currentNode.nextNode = currentNode.previousNode; firstNode = currentNode.previousNode.previousNode = currentNode; lastNode.nextNode = null; firstNode.previousNode = null; return; } if ( currentNode == lastNode ) { var nMinus2Node = currentNode.previousNode.previousNode; nMinus2Node.nextNode = currentNode; currentNode.previousNode.previousNode = currentNode; lastNode = currentNode.nextNode = currentNode.previousNode; currentNode.previousNode = nMinus2Node; lastNode.nextNode = null; return; } var nMinus2Node = currentNode.previousNode.previousNode; var nPlus1Node = currentNode.nextNode; if ( nMinus2Node == null ) firstNode = currentNode; else nMinus2Node.nextNode = currentNode; currentNode.nextNode.previousNode = currentNode.previousNode; currentNode.nextNode = currentNode.previousNode; currentNode.previousNode.previousNode = currentNode; currentNode.previousNode.nextNode = nPlus1Node; currentNode.previousNode = nMinus2Node; } function moveToNode(index) { /* --returns an item at a specified index-- */ if (index < 0 || index > lsize - 1) return null; /* --move to index node-- */ var currentNode; if ( index < Math.floor(lsize/2) ) { currentNode = firstNode; for (var i = 0; i < index; i++) currentNode = currentNode.nextNode; } else { currentNode = lastNode; for (var i = lsize; i > index+1; i--) currentNode = currentNode.previousNode; } return currentNode; } function _isEmpty() { return firstNode == null; } /* --returns true if list is empty-- */ function _getFirst() { /* --returns an item from the front of the list-- */ if (firstNode == null) return null; else return firstNode.data; } function _getLast() { /* --returns an item from the end of the list-- */ if (lastNode == null) return null; else return lastNode.data; } function _insert(index, newItem) { /* --inserts an element into the list-- */ if (index < 0 || index > lsize) return; if (firstNode == null || index == 0) this.addFirst(newItem); else if ( index == lsize ) this.addLast(newItem); else { var currentNode = moveToNode(index); var newNode = new _ListNode(newItem, currentNode, currentNode.previousNode); currentNode.previousNode.nextNode = newNode; currentNode.previousNode = newNode; lsize++; } } function _set(index, newItem) { /* --sets an element in the list-- */ if (index < 0 || index > lsize) return null; if (firstNode == null && index == 0) this.addFirst(newItem); else if ( index == lsize ) this.addLast(newItem); else { var replaceNode = moveToNode(index); var returnVal = replaceNode.data; replaceNode.data = newItem; return returnVal; } return null; } function _size() { return lsize; } /* --returns size of list-- */ function _get(index) { if (index < 0 || index > lsize - 1) return null; return moveToNode(index).data; } function _getNode(index) { if (index < 0 || index > lsize - 1) return null; return moveToNode(index); } function _clear() { /* --clears all items from the list-- */ firstNode = lastNode = null; lsize = 0; } function _clone() { /* --returns a cloned list object-- */ var tempList = new LinkedList(); var currentNode = firstNode; for (var i = 0; i < lsize; i++) { tempList.addLast(currentNode.data); currentNode = currentNode.nextNode; } return tempList; } function _remove(index) { /* --removes an item from a specified index-- */ if (index < 0 || index > lsize - 1) return null; if (index == 0) { var returnVal = firstNode.data; this.removeFirst(); return returnVal; } if ( index == lsize - 1) { var returnVal = lastNode.data; this.removeLast(); return returnVal; } var currentNode = moveToNode(index); currentNode.nextNode.previousNode = currentNode.previousNode; currentNode.previousNode.nextNode = currentNode.nextNode; lsize--; return currentNode.data; } function _contains(item) { /* --returns true if the specified item is contained w/in the list-- */ var returnValue = false; var currentNode = firstNode; for (var i = 0; i < lsize; i++) { if (currentNode.data == item) { returnValue = true; break; } else currentNode = currentNode.nextNode; } return returnValue; } function _toArray() { /* --returns an array of the list values-- */ var tempArr = new Array(lsize); var currentNode = firstNode; for (var i = 0; i < lsize; i++) { tempArr[i] = currentNode.data; currentNode = currentNode.nextNode; } return tempArr; } function _ListNode(data, nextNode, previousNode) { /* --List node Object-- */ this.data = data; this.nextNode = nextNode; this.previousNode = previousNode; } }