Algorithm:
단일 연결 리스트(Singly Linked List)
칠일오.
2023. 5. 22. 13:32
- 순서에 따라 다수의 데이터를 저장한다. 그러나 배열과 다른 점은 인덱스가 없다.
- 마치 객체들이 연속으로 연결되어 있는 기차와 같다.
- 각각 요소를 '노드(node)'라고 부른다. string, number와 같은 하나의 데이터를 저장한다.
- 각 노드들은 다음 요소를 가리키는 정보 또한 저장하고 있다.
- 다음 노드가 없을 경우, null을 저장한다.
- head는 연결 리스트의 시작 노드를 가리킨다.
- tail은 연결 리스트의 마지막 노드를 가리킨다.
배열은 엘레베이터, 연결 리스트는 계단과도 같다.
List | Array |
Do not have indexes! | Indexed in order! |
Connected via nodes with a next pointer | Insertion and deletion can be expensive |
Random access is not allowed | Can quickly be accessed at a specific index |
➡ 연결 리스트는 새로운 항목을 추가하거나 기존 항목을 제거할 경우 편리하다. (인덱스 없음)
class Node{
constructor(val){
this.val = val;
this.next = null;
}
}
class SinglyLinkedList{
constructor(){
this.head = null;
this.tail = null;
this.length = 0;
}
push(val) {
var newNode = new Node(val)
if (!this.head) {
this.head = newNode;
this.tail = newNode;
} else {
this.tail.next = newNode;
this.tail = newNode;
}
this.length++;
return this;
}
pop() {
if(!this.head) return undefined;
var current = this.head;
var newTail = current;
while(current.next){
newTail = current;
current = current.next; // newTail은 항상 이전 노드를 가리킨다.
}
this.tail = newTail;
this.tail.next = null; // pop
this.length--;
if(this.length === 0){
this.head = null;
this.tail = null;
}
return current;
}
shift(){
if(!this.head) return undefined;
var currentHead = this.head;
this.head = currentHead.next;
this.length--;
if(this.length === 0){
this.tail = null;
}
return currentHead;
}
unshift(val){
var newNode = new Node(val);
if(!this.head) { // 리스트 길이가 0일 경우
this.head = newNode;
this.tail = this.head;
} else {
newNode.next = this.head;
this.head = newNode;
}
this.length++;
return this;
}
get(index){
// 인덱스가 음수이거나 길이보다 같거나 클 경우 null을 반환
if(index < 0 || index >= this.length) return null;
var counter = 0;
var current = this.head;
while(counter !== index){
current = current.next;
counter++;
}
return current;
}
set(index, val){
var foundNode = this.get(index);
if(foundNode){
foundNode.val = val;
return true;
}
return false;
}
insert(index, val){
// 음수 혹은 리스트 길이보다 큰 값인지 확인
// 길이가 같으면 맨끝에 삽입한다.
if(index < 0 || index > this.length) return false;
if(index === this.length) return !!this.push(val);
if(index === 0) return !!this.unshift(val);
var newNode = new Node(val);
var prev = this.get(index - 1);
var temp = prev.next;
prev.next = newNode;
newNode.next = temp;
this.length++;
return true;
}
remove(index){
if(index < 0 || index >= this.length) return undefined;
if(index === 0) return this.shift();
if(index === this.length - 1) return this.pop();
var previousNode = this.get(index - 1);
var removed = previousNode.next;
previousNode.next = removed.next;
this.length--;
return removed;
}
reverse(){
var node = this.head;
this.head = this.tail;
this.tail = node;
var next;
var prev = null; // 초기 tail의 next가 null이기 때문에
for(var i = 0; i < this.length; i++){
next = node.next;
node.next = prev;
prev = node;
node = next;
}
return this;
}
// console.log를 통해 리스트에 있는 노드들을 순서에 따라 배열로 프린트한다. (return X)
print(){
var arr = [];
var current = this.head
while(current){
arr.push(current.val)
current = current.next
}
console.log(arr);
}
}
var list = new SinglyLinkedList()
list.push("HELLO")
list.push("GOODBYE")
list.push("!")
list.push(100)
list.push(201)
list.push(250)
list.push(350)
list.push(999)