-
Notifications
You must be signed in to change notification settings - Fork 1
/
linked-list.js
218 lines (184 loc) · 5.87 KB
/
linked-list.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
// 연결 리스트에서 사용할 ListNode 헬퍼 클래스가 우선 필요합니다.
// 연결 리스트에 추가되는 원소가 바로 Node입니다.
// element가 바로 원소에 해당되며, next 프로퍼티는 다음 노드를 가리키는 포인터입니다.
class ListNode {
constructor(element) {
this.element = element;
this.next = null;
}
}
class LinkedList {
// #length는 내부 프라이빗 프로퍼티로, 연결 리스트에 담긴 원소의 개수입니다.
#length = 0;
constructor(head = null) {
// head는 연결이 시작되는 지점을 참조합니다.
this.head = head;
}
/**
* 리스트 끝에 원소 추가하기
* @param {*} element 추가할 원소
*/
append(element) {
const node = new ListNode(element);
let current;
if (this.head === null) {
// 리스트가 비어있다면,
this.head = node;
} else {
// 끝에 새 원소를 추가하려면 먼저 리스트의 마지막 원소를 찾아야한다.
// 유일한 단서는 첫 번째 원소를 가리키고 있는 참조변수(head)이다.
current = this.head;
// 마지막 원소를 찾을 때까지 루프로 순회한다.
// next가 null이 되는 지점에서 루프를 끝낸다.
while (current.next) {
current = current.next;
}
// current가 마지막 원소이므로
// current.next에 새로 추가한 원소를 가리키게 하면 성공이다.
current.next = node;
}
this.#length++; // 리스트의 크기를 업데이트한다.
}
/**
* 원소의 위치를 기준으로 삭제
* @param {number} position 삭제할 원소의 위치
* @returns 삭제된 원소
*/
removeAt(position) {
// position 값의 유효성을 체크한다. (0부터 length - 1)
if (position > -1 && position < this.#length) {
let current = this.head,
previous,
index = 0;
if (position === 0) {
// 첫 번째 원소를 삭제할 경우
this.head = current.next; // head가 그 다음 요소를 가리키도록 바꿔준다.
} else {
while (index++ < position) {
// 리스트를 원하는 위치까지 루프를 돌린다.
previous = current; // previous로 현재 원소의 바로 이전 원소를 가리킨다.
current = current.next; // current는 항상 리스트의 현재 원소를 가리키는 변수다.
}
// 원소를 삭제하기 위해 previous.next가 current.next를 가리키게 바꿔치기 한다.
previous.next = current.next;
}
this.#length--; // 리스트의 크기를 업데이트한다.
return current.element;
} else {
// 유효한 position이 아니라면 삭제된 원소가 하나도 없음을 알린다.
return null;
}
}
/**
* 임의의 위치에 원소 삽입하기
* @param {number} position 원소를 삽입할 위치의 인덱스
* @param {*} element
*/
insert(position, element) {
// position 값의 유효성을 체크한다. (0부터 length)
if (position > -1 && position <= this.#length) {
const node = new ListNode(element);
let current = this.head,
previous,
index = 0;
if (position === 0) {
// 첫 번째 원소를 추가할 경우
node.next = current;
this.head = node;
} else {
while (index++ < position) {
// 리스트를 원하는 위치까지 루프를 돌린다.
previous = current; // previous로 현재 원소의 바로 이전 원소를 가리킨다.
current = current.next; // current는 항상 리스트의 현재 원소를 가리키는 변수다.
}
node.next = current;
previous.next = node;
}
this.#length++; // 리스트의 크기를 업데이트한다.
return current.element;
} else {
// 유효한 position이 아니라면 리스트에 아무것도 추가되지 않았음을 알린다.
return false;
}
}
/**
* 원소 값을 인자로 받아 리스트에서 해당 원소의 인덱스를 반환한다.
* @param {*} element
*/
indexOf(element) {
let current = this.head,
index = 0;
while (current) {
if (element === current.element) {
return index;
}
index++;
current = current.next;
}
return -1;
}
/**
* removeAt과 indexOf 메소드를 활용하여 원소의 값을 기준으로 삭제
* @param {*} element 삭제할 원소의 값
*/
remove(element) {
const index = this.indexOf(element);
return this.removeAt(index);
}
/**
* @returns 리스트가 비어있는지 여부
*/
isEmpty() {
return this.#length === 0;
}
/**
* @returns 리스트의 크기
*/
size() {
return this.#length;
}
/**
* 리스트를 비운다.
*/
clear() {
this.head = null;
}
/**
* 리스트를 문자열로 변환한다.
*/
toString() {
let current = this.head,
string = "";
while (current) {
string += current.element;
current = current.next;
}
return string;
}
/**
* @returns head
*/
getHead() {
return this.head;
}
}
// 리스트 인스턴스 생성
const list = new LinkedList();
// 리스트에 원소를 추가
list.append("hello");
list.append("world");
list.append("javascript");
// 리스트를 문자열로 변환
console.log(list.removeAt(2)); // javascript
// 연결 리스트의 크기를 확인
console.log(list.size()); // 2
// 리스트를 문자열로 변환
console.log(list.toString()); // helloworld
// 원소 값을 인자로 받아 리스트에서 해당 원소의 인덱스를 반환
console.log(list.indexOf("hello")); // 0
console.log(list.indexOf("world")); // 1
// 리스트가 비어있는지 체크
console.log(list.isEmpty()); // false
// head를 반환
console.log(list.getHead()); // ListNode {element: 'hello', next: ListNode}
list.size();