2011-02-01 5 views
5

고정 크기 순환 버퍼 (배열로 구현 됨)가 있습니다. 초기화시 버퍼가 지정된 최대 수의 요소로 채워 지므로 서클의 현재 위치를 추적하기 위해 단일 위치 인덱스.고정 크기 순환 버퍼의 인덱스를 효율적으로 줄이는 방법

순환 버퍼의 요소에 액세스하는 효율적인 방법은 무엇입니까?

int GetElement(int index) 
{ 
    if (index >= buffer_size || index < 0) 
    { 
     // some code to handle the case 
    } 
    else 
    { 
     // wrap the index 
     index = end_index + index >= buffer_size ? (index + end_index) - buffer_size : end_index + index; 
    } 

    return buffer[index]; 
} 

일부 정의 :
end_index 즉시 원의 마지막 요소 (그것은 또한 START_INDEX, 또는 첫 번째 요소의 같은 간주됩니다 후 요소의 인덱스입니다 여기에 내 현재의 솔루션입니다 동호회).
buffer_size은 버퍼의 최대 크기입니다.

+0

이 때 BUFFER_SIZE 같지 END_INDEX하지 않습니다 (당신이 음수 작업해야 가정)? –

+0

@Fred, 순환 버퍼에 요소를 추가하면 ... buffer_size를 지나갈 때마다 색인이 래핑됩니다. – Kiril

+0

@ 리릭 : 뭔가 빠뜨린 것 같습니다. –

답변

10

버퍼가 항상 2의 제곱수인지 확인하고 맨 위 비트를 마스크 아웃하십시오.

+1

그래서 ... modulus/modulo? : P –

+4

@ Johnatan : 조기에 최적화 된 모듈러스 연산, 예. – delnan

+0

@delnan 나는 조숙하게 대해 모른다. 개인적으로는 모듈을 사용하지만 실제로 배열은이 두 가지의 힘이되는 것이 일반적입니다. – corsiKa

5

가 프로세서에 다소 의존 하겠지만, 그것은 return (end_index + index) % buffer_size;

+0

** (1) ** end_index는'buffer_size'와 같지 않습니다 (0 인덱스 배열)? 이 점을 염두에두고'a (n + 4) % n;을 반환하는 것으로 단순화하자 -'a = -5'와'n = 4 '이면'(a + n)'은 여전히 ​​-1이다. (즉, a <-n에 대해 실패한다). – mpen

+1

@ 마크 : 원래의 코드는 음수의 가능성을 암시하지만, 일반적으로 허용되지는 않습니다.하지만 부호없는 타입을 사용하는 것이 좋습니다. –

+0

오 ... 내 상황이 다름 같아. 나는 종종 마지막 요소를 의미하기 위해 -1을 사용합니다. – mpen

0

FWIW 같은 적어도 가치가 시도하는 것을 아마, 당신은 병렬 배열 할 항상 수 : 정말, 난 항상했습니다, i = next[i];

하지만를 이 이제까지 상당한 성능 문제가되는 경우 i++; if (i >= n) i = 0; 또는

i = (i+1) % n;에 관계없이, 내가 정말 놀랄 것 : 그냥이 완료.

4

I tested all 3 versions :

// plain wrap 
public static int WrapIndex(int index, int endIndex, int maxSize) 
{ 
    return (endIndex + index) > maxSize ? (endIndex + index) - maxSize : endIndex + index; 
} 

// wrap using mod 
public static int WrapIndexMod(int index, int endIndex, int maxSize) 
{ 
    return (endIndex + index) % maxSize; 
} 

// wrap by masking out the top bits 
public static int WrapIndexMask(int index, int endIndex, int maxSize) 
{ 
    return (endIndex + index) & (maxSize - 1); 
} 

의 실적은 (틱) :

Plain: 25 Mod: 16 Mask: 16 (maxSize = 512) 
Plain: 25 Mod: 17 Mask: 17 (maxSize = 1024) 
Plain: 25 Mod: 17 Mask: 17 (maxSize = 4096) 

를 그것의 크기에 어떤 제한을 필요로하지 않기 때문에 그래서, 계수가 더 나은 선택 인 것 같다 완충기. 내가 함께 왔어요 최저

11

은 다음과 같습니다

public static int Wrap(int index, int n) 
{ 
    return ((index % n) + n) % n; 
} 

+1

그것은 나에게 명백하지 않았으므로 여기에 약간의 설명이 있습니다. 'a'는 줄 바꿈이 필요한 인덱스이고'n '은 배열 크기입니다. – GER

관련 문제