classNode {constructor(data) {this.data = data;this.next =null; }}classSinglyLinkedList {constructor() {this.head =null;this.rear =null;this.size =0; }// 단일 연결 리스트 맨 앞에 원소 추가하기unshift(data) {constnode=newNode(data);if (!this.head) this.rear = node;node.next =this.head;this.head = node;this.size +=1;returnthis; }// 단일 연결 리스트 맨 뒤에 원소 추가하기push(data) {constnode=newNode(data);if (this.size ===0) this.head = node;elsethis.rear.next = node;this.rear = node;this.size++;returnthis; }// 단일 연결 리스트 중간에 원소 추가하기insert(index, data) {if (index <0|| index >this.size) returnfalse;if (index ===0) return!!this.unshift(data);if (index ===this.size) return!!this.push(data);constnode=newNode(data);let prev =this.get(index -1);node.next =prev.next;prev.next = node;this.size +=1;returntrue; }// 단일 연결 리스트의 원소 가져오기get(index) {if (index <0|| index >=this.size) returnnull;if (index ===this.size -1) returnthis.rear;let cur =this.head;let count =0;while (count < index) { cur =cur.next; count +=1; }return cur; }// 단일 연결 리스트의 첫번째 원소 삭제하기shift() {if (!this.head) returnundefined;constcurrentHead=this.head;this.head =currentHead.next;this.size -=1;if (this.size ===0) this.rear =null;return currentHead; }// 단일 연결 리스트의 마지막 원소 삭제하기pop() {if (!this.head) returnundefined;let current =this.head;let newRear = current;while (current.next) { newRear = current; current =current.next; }newRear.next =null;this.rear = newRear;this.size -=1;if (this.size ===0) {this.head =null;this.rear =null; }return current; }// 단일 연결 리스트의 중간 원소 삭제하기insert(index, data) {if (index <0|| index >this.size) returnfalse;if (index ===0) return!!this.unshift(data);if (index ===this.size) return!!this.push(data);constnode=newNode(data);let prev =this.get(index -1);node.next =prev.next;prev.next = node;this.size +=1;returntrue; }// 단일 연결 리스트 초기화하기clearList() {this.head =null;this.rear =null;this.size =0; }// 단일 연결 리스트의 모든 원소 출력하기printListData() {let cur =this.head;while (cur) {console.log(cur); cur =cur.next; } }// 단일 연결 리스트 역순으로 바꾸기reverse() {let head =this.head;let rear =this.rear;this.head = rear;this.rear = head;let prev =this.rear;let cur =this.rear.next;let count =0;while (count <this.size -1) {consttemp=cur.next;cur.next = prev; cur = temp; prev = cur; count +=1; }this.rear.next =null;returnthis; }}
1. 개요
배열과 함께 다른 자료 구조들을 구현하는 데 자주 사용되는 연결 리스트에 대해 살펴본다.
2. 연결 리스트란?
각 노드가 데이터와 포인터를 가지고 한 줄로 연결되어 있는 방식으로 데이터를 저장하는 자료 구조이다. 연결 리스트는 자료의 추가와 삭제가 O(1)의 시간을 가능하다는 장점을 갖지만 특정 위치의 데이터를 검색해 내는데에는 O(n)의 시간이 걸리는 단점을 갖고 있다.
연결 리스트의 종류는 아래와 같다.
단일(단방향) 연결 리스트
각 노드에 자료 공간과 한 개의 포인터 공간이 있다.
각 노드의 포인터는 다음 노드를 가리킨다.
이중(양방향) 연결 리스트
포인터 공간이 두 개가 있고 각각의 포인터는 앞의 노드와 뒤의 노드를 가리킨다.
원형 연결 리스트
일반적인 연결 리스트에 마지막 노드와 처음 노드를 연결시켜 원형으로 만든 구조이다.
현재 챕터에서는 단일 연결 리스트에 다루고 다음 챕터에서 이중 연결 리스트에 대해 다룬다.
연결 리스트(Linked List)를 자바스크립트로 구현하는 연습을 하였다. 구현을 하면서 배열의 메서드도 공부했던 과정처럼 만들어지는 것 같았다. while 문을 언제까지 실행하는 것을 정하는 것이 조금 까다로웠지만 구현을 하고 나니 많은 공부가 되었다. 블로그를 참고하였는데 참고하면서 최대한 의미를 파악하고 나의 방식으로 다시 코드를 구현하도록 노력했다. 연결 리스트가 앞으로 얼마나 많이 사용할지는 모르겠지만 오늘 배운 내용이 자료 구조를 공부할 때 많은 도움이 되었으면 한다. 연결 리스트는 다른 자료 구조를 구현하는데 많이 사용하기 때문에 기본이라고 생각한다. 머리가 살짝 지끈거리다.🤣