상각 상각 시간


답변:


776

상각 된 시간은 간단한 용어로 설명됩니다.

작업이 백만 번 말하면 실제로 작업의 최악의 경우 또는 가장 좋은 경우에 신경 쓰지 않습니다. 관심있는 것은 백만 번 작업을 반복 할 때 총 시간이 얼마나 걸리는가입니다. .

따라서 "한 번에 한 번"이 느리게 희석 될 정도로 드물기 만하면 작업이 한 번에 매우 느리게 진행되는지는 중요하지 않습니다. 본질적으로 상각 된 시간은 "작업이 많은 경우 작업 당 평균 평균 시간"을 의미합니다. 상각 시간이 일정 할 필요는 없습니다. 선형 및 대수 상각 시간 또는 기타 다른 것을 가질 수 있습니다.

반복적으로 새 항목을 추가하는 동적 배열의 매트를 예로 들어 보겠습니다. 일반적으로 항목을 추가하는 데 일정한 시간이 걸립니다 (즉, O(1)). 그러나 어레이가 가득 찰 때마다 두 배의 공간을 할당하고 데이터를 새 지역에 복사하고 이전 공간을 비 웁니다. 일정 시간에 할당 및 해제를 가정하면이 확대 프로세스는O(n) n이 어레이의 현재 크기 인 시간 .

따라서 확대 할 때마다 마지막 확대보다 약 두 배의 시간이 걸립니다. 그러나 당신은 또한 그것을하기 전에 두 배나 기다렸습니다! 따라서, 각각의 확대 비용은 삽입물 사이에서 "확산"될 수있다. 이는 장기적으로 m 항목을 배열 에 추가하는 데 걸리는 총 시간 이 O(m)이므로 상각 된 시간 (즉, 삽입 당 시간)은임을 의미 O(1)합니다.


61
표기법에 대한 참고 사항 : O (n)의 상각 상수 실행 시간은 O (n)과 달리 O (n) +로 작성됩니다. 더하기 부호를 추가하면 실행 시간이 O (n) 인 것은 아니며 실제로 해당 실행 시간을 초과 할 수 있음을 나타냅니다.
Jeffpowrs

1
공간 할당 측면에서 힙에서 나온 공간입니까?
committedandroider

3
나는 "당신은 정말로 최악의 상황에 관심이 없다"는 것에 동의하지 않는다. 유스 케이스에 따라 다릅니다. 결국 인용 된 1 백만 개의 연산 결과에만 관심이 있다면 실제로 신경 쓰지 않아도됩니다. 그러나 실시간 앱인 경우 지속적으로 데이터를 읽고 응답하는 경우, 해당 데이터를 처리하는 데 1 백만 개의 데이터 항목이 처리 될 때마다 정상보다 백만 배 더 오래 걸리면 큰 문제가 발생할 수 있습니다!
Kai Petzke

2
@Jeffpowrs 나는 O (n)이 선형 시간이고 O (1)이 일정한 시간 이라고 생각 했습니다 . 그렇다면 O (1) +는 일정한 시간을 상각하고 O (n) +는 선형적인 시간을 상각한다는 의미 입니까?
John Meyer

1
@JohnMeyer 예.
Artelius

55

시간이 지남에 따라 최악의 시나리오는 기본적으로 O (1) 또는 일정 시간으로 설정됩니다. 일반적인 예는 동적 배열입니다. 새 항목에 이미 메모리를 할당 한 경우 추가하면 O (1)이됩니다. 할당하지 않은 경우 현재 금액의 두 배를 할당하여 할당합니다. 이 특정 삽입 할 수 없습니다 O (1), 그러나 다른 사람보다는 뭔가.

중요한 것은 알고리즘이 일련의 작업 후에 고가의 작업이 상각되어 전체 작업 O (1)을 렌더링한다는 것을 보장한다는 것입니다.

더 엄격한 용어로

상수 c가 있습니다. 모든 길이 L의 (a 비싼 연산으로 끝나는 하나) 동작의 순서, 시간 C 이하인 * L (감사 라팔 Dowgird )


