Linked List 노드들을 그림으로 표현 (출처 : 생활코딩)
배열 리스트와 연결 리시트의 차이점을 잘 보여주는 그림 (출처 : 생활코딩)
- 데이터에 대한 접근이 잦은 경우 ==> 배열
- 데이터에 대한 수정이 잦은 경우 ==> 배열
- 데이터의 추가, 삽입, 삭제가 잦은 경우 ==> 연결 리스트
// 노드 클래스
class Node {
// 마지막 노드의 next는 다폴트로 null이 되도록 구조생성
constructor(data, next = null) {
this.data = data;
this.next = next;
}
}
const n1 = new Node(100);
console.log(n1);
// Node { data: 100, next: null } 노드를 생성 할 수 있다.
// 링크드 리스트 클래스
class LinkedList {
constructor() {
this.head = null;
this.size = 0;
}
}
// 현재는 목록이 비어있기 때문에 디폴트 head = null, size = 0
- head가 존재하며 기본적으로 null값을 가진다.
- head가 null이면 목록이 비어 있음을 의미한다.
- size : 목록의 크기를 추적한다.
// Insert first node
insertFirst(data) {
this.head = new Node(data, this.head);
this.size++;
}
const ll = new LinkedList();
ll.insertFirst(100);
console.log(ll);
LinkedList { head: Node { data: 100, next: null }, size: 1 }
const ll = new LinkedList();
ll.insertFirst(100);
ll.insertFirst(200);
console.log(ll);
LinkedList {
head: Node { data: 200, next: Node { data: 100, next: null } },
size: 2
}
// Print list data
printListData() {
let current = this.head; // current는 지금의 헤드
while (current) { // current가 null이 될때 까지
console.log(current.data, current.next);
current = current.next; // current는 next의 헤드가 된다.
}
}
const ll = new LinkedList();
ll.insertFirst(100);
ll.insertFirst(200);
ll.insertFirst(300);
ll.printListData();
// Insert last node
insertLast(data) {
let node = new Node(data); // 헤드에 생성하는게 아니므로
let current; // current를 초기화
// 우선 마지막 노드를 먼저 고려한다.
// If empty, make head 리스트가 비어있다면 헤드가 되야한다.
if (!this.head) {
this.head = node;
} else {
current = this.head; // 헤드가 있다면, 기존의 헤드를 가져온다.
while (current.next) { // 헤드의 다음 노드가 있는지 확인하기 위해
current = current.next; // current를 마지막까지 이동
}
current.next = node; // 마지막 current의 next에 새노드 추가
}
this.size++; // 마지막에 추가되었기에 사이즈 ++
}
const ll = new LinkedList();
ll.insertFirst(100);
ll.insertFirst(200);
ll.insertFirst(300);
ll.insertLast(400);
ll.printListData();
// Insert at index
insertAt(data, index) {
// If index is out of range 리스트 사이즈보다 큰 인덱스의 경우
if (index > 0 && index > this.size) {
return;
}
// If first index 지정한 인덱스가 0 즉 헤드인 경우
if (index === 0) {
this.insertFirst(data) // insertFirst()과 동일
return;
}
// 인덱스가 0이 아닌 경우
const node = new Node(data); // 새로운 노드가 필요하다.
let current, previous; // current와 previous를 초기화
// Set current to first // current를 먼저 셋팅하자
current = this.head; // current는 현재의 헤드
let count = 0;
// 인덱스가 2라고 가정한다면
while (count < index) { // ex) 0 < 2 => 1 < 2 => 2 < 2
previous = current; // Node before index
// pre=0 => pre=1 => pre=2
count++; // 1 => 2 => 3
current = current.next; // Node after index
// current=1 => current 2 => 3
}
// current = 3 pre = 2
node.next = current;
previous.next = node;
// 새로운 노드는 2와 3사이에 들어간다.
this.size++;
}
const ll = new LinkedList();
ll.insertFirst(100);
ll.insertFirst(200);
ll.insertFirst(300);
ll.insertLast(400);
ll.insertAt(500, 2);
ll.printListData();
// search for data by index
searchAt(index) {
let current = this.head; // 헤드부터 탐방
let count = 0; // 특정 인덱스까지
while (current) { // current가 null까지
if (count === index) {
console.log(current.data);
}
count++;
current = current.next; // 다음 노드로 이동
}
return null; // 찾으면 종료
}
const ll = new LinkedList();
ll.insertFirst(100);
ll.insertFirst(200);
ll.insertFirst(300);
ll.insertLast(400);
ll.insertAt(500, 0);
ll.printListData();
console.log("\n");
ll.getAt(2);
//
// Remove at index
removeAt(index) { // 범위 벗아나면 리턴
if (index > 0 && index > this.size) {
return;
}
let current = this.head; // 헤드부터 탐방
let previous;
let count = 0;
// Remove first
if (index === 0) {
this.head = current.next; // 헤드를 다음 노드로 지정 (기존 헤드 삭제)
} else { // 2라고 가정한다면
while (count < index) { // 0 < 2 => 1 < 2 => 2 < 2
count++; // 1 => 2 => 3
previous = current; // pre:0 => pre:1 => pre:2
current = current.next; // cur:1 => cur:2 => cur:3
}
// pre: 2 cur: 3
previous.next = current.next;
// 2번쨰 노드의 next를 3번쨰 노드 next로 바꿈
// 즉 2번쨰 노드의 data가 사라진다.
}
this.size--;
}
const ll = new LinkedList();
ll.insertFirst(100);
ll.insertFirst(200);
ll.insertFirst(300);
ll.insertLast(400);
ll.insertAt(500, 0);
ll.removeAt(2);
ll.printListData();
// Clear list
clearList() {
this.head = null;
this.size = 0;
}
const ll = new LinkedList();
ll.insertFirst(100);
ll.insertFirst(200);
ll.insertFirst(300);
ll.insertLast(400);
ll.insertAt(500, 0);
ll.removeAt(2);
ll.clearList();
ll.printListData();