Doubly Linked List
Single Linked List와는 다르게 Pointer가 2개이다. 다음 Data를 가리키는 pointer, 그 전 Data를 가리키는 pointer가 그것이다.
pointer가 하나 더 있기 때문에 Memory가 2배로 소모되지만 더 flex하게 Data를 다룰 수 있다.(특히 앞에서만 시작했던 linked list와는 달리 뒤에서도 접근이 가능하다.)
웹페이지 forward, backward가 이것으로 구성되어 있다.
Methods
methods | Big O notation |
---|---|
Inserts | O(1) |
Removal | O(1) |
Searching | O(n) |
Access | O(n) |
물론 실제로는 searching, access는 O(n/2)지만 규칙에 따라 O(n)이다.
reference
https://visualgo.net/en/list?slide=1a
My codes (Javascript)
class Node{
constructor(val){
this.val = val;
this.next = null;
this.prev = null;
}
}
class DoublyLinkedList {
constructor(){
this.head = null;
this.tail = null;
this.length = 0;
}
push(val){
var newNode = new Node(val);
if(this.length === 0){
this.head = newNode;
this.tail = newNode;
} else {
this.tail.next = newNode;
newNode.prev = this.tail;
this.tail = newNode;
}
this.length++;
return this;
}
pop(){
if(!this.head) return undefined;
var poppedNode = this.tail;
if(this.length === 1){
this.head = null;
this.tail = null;
} else {
this.tail = poppedNode.prev;
this.tail.next = null;
poppedNode.prev = null;
}
this.length--;
return poppedNode;
}
shift(){
if(this.length === 0) return undefined;
var oldHead = this.head;
if(this.length === 1){
this.head = null;
this.tail = null;
}else{
this.head = oldHead.next;
this.head.prev = null;
oldHead.next = null;
}
this.length--;
return oldHead;
}
unshift(val){
var newNode = new Node(val);
if(this.length === 0) {
this.head = newNode;
this.tail = newNode;
} else {
this.head.prev = newNode;
newNode.next = this.head;
this.head = newNode;
}
this.length++;
return this;
}
get(index){
if(index < 0 || index >= this.length) return null;
var count, current;
if(index <= this.length/2){
count = 0;
current = this.head;
while(count !== index){
current = current.next;
count++;
}
} else {
count = this.length - 1;
current = this.tail;
while(count !== index){
current = current.prev;
count--;
}
}
return current;
}
set(index, val){
var foundNode = this.get(index);
if(foundNode != null){
foundNode.val = val;
return true;
}
return false;
}
insert(index, val){
if(index < 0||index >= this.length){
return undefinded;
}
if(index === 0){
return this.unshift(val);
}
if(index === this.length){
return this.push(val);
}
var newNode = new Node(val);
var foundNode = this.get(index-1);
var nextNode = foundNode.next;
foundNode.next = newNode;
nextNode.prev = newNode;
newNode.next = nextNode;
newNode.prev = foundNode;
this.length++;
return this;
}
remove(index){
if(index < 0||index >= this.length){
return undefinded;
}
if(index === 0){
return this.shift();
}
if(index === this.length-1){
return this.pop();
}
var foundNode = this.get(index);
var nextNode = foundNode.next;
var prevNode = foundNode.prev;
nextNode.prev = prevNode;
prevNode.next = nextNode;
foundNode = null;
this.length--;
return foundNode;
}
}