11
"충분히 많은 양의 작업 후"-상각 된 상각 시간에는이 조건이 필요하지 않습니다. 위한되도록 상수 C를가 모든 길이 L의 (a 비싼 연산으로 끝나는 하나) 동작의 순서, 시간 C * L 이하인된다.
Rafał Dowgird

금액 은 어디 에서 오는 금액의 두 배를 할당 합니까? 하나의 항목을 할당해서는 안됩니까? 아니면 가설적인 예입니까?
talekeDskobeDa

@talekeDskobaDa 이것은 임의의 예가 아니라 널리 사용되는 알고리즘입니다. 제안한대로 한 번에 한 항목에 공간을 할당 한 경우 단일 값을 삽입하기위한 상각 시간은 O (n)입니다. 공간이 꽉 차면 공간을 두 배로 늘리면 할부 상환 시간이 훨씬 좋습니다 (O (1)). 분명히, 한 번에 한 항목에 공간을 할당 할 때 발생하는 문제는 배열에 큰 연속 공간 블록이 필요하다는 것입니다. OS에서 더 큰 블록을 얻는 것은 쉽지만, 바로 뒤에 다른 데이터가 저장되어 있기 때문에 기존 블록을 확장하는 것이 불가능한 경우가 많습니다.
Artelius

23

직관적 인 사고 방식을 개발하려면 동적 배열 (예 std::vector: C ++) 에 요소를 삽입하는 것이 좋습니다. 배열에 N 개의 요소를 삽입하는 데 필요한 연산 수 (Y)의 종속성을 보여주는 그래프를 그려 봅시다.

음모

블랙 그래프의 세로 부분은 배열을 확장하기 위해 메모리 재 할당에 해당합니다. 여기서 우리는이 의존성이 대략 선으로 표현 될 수 있음을 알 수 있습니다. 그리고이 선 방정식은 Y=C*N + b( 우리의 경우 C상수, b= 0입니다). 따라서 우리는 C*N배열에 N 개의 요소를 추가 하기 위해 평균적으로 작업 을 소비 하거나 C*1하나의 요소를 추가하는 작업 (강조 된 상수 시간) 을 소비해야한다고 말할 수 있습니다 .


14

3 번 반복해서 읽은 후 Wikipedia 설명이 유용하다는 것을 알았습니다.

출처 : https://en.wikipedia.org/wiki/Amortized_analysis#Dynamic_Array

"동적 배열

동적 어레이에 대한 푸시 작업의 상각 분석

Java의 ArrayList와 같이 더 많은 요소가 추가되면 크기가 커지는 동적 배열을 고려하십시오. 크기가 4 인 동적 배열로 시작한 경우 4 개의 요소를 밀어 넣는 데 일정한 시간이 걸립니다. 그러나 배열에 다섯 번째 요소를 밀어 넣으면 배열이 현재 크기의 두 배인 새 배열을 작성하고 (8) 이전 요소를 새 배열에 복사 한 다음 새 요소를 추가해야하므로 시간이 더 오래 걸립니다. 다음 세 번의 푸시 작업도 마찬가지로 일정한 시간이 걸리며, 이후의 추가 작업에는 어레이 크기를 두 배로 느리게 두 번 증가시켜야합니다.

일반적으로 임의의 수의 푸시 n을 크기 n의 배열로 고려할 경우 크기 배가 연산을 수행하는 데 O (n) 시간이 걸리는 마지막 것을 제외하고는 푸시 작업에 일정한 시간이 걸리는 것을 알 수 있습니다. 총 n 개의 연산이 있었으므로이 평균을 취하여 동적 배열에 요소를 푸시하는 데 걸리는 시간은 O (n / n) = O (1), 상수 시간입니다. "

간단한 이야기로 이해 :

돈이 많다고 가정하자. 그리고 당신은 그들을 방에 쌓아두기를 원합니다. 그리고 현재 또는 미래에 필요한만큼 손과 다리가 길다. 그리고 한 방에 모두 채워야하므로 잠그기가 쉽습니다.

따라서 방의 끝 / 구석으로 가서 쌓아 올리십시오. 쌓아 올리면 천천히 공간이 부족합니다. 그러나 채울 때 쉽게 쌓을 수있었습니다. 돈을 가지고 돈을 넣어. 쉬운. O (1)입니다. 우리는 이전 돈을 옮길 필요가 없습니다.

