簡體   English   中英

在數組中查找y的x個連續值的最有效方法是什么?

[英]What is the most efficient method to find x contiguous values of y in an array?

通過callgrind運行我的應用程序顯示,這一行使其他所有內容相形見絀大約10,000。 我可能會圍繞它重新設計,但它讓我感到疑惑; 有沒有更好的方法呢?

這就是我現在正在做的事情:

int i = 1;
while
(
    (
        (*(buffer++) == 0xffffffff && ++i) || 
        (i = 1)
    )
    &&
    i < desiredLength + 1
    &&
    buffer < bufferEnd
);

它正在尋找32位無符號整數數組中第一塊desiredLength 0xffffffff值的偏移量。

它比任何涉及內循環的實現都要快得多。 但它仍然太慢了。

我也會去尋找search_n建議,因為我很確定它能做到這一點。 它實際上非常簡單,基本上可以通過expect_length因子來加速。 除非目標值在數組中非常密集。

這是一個想法:如果從位置I開始有K個連續的值實例,則必須是位置I + K - 1包含該值的情況。 所以你先檢查一下; 如果沒有,那么可能包含K個連續值的最早位置是I + K ,因此您可以在那里重新啟動算法。

另一方面,如果你在I + K - 1處找到值,那么你向后掃描直到你到達I (在這種情況下你成功),或者你到達某個位置J - 1 ,它不包含目標值。 在后一種情況下,您知道有從JI + K - 1目標值,因此您現在檢查J + K - 1 如果可行,您只需向后掃描到I + K 如果它不起作用,則在J + K重新啟動算法。

大多數情況下,您只會查看向量中的每個第K'th位置。 對於大K ,這是一個巨大的勝利。

你標記了c ++所以我假設你有STL算法可用:

std::search_n(buffer, bufferEnd, desiredLength, 0xffffffff);

嘗試使用C標准庫中的memcmp 現代編譯器應具有非常優化的memxxx函數實現, memxxx使現代CPU的速度最快。

只是一個想法,但你一次迭代int數組一個嗎? 考慮一下,如果*(buffer) != 0xffffffffbuffer[desiredLength-1] != 0xffffffff那么你可以確定在兩者之間檢查是沒有意義的,所以你可以通過desiredLength而不是僅僅1來移動buffer 。可以顯著提高你的速度,如果desiredLength比1大得多。 當然它會使你的功能變得復雜,因為:

  1. 如果*(buffer)buffer[desiredLength-1]等於0xffffffff那么你不能認為它們之間是連續的,所以你仍然需要檢查它。
  2. 如果*(buffer)不等於0xffffffffbuffer[desiredLength-1]確實等於0xffffffff那么你必須跟蹤到0xffffffff序列的開頭。
  3. 檢查buffer[desiredLength-1]時,你必須確保不要超出buffer[desiredLength-1]

有點復雜但它可能加快速度。 希望有道理。

如果我想實現這個,我將使用memchrmemcmp來實現:

bool found = false;
std::vector<unsigned char> tmp(desiredLength*sizeof(uint32_t), 0xFF);
while( true ) {
    void* p = memchr(bufferStart, 0xFF,
        (bufferEnd-bufferStart-desiredLength) * sizeof(uint32_t));
    if( !p ) break;
    if( !memcmp(p, &tmp[0], desiredLength * sizeof(uint32_t)) ) {
        found = true;
        break;
    }
}

您也可以使用std::search_n ,它可能比您自己的代碼更優化

std::search_n不可用時:

int i = 1;
while
(
    (
        i == 1
        &&
        buffer < bufferEnd
        &&
        (
            (
                *buffer == desired
                &&
                *(buffer + desiredLength - 1) == desired
                &&
                (i = 3)
            )
            ||
            (buffer += desiredLength && (i = 1))
        )
    )
    ||
    (
        i == 2
        &&
        (
            (
                buffer > arr
                &&
                (*(--buffer) == desired)
            )
            ||
            (i = 3)
        )
    )
    ||
    (
        i >= 3
        &&
        buffer < bufferEnd
        &&
        (
            (
                *(buffer++) == desired
                &&
                (i++ || true)
            )
            ||
            (i = 1)
        )
        &&
        (
            i < 3
            ||
            i - 3 < desiredLength + 1
        )
    )
);
buffer -= i - 4;

if (buffer > bufferEnd - (i-3))
    buffer = bufferEnd;

返回相同的結果僅略慢於std:search_n

buffer = std::search_n(buffer, bufferEnd-1, desiredLength, desired);
if (buffer == bufferEnd-1)
    buffer = bufferEnd;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM