2015-02-09 26 views
12

içerisinde en yakın veya tam anahtarı bulmak Bir süreyi bir zaman aralığına bağlayan bir arama tablosu oluşturmam gerekiyor (ikisi de veri türü çiftidir). Anahtarlar, eklendikçe doğrusal olarak artar, bu yüzden zaten sıralanacaktır (belki de bir unordered_map daha iyi olur mu?).std :: map

Aradığım şey, zaman değerini elde etmek için sağlanan geçerli uzunlukla en iyi eşleşen bir anahtarı bulmanın veya daha uzun olanı çevreleyen iki anahtarın (verilen anahtar aralarında) bulunmasını sağlamaktır. iki zaman değeri arasındaki enterpolasyonlu değeri bulabilir.

Ayrıca gerçek zamanlı olarak çağrılacağı için mümkün olan en iyi performansa ihtiyacım var.

DÜZENLEME: Aşağıdakine aşağıdaki ilk yanıtın bir yorumu vardı, ancak formatın okunması zor.

ben aşağıdakileri yapmaya çalıştım ama aynı yineleyici (5.6) dönmek gibi görünüyor:

std::map<double, double> map; 
map.insert(std::pair<double, double>(0.123, 0.1)); 
map.insert(std::pair<double, double>(2.5, 0.4)); 
map.insert(std::pair<double, double>(5.6, 0.8)); 

std::map<double, double>::iterator low, high; 
double pos = 3.0; 
low = map.lower_bound(pos); 
high = map.upper_bound(pos); 

kullandığım anahtarın daha < olan son öğeye işaret edecek 'düşük' alacağı nasıl aramak?

DÜZENLEME 2: Aptal ben, 'düşük--' ilk öğeyi sağlamayan, bunu yapacaktır.

Ulaşım :)

+0

Bazı ek bilgiler yardımcı olabilir. Şimdiye kadar sahip olduğum şey, bir fonksiyonun l = f (t) olmasıdır. Ve onun tersi t = f^-1 (l). Ve bu veriyi bazı veri noktalarından tahmin etmeli ve enterpolasyon yapmalısınız, doğru mu? Bir arama tablosu yerine, belki sürekli güncellenen bazı yaklaşım işlevi size daha iyi hizmet edecektir. – BitTickler

+0

Haritada sadece birkaç girişiniz varsa (5'ten az gibi), doğrusal arama normalde ilk etapta bir harita kullanmaktan daha hızlıdır. Daha fazla girdiniz varsa, arama tablosu girişlerinizi eşit zamanlı zaman değerleriyle "örneklemek" için para ödeyebilirsiniz. O zaman aramanıza gerek yoktur, ancak endeksi LUT'nizde doğru girişe hesaplayabilirsiniz. – BitTickler

cevap

13

Bunun için, ya std::map::lower_bound

tuşunun az olmadığı ilk elemana işaret bir yineleyici döndürür kullanabilirsiniz.

veya std::map::equal_range kap içinde verilen anahtar ile tüm elemanları ihtiva eden bir dizi döner. Bunun için en yakın giriş isterseniz durumda


, daha önce iade girişi ve bir hem kontrol ve farklılıkları karşılaştırmak gerekir. Böyle bir şey

std::map<double, double>::iterator low, prev; 
double pos = 3.0; 
low = map.lower_bound(pos); 
if (low == map.end()) { 
    // nothing found, maybe use rbegin() 
} else if (low == map.begin()) { 
    std::cout << "low=" << low->first << '\n'; 
} else { 
    prev = std::prev(low); 
    if ((pos - prev->first) < (low->first - pos)) 
     std::cout << "prev=" << prev->first << '\n'; 
    else 
     std::cout << "low=" << low->first << '\n'; 
} 
+0

Teşekkürler. Arama anahtarı her zaman> = dak ve <= max, yani bir şey bulunacaktır.Bu iki yineleyici ile yeni bir zaman değeri çalışabilirim – Rebirth

+0

Bir soru std :: bunun için kaputun altında en hızlı olan harita mı? Arama tablosu 10000'e kadar elemandan oluşabilir, ancak bunu daha fazla yaklaşmayla azaltabilirim .. – Rebirth

+0

A hash map ('std :: unordered_m ap') tam bir değer ararken daha hızlı olabilir, ancak sipariş edilen değerlere sahip değilsiniz. Bu nedenle, bir "std :: map" veya sıralanmış std :: vector ", bu kullanım durumu için en hızlı standart konteyner gibi görünüyor. Her zaman en büyük veya en küçük değeri istediğinizde öncelik sırasını kullanmak yararlı olabilir. –

3

Yapabilirsin yürütmesinde logaritmik olan kurs kullanım LOWER_BOUND ve UPPER_BOUND ait. Ve istediklerini yapmalılar.

std::map<double,double>::iterator close_low; 
//... your_map ... 
close_low=your_map.lower_bound (current_length); 

Bu, anahtar < akım uzunluğu ilk harita elemana bir yineleyici vermelidir. Aynı şekilde upper_bound ile yapın ve zamanınızı kuşattırabilirsiniz.

+2

"* Aynı şekilde, üst_bound ile ve zamanınızı çevrelediniz." * - bu, arama süresini iki katına çıkarır - genellikle, iteratörün öğeye büyük değere ulaşması için artması daha iyidir veya "end()" (eski) olmalıdır alt-sınırdan hemen sonra, ama aynı zamanda çok sayıda anahtar-anahtar unsuru varsa ve yinelemeyi istemediyseniz/istemediyseniz sadece üst sınırla uğraşmayacağınız bir “multimap” ile bile –

+0

iyi bir şekilde çalışıyorum, thx – mths

1

fonksiyonlarını std::lower_bound() işe yarayabilecek ve std::upper_bound() burada faydalı olacaktır.

lower_bound(), aradığınız değere >= olan ilk öğeyi verir; upper_bound(), bu değerden > olan ilk öğeyi verir.upper_bound() beşinci elemanı dönmek ise lower_bound() döner üçüncü eleman kullanılarak {1,3,5,5,6} , aşağıdaki listede değeri 5 aramaya Örneğin

. İki işlev aynı şeyi x döndürürse, aradığınız değer listede yok. x-1'dan hemen önceki değer ve x'dan sonraki değer.

gibi genellikle yinelenen unsurları içermeyen bir yorumun, haritalar istedi Söz, içinde Tony D tarafından işaret etti. İki örneği göstermek için bu örneği saklıyorum.

3

"en iyi performansı sağlamak" - Daha iyi önbellek kullanımı alırsınız veri bitişik adrese dolu olacak çünkü - Bir std::vector içine push_back/emplace_back bunları daha sonra std::lower_bound kullanabilirsiniz, size artan sırayla öğeler eklemek verilen alanı.

+0

Teşekkürler, daha da optimize ettiğimde bir vektöre geçmeyi düşüneceğim. Üzgünüm cevabını kaçırdım. – Rebirth

İlgili konular