JavaScript의 배열은 항목을 추가하고 제거하여 수정하기가 매우 쉽습니다. 대부분의 언어 배열이 고정 크기이고 크기를 조정하려면 복잡한 작업이 필요하다는 사실을 다소가립니다. JavaScript를 사용하면 성능이 떨어지는 배열 코드를 쉽게 작성할 수 있습니다. 이것은 질문으로 이어집니다.
배열 성능과 관련하여 JavaScript 구현에서 어떤 성능 (큰 O 시간 복잡도 측면에서)을 기대할 수 있습니까?
모든 합리적인 JavaScript 구현에는 다음과 같은 큰 O가 있다고 가정합니다.
- 액세스-O (1)
- 추가-O (n)
- 준비중-O (n)
- 삽입-O (n)
- 삭제-O (n)
- 스와핑-O (1)
JavaScript를 사용하면 new Array(length)
구문을 사용하여 배열을 특정 크기로 미리 채울 수 있습니다 . (보너스 질문 : O (1) 또는 O (n) 방식으로 배열을 생성합니까?) 이것은 기존 배열과 더 비슷하며 사전 크기 배열로 사용하면 O (1) 추가를 허용 할 수 있습니다. 순환 버퍼 로직이 추가되면 앞에 O (1)을 얻을 수 있습니다. 동적 확장 배열을 사용하는 경우 O (log n)는 두 가지 모두에 대한 평균 사례가됩니다.
여기에서 가정 한 것보다 더 나은 성능을 기대할 수 있습니까? 어떤 사양에도 설명되어 있지는 않지만 실제로는 모든 주요 구현이이면에서 최적화 된 어레이를 사용할 수 있습니다. 동적으로 확장되는 어레이 또는 다른 성능 향상 알고리즘이 작동합니까?
추신
이것이 궁금한 이유는 정렬 알고리즘을 연구하고 있기 때문이며, 대부분은 전체적인 큰 O를 설명 할 때 추가 및 삭제가 O (1) 작업이라고 가정하는 것 같습니다.
답변
참고 :이 답변은 2012 년에 정확했지만 오늘날 엔진은 객체와 배열 모두에 대해 매우 다른 내부 표현을 사용합니다. 이 대답은 사실 일 수도 있고 아닐 수도 있습니다.
배열을 사용하여 배열을 구현하는 대부분의 언어와 달리 Javascript 배열은 객체이며 값은 일반 객체 값과 마찬가지로 해시 테이블에 저장됩니다. 이와 같이 :
- 액세스-O (1)
- Appending-Amortized O (1) (때로는 해시 테이블의 크기를 조정해야하며 일반적으로 삽입 만 필요함)
- Prepending-O (n) via
unshift
, 모든 인덱스를 재 할당해야하기 때문입니다. - 삽입-값이 존재하지 않는 경우 상각 된 O (1). O (n) 기존 값을 이동하려는 경우 (예 🙂
splice
. - 삭제-상각 된 O (1)는 값을 제거하고, O (n)는를 통해 인덱스를 재 할당하려는 경우
splice
입니다. - 스와핑-O (1)
일반적으로 dict에서 키를 설정하거나 설정 해제하는 것은 O (1)로 분할되며 인덱스가 무엇이든 상관없이 배열에도 동일하게 적용됩니다. 영향을받는 모든 값을 업데이트해야하기 때문에 기존 값의 번호를 다시 매겨 야하는 모든 작업은 O (n)입니다.
답변
보증
어레이 작업에 대해 지정된 시간 복잡도 보장은 없습니다. 어레이의 성능은 엔진이 선택한 기본 데이터 구조에 따라 다릅니다. 엔진은 또한 다른 표현을 가질 수 있으며 특정 휴리스틱에 따라 전환 할 수 있습니다. 초기 배열 크기는 그러한 휴리스틱 일 수도 있고 아닐 수도 있습니다.
현실
예를 들어, V8은 (오늘부터) 해시 테이블 과 배열 목록 을 모두 사용 하여 배열 을 나타냅니다. 또한 객체에 대한 다양한 표현이 있으므로 배열과 객체를 비교할 수 없습니다. 따라서 배열 액세스는 항상 O (n)보다 낫고 C ++ 배열 액세스만큼 빠를 수도 있습니다. 데이터 구조의 크기에 도달하지 않고 크기를 조정해야하는 경우가 아니면 추가는 O (1)입니다 (O (n)). 준비하는 것이 더 나쁩니다. 삭제는 delete array[index]
엔진이 표현을 변경하도록 강제 할 수 있으므로 (하지 마세요!) 와 같은 작업을 수행하면 훨씬 더 나빠질 수 있습니다 .
조언
숫자 데이터 구조에 배열을 사용하십시오. 그것이 그들이 의미하는 바입니다. 이것이 엔진이이를 최적화하는 것입니다. 희소 배열을 피하십시오 (또는 필요한 경우 성능 저하를 예상). 데이터 유형이 혼합 된 배열을 사용하지 마십시오 (내부 표현이 더 복잡해 지므로 ).
특정 엔진 (및 버전)에 대해 정말로 최적화하려면 소스 코드 에서 절대 답을 확인하십시오 .