簡體   English   中英

在已排序的STL容器中查找給定鍵的“最佳匹配鍵”

[英]Finding “best matching key” for a given key in a sorted STL container

問題

我有時間戳數據,我需要根據時間戳進行搜索,以獲得與我最接近的輸入時間戳匹配的現有時間戳。
優選地,這應該用STL解決。 boost :: *或stl :: tr1 :: *(來自帶有Featurepack的VS9)也是可能的。
帶時間戳的數據示例:

struct STimestampedData
{
 time_t m_timestamp; // Sorting criterion
 CData m_data;       // Payload
}

使用stl::vectorsort()equal_range()

由於mapset只允許我找到完全匹配,因此我不會再使用其中任何一個。 所以現在我有一個vector附加數據的vector 。在搜索之前我使用<algorithm>sort()並為它提供自定義比較函數。
之后我使用<algorithm>equal_range()來查找指定值x的兩個鄰居。 從這兩個值我檢查哪一個最接近x然后我有我最好的匹配。


雖然這不是太復雜,但我想知道是否有更優雅的解決方案。
也許STL已經有了一個完全正確的算法,所以我不會在這里重新發明一些東西?

更新:線性與二進制搜索

我忘了提到我有很多數據要處理,所以我不想要線性搜索。
我使用sort()對向量進行sort()的原因是因為它具有隨機訪問迭代器,而不是map的情況。 使用map不允許equal_range()以兩倍的對數復雜度進行搜索。
我對么?

對於這樣的事情,我也會使用equal_range。

如果你每次在vector上使用sort(),最好使用map(或set),因為它總是自動排序,並使用成員equal_range

但這取決於插入/查詢/數據量。 (雖然在我查詢時總是需要排序的東西,地圖將是我的第一選擇,如果有一個很好的理由我只會使用矢量)

我會使用set :: lower_bound來查找匹配或更大的值,然后遞減迭代器以檢查下一個較低的值。 您應該使用std :: set而不是std :: map,因為您的密鑰嵌入在對象中 - 您需要提供一個比較時間戳成員的仿函數。

struct TimestampCompare
{
    bool operator()(const STimestampedData & left, const STimestampedData & right) const
    {
        return left.m_timestamp < right.m_timestamp;
    }
};
typedef std::set<STimestampedData,TimestampCompare> TimestampedDataSet;

TimestampedDataSet::iterator FindClosest(TimestampedDataSet & data, STimestampedData & searchkey)
{
    if (data.empty())
        return data.end();
    TimestampedDataSet::iterator upper = data.lower_bound(searchkey);
    if (upper == data.end())
        return --upper;
    if (upper == data.begin() || upper->m_timestamp == searchkey.m_timestamp)
        return upper;
    TimestampedDataSet::iterator lower = upper;
    --lower;
    if ((searchkey.m_timestamp - lower->m_timestamp) < (upper->m_timestamp - searchkey.m_timestamp))
        return lower;
    return upper;
}

根據您的使用情況,您可以進行簡單的線性搜索而不是排序。 提出一個“距離”功能,循環跟蹤目前為止的最佳匹配及其距離。 當你找到更好的匹配時,忘記前一個,並保持新的和它的距離。 當你完成所有事情時,你就得到了你的匹配。

這可以是O(N * S),其中N是向量中的項目數,S是搜索數。

您當前的方式是O((N + S)* LogN),如果搜索的數量很小且有界,則更大。 否則排序/二進制搜索更好。

//the function should return the element from iArr which has the least distance from input
double nearestValue(vector<double> iArr, double input)
{
    double pivot(0),temp(0),index(0);
    pivot = abs(iArr[0]-input);
    for(int m=1;m<iArr.size();m++)
    {           
        temp = abs(iArr[m]-input);

        if(temp<pivot)
        {
            pivot = temp;
            index = m;
        }
    }

    return iArr[index];
}

void main()
{
    vector<double> iArr;

    srand(time(NULL));
    for(int m=0;m<10;m++)
    {
        iArr.push_back(rand()%20);
        cout<<iArr[m]<<" ";
    }

    cout<<"\nnearest value is: "<<lib.nearestValue(iArr,16)<<"\n";
}

暫無
暫無

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

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