[선형] 7. 이중 연결 리스트
1. 이중 연결 리스트 (Double Linked List)
- 각 노드가 데이터와 포인터를 가지며,
두 줄
로 연결되어 있는 방식으로 데이터를 저장하는 자료 구조 - 노드 개수 / 비어있는지 확인 :
DoubleLinkedList.size()
,DoubleLinkedList.isEmpty()
- 순차 출력 / 역 출력 :
DoubleLinkedList.printNode()
,DoubleLinkedList.printNodeInverse()
- 노드 추가 :
DoubleLinkedList.append()
,DoubleLinkedList.insert()
- 노드 삭제 :
DoubleLinkedList.remove()
,DoubleLinkedList.removeAt()
- 데이터 위치 확인 :
DoubleLinkedList.indexOf()
2. 이중 연결 리스트 구현하기
1. 기본
// Node()
function Node(data) {
this.data = data;
this.next = null;
this.prev = null;
}
function DoubleLinkedList() {
this.head = null;
this.tail = null;
this.length = 0;
}
DoubleLinkedList.prototype.size = function () {
return this.length;
};
DoubleLinkedList.prototype.isEmpty = function () {
return this.length === 0;
};
let dll = new DoubleLinkedList();
let node;
console.log(dll); //DoubleLinkedList { head: null, tail: null, length: 0 }
node = new Node(123);
dll.head = node;
dll.tail = node;
dll.length++;
console.log(dll);
// DoubleLinkedList {
// head: Node { data: 123, next: null, prev: null },
// tail: Node { data: 123, next: null, prev: null },
// length: 1
// }
node = new Node(456);
dll.tail.next = node;
node.prev = dll.tail;
dll.tail = node;
dll.length++;
console.log(dll);
// DoubleLinkedList {
// head: <ref *1> Node {
// data: 123,
// next: Node { data: 456, next: null, prev: [Circular *1] },
// prev: null
// },
// tail: <ref *2> Node {
// data: 456,
// next: null,
// prev: <ref *1> Node { data: 123, next: [Circular *2], prev: null }
// },
// length: 2
// }
2. printNode(), printNodeInverse(), append()
DoubleLinkedList.prototype.printNode = function(){
process.stdout.write("head -> ")
for (let node = this.head; node != null; node = node.next){
process.stdout.write(`${node.data} => `)
}
console.log("null")
}
DoubleLinkedList.prototype.printNodeInverse = function(){
let temp = []
process.stdout.write("null <- ")
for (let node = this.tail; node !=null; node = node.prev){
temp.push(node.data)
}
for (let i = temp.length-1; i >= 0; i--){
process.stdout.write(`${temp[i]} <- `)
}
console.log("tail")
}
// while 안써도 된다
DoubleLinkedList.prototype.append = function(value){
let node = new Node(value)
if (this.head === null){
this.head = node
this.tail = node
} else {
this.tail.next = node;
node.prev = this.tail
this.tail = node
}
this.length++
}
dll.append(1)
dll.append(10)
dll.append(100)
dll.printNode() //head -> 123 => 456 => 1 => 10 => 100 => null
dll.printNodeInverse() //null <- 123 <- 456 <- 1 <- 10 <- 100 <- tail
3. insert()
DoubleLinkedList.prototype.insert = function (value, position = 0) {
if (position < 0 || position > this.length) {
return false;
}
let node = new Node(value),
current = this.head,
index = 0,
prev;
if (position == 0) {
if (this.head === null) {
this.head = node;
this.tail = node;
} else {
node.next = current;
current.prev = node;
this.head = node;
}
} else if (position === this.length) {
current = this.tail;
current.next = node;
node.prev = current;
this.tail = node;
} else {
while (index++ < position) {
prev = current;
current = current.next;
}
node.next = current;
prev.next = node;
current.prev = node;
node.prev = prev;
}
this.length++;
return true;
};
dll.insert(1);
dll.insert(10);
dll.insert(100);
dll.printNode(); //head -> 100 => 10 => 1 => 123 => 456 => 1 => 10 => 100 => null
dll.printNodeInverse(); //null <- 100 <- 10 <- 1 <- 123 <- 456 <- 1 <- 10 <- 100 <- tail
dll.insert(2,1);
dll.insert(3,3);
dll.insert(100);
dll.printNode(); //head -> 100 => 100 => 2 => 10 => 3 => 1 => 123 => 456 => 1 => 10 => 100 => null
dll.printNodeInverse(); //null <- 100 <- 100 <- 2 <- 10 <- 3 <- 1 <- 123 <- 456 <- 1 <- 10 <- 100 <- tail
4. remove()
DoubleLinkedList.prototype.remove = function (value) {
let current = this.head,
prev = current;
while (current.data != value && current.next != null) {
prev = current;
current = current.next;
}
if (current.data != value) {
return null;
}
if (current === this.head) {
this.head = current.next;
if (this.length === 1) this.tail = null;
else this.head.prev = null;
} else if (current === this.tail) {
this.tail = current.prev;
this.tail.next = null;
} else {
prev.next = current.next;
current.next.prev = prev;
}
this.length--;
return current.data;
};
dll.insert(1);
dll.insert(10);
dll.insert(100);
dll.insert(2,1);
dll.insert(3,3);
dll.printNode(); //head -> 100 => 100 => 2 => 10 => 3 => 1 => 123 => 456 => 1 => 10 => 100 => null
dll.printNodeInverse(); //null <- 100 <- 100 <- 2 <- 10 <- 3 <- 1 <- 123 <- 456 <- 1 <- 10 <- 100 <- tail
console.log(dll.remove(1000)) //null
dll.printNode(); //head -> 100 => 100 => 2 => 10 => 3 => 1 => 123 => 456 => 1 => 10 => 100 => null
console.log(dll.remove(1))
dll.printNode(); //head -> 100 => 2 => 10 => 3 => 123 => 456 => 1 => 10 => 100 => null
console.log(dll.remove(2))
dll.printNode(); //head -> 100 => 10 => 3 => 123 => 456 => 1 => 10 => 100 => null
console.log(dll.remove(100))
dll.printNode(); //head -> 10 => 3 => 123 => 456 => 1 => 10 => 100 => null
5. removeAt()
DoubleLinkedList.prototype.removeAt = function (position = 0){
if (position < 0 || position >= this.length) {
return null
}
let current = this.head,
index = 0,
prev
if (position === 0 ){
this.head = current.next
if (this.length === 1) this.tail = null
else this.head.prev = null
} else if (position === this.length -1){
current = this.tail
this.tail = current.prev
this.tail.next = null
} else {
while (index++ < position){
prev = current
current = current.next
}
prev.next = current.next
current.next.prev = prev
}
this.length--
return current.data
}
dll.insert(1);
dll.insert(10);
dll.insert(100);
dll.insert(2,1);
dll.insert(3,3);
dll.printNode(); //head -> 100 => 100 => 2 => 10 => 3 => 1 => 123 => 456 => 1 => 10 => 100 => null
dll.printNodeInverse(); //null <- 100 <- 100 <- 2 <- 10 <- 3 <- 1 <- 123 <- 456 <- 1 <- 10 <- 100 <- tail
console.log(dll.removeAt(1000)) //null
dll.printNode(); //head -> 100 => 100 => 2 => 10 => 3 => 1 => 123 => 456 => 1 => 10 => 100 => null
console.log(dll.removeAt(4)) //1
dll.printNode(); //head -> 100 => 2 => 10 => 3 => 123 => 456 => 1 => 10 => 100 => null
console.log(dll.removeAt()) //100
dll.printNode(); //head -> 2 => 10 => 3 => 123 => 456 => 1 => 10 => 100 => null
console.log(dll.removeAt(1)) //10
dll.printNode(); //head -> 2 => 3 => 123 => 456 => 1 => 10 => 100 => null
6. indexOf()
// LinkedList 와 완전 동일
DoubleLinkedList.prototype.indexOf = function (value) {
let current = this.head,
index = 0;
while (current != null) {
if (current.data === value) {
return index;
}
index++;
current = current.next;
}
return -1;
};
DoubleLinkedList.prototype.remove2 = function (value) {
let index = this.indexOf(value);
return this.removeAt(index);
};
dll.insert(1);
dll.insert(10);
dll.insert(100);
dll.insert(2, 1);
dll.insert(3, 3);
dll.printNode(); //head -> 100 => 100 => 2 => 10 => 3 => 1 => 123 => 456 => 1 => 10 => 100 => null
dll.printNodeInverse(); //null <- 100 <- 100 <- 2 <- 10 <- 3 <- 1 <- 123 <- 456 <- 1 <- 10 <- 100 <- tail
console.log(dll.remove2(1000)); //null
dll.printNode(); //head -> 100 => 100 => 2 => 10 => 3 => 1 => 123 => 456 => 1 => 10 => 100 => null
console.log(dll.remove2(100)); //100
dll.printNode(); //head -> 2 => 10 => 3 => 1 => 123 => 456 => 1 => 10 => 100 => null
console.log(dll.remove2(2)); //2
dll.printNode(); //head -> 10 => 3 => 1 => 123 => 456 => 1 => 10 => 100 => null
console.log(dll.remove2(1)); //1
dll.printNode(); //head -> 10 => 3 => 123 => 456 => 1 => 10 => 100 => null