Linked List
Node로 이루어져 있는 자료구조이다.
//노드 : 크기가 동적으로 변한다.
//노드 안에는 데이터를 담을 변수, 링크를 담을 변수를 가진다.
//연결리스트의 각 노드는 인덱스를 가지지 않는다.
데이터가 들어올때마다 동적으로 메모리를 할당하는 자료구조이다.
Dynamic Array(동적배열)이라고도 불린다.
크게 세가지의 종류가 있다.
//노드 안의 링크가 어떻게 구성되어있는지에 따라 다르다.
//Singly Linked List - 일방적이다.. 되돌아올 수 없다.
//Doubly Linked List - 양방향
//Circular Linked List - 마지막 노드가 첫 번째 노드를 가리킨다.(계속 회전)
연결리스트가 가지고 있는 method
addToTail(value) - 주어진 값을 연결 리스트의 끝에 추가한다.
remove(value) - 주어진 값을 찾아서 연결을 해제(삭제)합니다
getNodeAt(index) - 주어진 인덱스의 노드를 반환한다.
//값이 아닌 노드 반환한다.
//해당 인덱스에 노드가 없다면 undefined를 반환한다.
contains(value) - 연결리스트에 주어진 값을 가지는 노드의 존재 여부를 반환한다.
indexOf(value) - 주어진 값의 인덱스를 반환한다.
//없을 경우 -1을 반환한다.
코드로 구현해보기
class Node {
constructor(value){
this.value = value;
this.next = null;
}
}//노드의 클래스 선언
class LinkedList {
constructor() {
this.head = null;
this.tail = null;
this.size = 0;
}
addToTail(value) {
let node = new Node(value)
//Node의 인스턴스 생성
if(this.head === null){
this.head = node;
this.tail = node;
this.size++
//head가 없을 때,head와 tail에 노드 추가
} else {
this.tail.next = node;
this.tail = node;
this.size++;
}//head가 있을 때, tail의 다음을 node로 하고 꼬리 추가
}
remove(value) {
let currentNode = this.head
let preNode = this.head
if(this.head === value){
this.head = this.head.next
//value가 head일경우 head제거
}
else {
while(currentNode.value !== value){
preNode = currentNode;
currentNode = currentNode.next;
//head를 유지하고 , head는 다음 head가 된다.
}
preNode.next = currentNode.next;
}
this.size--;
}
getNodeAt(index) {
let count = 0;
let currentNode = this.head;
while(count !== index){//count가 index 될 때까지
count++; //count = count + 1
currentNode = currentNode.next; // 다음노드를 계속 탐색
if(!currentNode){
return undefined;
}
}
return currentNode;
}// 왜 변수로 담아야하지 ?
contains(value) {
let currentNode = this.head;
for(let i = 0; i < this.size; i++){ // size만큼 반복
if(currentNode.value === value){
return true; // value가 있다면 true
}
currentNode = currentNode.next; // 다음노드를 계속 탐색
}
return false; // value가 없다면 false
}// 왜 변수로 담아야하지 ?
indexOf(value) {
let currentNode = this.head;
let count = 0;
while(currentNode.value !== value){
//head의 value가 value와 같아질때까지
count ++; // count = count + 1
currentNode = currentNode.next; // 다음노드를 계속 탐색
if(!currentNode){
return -1; // 없다면 -1 return
}
}
return count; //있다면 count return
}
size() {
return this.size;
}//현재 size를 return
}
<-- 사용해보기 -->
let linkedList = new LinkedList;
linkedList;
//LinkedList {head: null, tail: null, size: 0}
linkedList.addToTail(1);
linkedList.addToTail(2);
linkedList.addToTail(3);
linkedList.addToTail(4);
linkedList;
//LinkedList {head: Node, tail: Node, size: 4}
linkedList.remove(3);
linkedList;
//LinkedList {head: Node, tail: Node, size: 3}
linkedList.getNodeAt(1);
//Node {value: 2, next: Node}
linkedList.getNodeAt(8);
//undefined
linkedList.contains(1);
//true
linkedList.contains(8);
/false
linkedList.indexOf(1);
//0
linkedList.indexOf(2);
//1
linkedList.indexOf(3);
//-1
linkedList.size
//3
연결리스트의 시간복잡도
추가하기 : O(1)
삭제하기 : O(1)
가져오기 : O(n)
//인덱스를 가지지 않기 때문에 전체 연결 리스트를 훑어야 한다.
링크드리스트를 이용한 예
파일 시스템(자료의 추가/삭제가 빈번히 일어날 경우)
'Software Engineering' 카테고리의 다른 글
고차함수(Higher order function) in Javascript (0) | 2020.11.14 |
---|---|
HTML (0) | 2020.11.12 |
Queue in Date structure (0) | 2020.11.07 |
Stack in Date structure (0) | 2020.11.06 |
시간복잡도(Time Complexity) (2) | 2020.11.06 |