배열과 연결 리스트의 차이
배열(Array)와 연결 리스트(Linked List)는 둘 다 데이터 요소들을 저장하고 관리하는 자료 구조이지만 각각의 특징과 동작 방식은 다르다.
배열 (Array):
- 일련의 연속적인 메모리 공간에 데이터를 저장하는 자료 구조
- 원소들은 인덱스(0부터 시작)를 사용하여 접근
- O(1) 시간에 특정 인덱스의 원소에 접근 가능
- 크기가 고정되어 있으며, 원소를 추가하거나 삭제할 때 배열의 크기를 변경해야 할 수 있다. 이로 인해 삽입과 삭제 연산이 시간이 더 걸릴 수 있다.
- 메모리 상에 연속적으로 배치되어 있기 때문에 접근 속도가 빠르며 캐시 효율이 좋다.
- 빠른 접근 속도와 인덱스 기반의 접근이 필요한 경우에 유용
- 데이터의 크기가 고정이거나 크기 변화가 적을 때 적합
연결 리스트 (Linked List):
- 노드라 불리는 개별적인 객체들로 이루어진 구조로, 각 노드는 데이터와 다음 노드를 가리키는 포인터를 포함한다.
- 각 노드는 메모리 상에 연속되지 않아도 되므로, 동적으로 크기를 조절할 수 있다. 원소를 추가하거나 삭제할 때 다른 노드들과의 연결만 수정하면 된다.
- 순차적으로 모든 노드를 탐색해야 하므로, 특정 위치에 접근하는 데 O(n) 시간이 소요
- 포인터를 사용하기 때문에 추가 메모리 사용이 필요
- 삽입과 삭제가 빈번한 경우에 유용
- 데이터의 크기가 동적으로 변할 때 적합합니다. 메모리 공간이 연속적으로 필요하지 않으므로 크기에 제한이 없다.
만드는 법
기본적으로 노드(Node)라 불리는 객체를 정의하고, 이 노드들을 연결하여 연결 리스트를 구성한다. 각 노드는 데이터와 다음 노드를 가리키는 포인터를 포함하게 된다.
1. 노드(Node) 정의
class Node {
constructor(data) {
this.data = data // 현재 노드의 데이터
this.next = null // 다음 노드를 가리키는 포인터
}
}
2. 연결 리스트 생성과 노드 추가
class LinkedList {
constructor() {
this.head = null // 연결 리스트의 첫 번째 노드를 가리키는 포인터
}
append(data) {
const newNode = new Node(data)
if (!this.head) {
this.head = newNode
return
}
let current = this.head
while (current.next) {
current = current.next
}
current.next = newNode
}
}
위에서 정의한 Node 클래스와 LinkedList 클래스를 사용하여 연결 리스트를 만들고 노드를 추가할 수 있다.
3. 연결 리스트 사용 예시
const linkedList = new LinkedList()
linkedList.append(10)
linkedList.append(20)
linkedList.append(30)
// 연결 리스트 출력
function printLinkedList(list) {
let current = list.head
while (current) {
console.log(current.data)
current = current.next
}
}
printLinkedList(linkedList) // 출력: 10, 20, 30
이 예시에서 LinkedList 클래스는 노드를 추가하고, printLinkedList 함수는 연결 리스트의 내용을 출력한다. 노드 추가시에는 기존의 마지막 노드의 next 포인터를 새로운 노드로 설정하여 연결하게 된다.