배열의 끝 지점의 삽입과 삭제를 다루는 push
, pop
함수를 이용한다.
배열의 첫 지점에서 삽입과 삭제를 다루는 unshift
, shift
함수를 이용할 수도 있다.
후입선출의 규칙만 지킨다면 어느방향으로 하던 상관은 없지만
unshift
, shift
는 배열에서는 첫번째 인자를 삽입 삭제할 경우 모든 요소들이 다 움직여야하기 때문에 시간복잡도가 O(N)
이라 비효율적이다.
push
, pop
의 경우는 O(1)
상수시간이기 때문에 이것을 사용하는게 더 낫다.
인덱스에 접근하는 것이 아니라 그냥 삽입했을 때 순서에 기반해서 정보를 다루기만 하면 되기 때문에 배열에 사용되는 많은 메소드들이 필요가 없다.
단일 연결리스트에서는 한쪽 방향으로만 연결되는 특성 때문에 맨 마지막에 요소를 삽입하거나 삭제할 때 앞에서부터 검색해야 함으로 push, pop보단 unshift,shift 로 처음요소를 삽입하고 제거하는것이 낫다.
후입선출의 규칙은 동일하다!
class Stack {
constructor(){
this.first = null;
this.last = null;
this.size=0;
}
push(val){
//앞에 삽입
const addData = new Node(val);
if(this.size ===0){
this.first = addData;
this.last = addData;
}
else{
addData.next = this.first;
this.first = addData;
}
return ++this.size;
}
pop(){
//앞을 제거
if(this.size ===0 ) return null;
let deleteData = this.first;
if(this.first===this.last){
this.last = null;
}
this.first = this.first.next;
this.size--;
return deleteData;
}
}
class Node {
constructor(val){
this.val = val;
this.next = null;
}
}
class Queue {
constructor(){
this.first = null;
this.last = null;
this.size=0;
}
enqueue(val){
const newNode = new Node(val);
if(this.size ===0){
this.first = newNode;
this.last = newNode;
}
else{
this.last.next = newNode;
this.last = newNode;
}
return ++this.size;
}
dequeue(){
if(this.size ===0 ) return null;
let deleteData = this.first;
if(this.first===this.last){
this.last = null;
}
this.first = this.first.next;
this.size--;
return deleteData;
}
}
class Node {
constructor(val){
this.val = val;
this.next = null;
}
}
스택과 큐에서는 탐색, 인덱스 위치를 사용해서 접근하는 것이 필요 없다.
삽입과 제거 후입선출, 선입선출을 잘 지키는 것이 중요하다.
연결리스트 - 삽입 O(1) / 삭제 O(1)
배열 - 삽입 O(1) / 삭제 O(1)
복잡도는 상수시간이지만 스택에서는 삽입 삭제만 필요함으로 배열처럼 많은 메서드가 필요없다.
연결리스트의 경우는 코드를 많이 구현해야하기 때문에, 좋은 방법이지만
빠르게 작성을 해야할 경우 배열을 사용하는 것이 낫다.
연결리스트 - 삽입 O(1) / 삭제 O(1)
배열 - 삽입 O(1) / 삭제 O(N) 혹은 반대