공간이 부족 해지면 우리는 더 큰 다른 방이 필요합니다. 여기에는 하나의 방만있을 수 있으므로 하나의 자물쇠 만 가질 수 있으므로 문제가 있습니다. 그 방에있는 기존의 모든 돈을 새로운 더 큰 방으로 옮길 필요가 있습니다. 따라서 모든 돈을 작은 방에서 더 큰 방으로 옮기십시오. 즉, 모두 다시 쌓으십시오. 따라서 우리는 이전의 모든 돈을 옮길 필요가 있습니다. 따라서 O (N)입니다. (N이 이전 돈의 총 돈이라고 가정)

다시 말해 N까지는 쉬웠지만 한 번만 조작 할 수 있었지만 더 큰 방으로 이사해야 할 때는 N 번을했습니다. 다시 말해서, 우리가 평균을 내면 시작 부분에 1 개의 삽입물이 있고 다른 방으로 이동하면서 1 개의 이동이 더 있습니다. 총 2 개의 작업, 한 번의 삽입, 한 번의 이동.

작은 방에서도 N이 1 백만이라고 가정하면 N (1 백만)에 비해 2 개의 연산은 실제로 비교할 수있는 숫자가 아니므로 상수 또는 O (1)로 간주됩니다.

우리가 더 큰 다른 방에서 위의 모든 작업을 수행하고 다시 움직일 필요가 있다고 가정합니다. 여전히 동일합니다. 예를 들어 N2 (예 : 10 억)는 더 큰 방에서 새로운 금액의 돈입니다.

그래서 우리는 N2를 가지고 있습니다 (이것은 모두 작은 방에서 더 큰 방으로 이동하기 때문에 이전의 N을 포함합니다)

우리는 여전히 2 개의 작업 만 필요합니다. 하나는 더 큰 방에 삽입하고 다른 하나는 더 큰 방으로 이동합니다.

따라서 N2 (10 억)의 경우에도 각각 2 개의 작업입니다. 다시는 아무것도 아닙니다. 따라서 상수 또는 O (1)

따라서 N이 N에서 N2로 증가함에 따라 그다지 중요하지 않습니다. 여전히 일정하거나 각 N에 필요한 O (1) 연산입니다.


이제 N이 1로 매우 작고 돈의 수가 적고 매우 작은 방이 있다고 가정합니다.

방에 돈을 채우 자마자 방이 가득 찼습니다.

더 큰 방에 갈 때 총 2 개의 돈을 더 넣을 수 있다고 가정하십시오. 즉, 이전에 돈을 옮겼고 1 개가 더 갔다는 것을 의미합니다. 그리고 다시 채워집니다.

이런 식으로, N은 느리게 성장하고 있으며 우리가 이전 방에서 모든 돈을 옮기고 있기 때문에 더 이상 O (1)는 아니지만 1 개만 더 들어갈 수 있습니다.

100 번이 지나면 새로운 방은 이전의 돈과 100 개의 돈을 수용 할 수 있습니다. 이것은 O (N)입니다. O (N + 1)이 O (N)이기 때문에, 즉 100 또는 101의 정도는 동일합니다. 이전 이야기와는 달리 수백에서 수백억에 달합니다. .

따라서 이것은 돈 (변수)을 위해 공간 (또는 메모리 / RAM)을 할당하는 비효율적 인 방법입니다.


따라서 좋은 방법은 2의 거듭 제곱으로 더 많은 공간을 할당하는 것입니다.

1 번째 방 크기 = 1 번 계산
2 번째 방 크기 = 4 번 계산
3 번째 방 크기 = 8 번 계산 맞음
4 번째 방 크기 = 16 번 계산 맞음
5 번째 방 크기 = 32 번 계산 맞음
6 번째 방 크기 = 맞음 64 개의 돈
7 번째 방 크기 = 128 개의 돈
크기 8 번째 방 크기 = 256 개의 돈
크기 9 번째 방 크기 = 512 개의 돈
크기 10 번째 방 크기 = 1024 개의 돈
11 번째 방 크기 = 2,048 개의 돈 맞음
. ..
16 번째 방 크기 = 65,536 개의 돈에 해당
...
32 번째 방 크기 = 4,294,967,296에 해당하는 돈
...
64 번째 방 크기 = 18,446,744,073,709,551,616에 해당

