문제

Vector(Java 사용자의 경우 ArrayList)의 고전적인 구현이 확장할 때마다 내부 배열 크기를 3배 또는 4배로 늘리는 대신 두 배로 늘리는 이유는 무엇입니까?

도움이 되었습니까?

해결책

벡터에 삽입하는 평균 시간을 계산할 때는 비 성장 삽입물과 증가하는 인서트를 허용해야합니다.

삽입 할 총 작업 수를 호출하십시오 N 항목 영형, 및 평균 영형평균.

삽입 한 경우 N 아이템, 그리고 당신은 한 가지 요인 만 자랍니다 필요에 따라 거기에 있습니다 영형 = n + σa 0 <i <1 + lnN 운영. 최악의 경우 사용합니다 1/a 할당 된 스토리지의.

직관적으로, a = 2 당신이 가진 최악의 의미 영형 = 2n, 그래서 영형평균 O (1), 최악의 경우 할당 된 스토리지의 50%를 사용합니다.

더 큰 경우 , 당신은 더 낮습니다 영형, 그러나 더 많은 낭비 스토리지.

더 작은 , 영형 더 크지 만 스토리지를 많이 낭비하지 않습니다. 기하학적으로 성장하는 한 여전히 O (1) 상각 삽입 시간이지만 상수는 더 높아집니다.

성장 인자 1.25 (빨간색), 1.5 (시안), 2 (검은 색), 3 (파란색) 및 4 (녹색)의 경우,이 그래프는 지점과 평균 크기 효율 (크기/할당 공간의 비율; 더 우수함)을 보여줍니다. 400,000 개의 항목을 삽입하기 위해 오른쪽에 왼쪽 및 시간 효율성 (삽입 / 작업 비율; 더 좋습니다). 크기 조정 직전에 모든 성장 인자에 대해 100% 공간 효율에 도달합니다. 사례 a = 2 시간 효율은 25%와 50%사이의 시간 효율성과 약 50%의 공간 효율을 보여줍니다. 이는 대부분의 경우에 좋습니다.

space and time efficiency graph - C like implementations

Java와 같은 Runtimes의 경우 배열이 0으로 채워 지므로 할당 할 작업 수는 배열의 크기에 비례합니다. 이를 고려하면 시간 효율 추정치 간의 차이가 줄어 듭니다.

space and time efficiency graph - Java like implementations

다른 팁

배열 (또는 문자열)의 크기를 기하 급수적으로 두 배로 늘리는 것은 배열에 충분한 셀을 갖는 것과 너무 많은 메모리를 낭비하는 사이의 좋은 타협입니다.

10 가지 요소로 시작한다고 가정 해보십시오.

1 - 10
2 - 20
3 - 40
4 - 80
5 - 160

크기를 3 배로 늘리면 너무 빨리 자랍니다.

1 - 10
2 - 30
3 - 90
4 - 270
5 - 810

실제로 당신은 아마도 10 번 또는 12 번 성장할 것입니다. 트리플을 트리플하면 7 ~ 8 배를 할 수 있습니다. 재 할당을위한 런타임 히트는 걱정할만큼 충분히 작지만 필요한 크기를 완전히 과도하게 휘젓 가능성이 높습니다.

비정상적인 크기의 메모리 블록을 할당한다면, 그 블록이 처리 될 때 (크기를 조정하거나 GC가 얻기 때문에) 메모리에 특이한 크기의 구멍이있어 두통이 발생할 수 있습니다. 메모리 관리자. 따라서 일반적으로 두 가지 힘으로 메모리를 할당하는 것이 선호됩니다. 경우에 따라 기본 메모리 관리자는 특정 크기의 블록 만 제공하며 이상한 크기를 요청하면 다음 큰 크기로 반올림됩니다. 따라서 470 대를 요구하는 대신, 어쨌든 512를 돌려받은 다음 요청한 470을 모두 사용하면 다시 조화를 이루기 위해 512를 시작하도록 요청할 수도 있습니다.