왜 이것이 더 낫습니까? RAM의 메모리 양과 비교할 때 처음에는 느리게 성장하고 나중에는 더 빨리 커지기 때문입니다.

첫 번째 경우는 좋지만 돈당 수행 할 총 작업량이 고정되어 있고 (2) 방 크기 (N)와 비교할 수 없기 때문에 초기 단계에서 수행 한 방이 너무 많을 수 있기 때문에 도움이됩니다. 우리가 처음에 전혀 저축 할 돈이 많은지에 따라 우리가 완전히 사용하지 않을 수도있는 큰 (백만).

그러나 마지막 경우 2의 거듭 제곱은 RAM의 한계에서 커집니다. 따라서 2의 거듭 제곱이 증가함에 따라 Armotized 분석은 일정하게 유지되며 오늘날의 제한된 RAM에 적합합니다.


2
아, 그래서 O (최악의 경우 / 작업 수)입니다. 이 답변이 가장 좋습니다.
nucleartide

1

위의 설명은 여러 작업에 대해 "평균"을 취한다는 아이디어 인 Aggregate Analysis에 적용됩니다. 은행가 방법 또는 물리학 자 상각 법 분석에 어떻게 적용되는지 잘 모르겠습니다.

지금. 정답이 확실하지 않습니다. 그러나 그것은 물리학 자 + 뱅커의 두 가지 방법의 원칙적 조건과 관련이 있습니다.

(상각비 상각액)> = (실제 운영비의 합).

내가 직면하는 가장 큰 어려움은 할부 상환 작업 비용이 일반 점근 비용과 다르다는 점을 감안할 때 상각 비용의 중요성을 어떻게 평가할 수 있는지 잘 모르겠습니다.

누군가 누군가가 상각 비용을 줄 때, 나는 정상적인 상각 비용과 동일하지 않다는 것을 알고 있습니다. 그렇다면 상각 비용에서 어떤 결론을 도출해야합니까?

일부 작업이 과충전되고 다른 작업이 과소 청구되는 경우가 있기 때문에 개별 작업의 상각 비용을 인용하면 의미가 없다는 가설이있을 수 있습니다.

예를 들어, 피보나치 힙의 경우, Decreasing-Key의 할부 상환 비용을 O (1)로 인용하는 것은 의미가 없습니다.

또는

우리는 다음과 같이 할부 상환 비용에 대한 이유에 대한 또 다른 가설을 가질 수 있습니다.

  1. 비싼 작업이 MULTIPLE LOW-COST 작업보다 우선한다는 것을 알고 있습니다.

  2. 분석을 위해 저비용 운영을 과충전 할 것인데, 그 비용은 변하지 않습니다.

  3. 이러한 저비용 운영으로 비용이 많이 드는 운영비를 증명할 수 있습니다.

  4. 따라서 나는 운영 비용의 ASYMPTOTIC-BOUND를 개선 / 감소시켰다.

따라서 상각 비용 분석 + 상각 비용 범위는 이제 고가의 작업에만 적용 할 수 있습니다. 값싼 작업은 일반 점근 비용과 동일한 점근 비용이 있습니다.


재미있는 생각.
Lonnie Best

0

"전체 함수 호출 수"를 "모든 해당 호출에 걸린 총 시간"으로 나누어 모든 함수의 성능을 평균화 할 수 있습니다. 각 호출마다 더 오래 걸리는 기능조차도 이러한 방식으로 평균화 할 수 있습니다.

따라서 수행하는 기능의 본질 Constant Amortized Time 이 "평균 시간"이 통화 수가 계속 증가함에 따라 초과되지 않는 한도에 도달한다는 것입니다. 특정 통화는 성능이 다를 수 있지만 장기적으로이 평균 시간이 계속 커지는 것은 아닙니다.

이것은에서 수행하는 무언가의 필수 장점입니다 Constant Amortized Time.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.