다수의 타협은 타협입니다. 너무 크게 만들고 너무 많은 기억을 낭비하십시오. 너무 작게 만들고 재 할당 및 복사를 위해 많은 시간을 낭비합니다. 두 배가 된 것이 작동하고 구현하기가 매우 쉽기 때문에 두 배가 있다고 생각합니다. 또한 1.5를 동일하게 승수로 사용하는 독점적 인 STL과 같은 라이브러리를 보았습니다.

Java 관련 구현에 대해 문의하는 경우 벡터 그리고 배열목록, 각 확장마다 반드시 두 배로 증가할 필요는 없습니다.

벡터용 Javadoc에서:

각 벡터는 다음을 유지하여 스토리지 관리를 최적화하려고 시도합니다. capacity 그리고 capacityIncrement.용량은 항상 최소한 벡터 크기만큼 큽니다.구성 요소가 벡터에 추가됨에 따라 벡터의 저장 공간이 크기만큼 커지기 때문에 일반적으로 더 큽니다. capacityIncrement.응용 프로그램은 많은 수의 구성 요소를 삽입하기 전에 벡터의 용량을 늘릴 수 있습니다.이렇게 하면 증분 재할당량이 줄어듭니다.

Vector의 생성자 중 하나를 사용하면 Vector의 초기 크기와 용량 증가분을 지정할 수 있습니다.Vector 클래스는 다음도 제공합니다. ensureCapacity(int minCapacity) 그리고 setSize(int newSize), 벡터의 최소 크기를 수동으로 조정하고 직접 벡터 크기를 조정합니다.

ArrayList 클래스는 매우 유사합니다.

ArrayList 인스턴스에는 용량이 있습니다.용량은 목록의 요소를 저장하는 데 사용되는 배열의 크기입니다.항상 최소한 목록 크기만큼 큽니다.ArrayList에 요소가 추가되면 용량이 자동으로 늘어납니다.요소를 추가하면 상각 시간 비용이 일정하다는 사실 외에는 성장 정책의 세부 사항이 지정되지 않습니다.

애플리케이션으로 용량을 늘릴 수 있습니다. ArrayList verifyCapacity 작업을 사용하여 많은 수의 요소를 추가하기 전에 인스턴스를 삭제하세요.이렇게 하면 증분 재할당량이 줄어들 수 있습니다.

벡터의 일반적인 구현에 대해 묻는 경우 크기 증가와 절충 정도를 선택하는 것보다 좋습니다.일반적으로 벡터는 배열의 지원을 받습니다.배열은 고정된 크기입니다.벡터가 가득 차서 크기를 조정하려면 배열의 모든 요소를 ​​더 큰 새 배열에 복사해야 한다는 의미입니다.새 배열을 너무 크게 만들면 절대 사용하지 않을 메모리를 할당하게 됩니다.너무 작으면 이전 배열의 요소를 더 큰 새 배열로 복사하는 데 시간이 너무 오래 걸릴 수 있습니다. 이 작업은 자주 수행하고 싶지 않습니다.

개인적으로, 나는 그것이 중재 선택이라고 생각합니다. 다중 크기 만 (1+e)로 두 배로 늘리는 대신베이스 E를 사용할 수 있습니다.)

벡터에 많은 양의 변수를 추가하려는 경우, 몇 가지만 저장 해야하는 경우 플립 측면에서 높은베이스를 갖는 것이 유리할 것입니다. AVG의 회원은 낮은 기지가 괜찮고 오버 헤드의 양을 줄여서 속도를 높입니다.

기본 2는 타협입니다.

ALL이 동일한 큰 O 성능 프로파일을 가지고 있기 때문에 두 배로 vs를 두 배로 늘리거나 두 배로 늘리는 성능의 이유가 없습니다. 그러나 절대적으로 두 배가되는 것은 일반 시나리오에서 더 많은 공간 효율적인 경향이 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top