2009-04-09 15 views
10

İlgi alanı dize eşleşmesidir. Böyle bir yapıya sahip olduğumu varsayın.Mükemmel bir karma için bir işlev tasarlamaya nasıl giderdin?

typedef struct 
{ 
    char *name, 
    int (*function)(); 

} StringArray 

StringArray s[] = 
{ 
    {"George", func1}, 
    {"Paul", func2}, 
    {"Ringo", func3}, 
    {"John", func4}, 
    {"",  NULL} /* End of list */ 
} 

Dizide sabit sayıda dizgi var. Örnekte olduğu gibi kodlanmışlardır. Tablo değişirse, hash işlevinin kalitesini yeniden değerlendirmek gerekir.

Bir dizeye bir karma işlevi uygulamak istiyorum ve dize dizideki bir ile eşleşiyorsa, işlevini çağırın. Bunun için mükemmel bir karma işlevi gereklidir. Çarpışmalara izin verilmez. Yemin etmenin amacı, aramada O (1) performansının elde edilmesidir.

Bunu yapmak için bir işlev tasarlama konusunda hangi fikirlere sahipsiniz?

+0

Spam bunu –

+0

@Mitch anlamı ne düşündüğünü demektir sanmıyorum: Şunu musunuz bu kolayca googled edilebilecek bir sorudur? –

+0

@ j_random_hacker: Ben yaptım. Ama geç oldu, ve spam değil ... –

cevap

16

kullanabilirsiniz.

+0

Vurgulanan kısım, wikipedia sayfasının alt kısmında buna bir bağlantı olması. – EvilTeach

0

Sen gperf giriş sayfasına bakın haritayı

std::string foo() { return "Foo"; } 
std::string bar() { return "Bar"; } 

int main() 
{ 
    std::map<std::string, std::string (*)()> m; 
    m["foo"] = &foo; 
    m["bar"] = &bar; 
} 
+0

std :: harita bir hash kullanmaz - bu ağaç tabanlı –

+0

neden tekerlek icat, harita gibi mevcut kütüphaneleri kullanabilirsiniz. – Vinay

+1

belki de soru sorucusu ağaç aramalarından ziyade karma karakterlerin performans özelliklerini istemiş midir? –

1
+0

Sorunu doğrudan ele almıyor, ancak yine de iyi bağlantılar var. – EvilTeach

+0

Downvoter (bu eski soruya) lütfen yorum bırakın. Teşekkürler. –

0

çarpışmalar kesinlikle izin verilmez değilseniz, tek seçenek muhtemelen bir en iyi yol değildir veritabanında her dize, takip etmektir gitmek.

Yapacağım şey, MD5 veya SHA gibi mevcut ortak güçlü karma algoritmalardan birini uygulamaktır. Etrafta örneklerin mimiad'leri var, örneğin bir tane: İşte bir örnek: http://www.codeproject.com/KB/security/cryptest.aspx

-1

Mükemmel bir hash fonksiyonu yok.

Çarpışmaları en aza indirecek çok şeyiniz var, ancak hiçbiri bunları yok etmiyor.

olsa birini tavsiye edebilir: P

DÜZENLEME: Çözüm mükemmel karma işlevi bulma olamaz . Çözüm, çarpışmaların farkında olmaktır. Genelde karma işlevinin çarpışmaları vardır. Bu açıkça, veri kümesine ve sonuçta oluşan karma kodun boyutuna bağlıdır.

+0

http://en.wikipedia.org/wiki/Perfect_hashing –

+0

@Adam: Sadece farklı bir veri kümesi olduğunda geçerli olduğu için oldukça büyük bir uyarı var. OP'nin kullanılmakta olan dizgileri sınırlamadan bahsetmediği için Megacan ile bu durumda mükemmel bir karma olmadığını kabul ediyorum. +1. – sipwiz

+0

Sorgucu, en azından dolaylı olarak - sadece dört Beatles'in var olduğunu) veya kovuldukları davulculuğu ve Stu whatsisname'i dahil ederseniz - sabit bir veri kümesi olduğunu belirtiyor. –

0

Dengeli bir ikili ağaç kullanın. Sonra, KNOW davranışı, ALWAYS O (logn) olur.

Keskiler sevmiyorum. İnsanlar algoritmaları ile ne kadar risk aldıklarını fark etmiyorlar. Bazı test verilerini çalıştırıyorlar ve alana yerleştiriyorlar. Kullanılmamış bir karma algoritmanın ASLA alanında davranış kontrolü olup olmadığını gördüm. O (1) yerine hemen hemen her zaman kabul edilebilir olan

.

+0

“O (log n), O (1) yerine hemen hemen her zaman kabul edilebilir.” Birçok uygulamada, bu ifade yanlış sonuçlandı. Bunu görmek için veri noktalarının sayısını birkaç milyonun üzerine çıkarmanız yeterlidir. –

+0

Bunu yaptıktan sonra test edin. Tüm olası girişlerin ne olabileceğini önceden bilmedikçe, şüpheler garantili sonuçlar vermez. Girişi toparlama eğilimi olan bir karma işlevi muhtemelen size O (1) vermeyecektir. –

+0

Bu durumda, tüm girişler bilinir. Dizide oturuyorlar. ve giriş dizesi tam bir eşleşme ya da eşleşme yok. – EvilTeach

2

Özet, hem C hem de C++'yi listeler. Hangisini arıyorsun? C ve C++ iki ayrı dildir ve string işleme ve veri yapılarında büyük ölçüde farklılık gösterir (ve C'nin C++ içinde çalışması gerçeği değişmez).

Neden, özellikle, mükemmel bir karma işlev istiyor musunuz? Bir dizeyi bir işlevle ilişkilendirmek istiyor ve bunu yapmak için iyi bir yol olacağını düşündünüz mü? Bu bir çeşit ödev görevi mi? <> C++ haritasından kaçınmak için bir nedeniniz var mı? (Ya da unordered_map <> eğer mevcutsa?)

Mükemmel bir kareye ihtiyacınız varsa, dizelerdeki kısıtlamalar nelerdir? Göndermek istediğiniz belirli bir sabit set olacak mı? Setlerden biri ile uyuşmayan dizeler ne olacak? Rastgele dizelerden isabet almayı kabul ediyor musunuz, yoksa gelen dizelerin sayısı sınırlı mı?

Sorunuzu bu gibi bilgileri içerecek şekilde düzenleyebilirseniz, çok daha yararlı olabiliriz. (Ilk iki yorumlara yanıt olarak)

DÜZENLEME: Eğer tahminen sizin C ve C++ çalışmaları hem bunu istiyor çünkü

Tamam, C çözümleri bakmak gerekir. Muhtemelen performansı istiyorsun, ama test ettin mi? G/Ç sisteminde gelen dizelerle uğraşıyorsak, gönderim zamanının cüce olması muhtemeldir.

Rasgele dizeler bekliyorsunuz. Tüm çarpışmaları rastgele verilerden uzaklaştıracak mükemmel bir karma işlev beklemek biraz fazladır, bu yüzden bunu dikkate almanız gerekir.

trie'u düşündünüz mü? Mükemmel bir karma fonksiyonundan (veya olmamasından) daha verimli olabilir, C içinde uygulanması oldukça kolay olmalı ve sevk dizileri veya olası çarpışmalar listenizi yeniden tasarlamada sorunlardan kaçınacaktır.

+0

Hem c hem de C++ kodlarım var ve tanrı bana yardım et Pro * C. O (1) performans için hashing. Lol, ödev yok. Bazı performans kritik kodlarını hızlandırmak için bir araç oluşturmaya çalışıyorum. Örnek tartışma amaçlı basitleştirilmiştir. Gerçek dünya kullanımı değildir. – EvilTeach

+0

Dizeler çok uzun olacaktır. Hiçbiri sıfır uzunluğunda olamaz. Pratik bir sınır olarak, dizideki hiçbir dize 32 karakterden uzun olamaz. Arayanın içeri girdiği yer herhangi bir uzunlukta olabilir, ancak tablodaki dizelerden daha uzunsa, eşleşmeden bahsetmek için – EvilTeach

+0

+ 1 no'lu bir eşleşme söz konusudur. –

0

Bu egzersizin nihai sonuç net kapalı dize odaklı hash fonksiyonları bir dizi çalmak

    • etmekti.
    • Her bir işlevi, veri kümesiyle bir dizi mod operatör değeriyle test eden ve bu işlevle çalışan en küçük mükemmel hashı arayan bir tür fabrika sınıfı oluşturun.
    • Bu fabrika sınıfı varsayılan yapıcısı, doğru karma işlevini çektiğinde ve en az miktarda bellek gerektiren mükemmel karma değeri vermek için mod boyutunu belirleyen bir dizi argümanı temsil eden bir dize döndürür.
    • normal kullanımda, yalnızca döndürülen argümanlarla sınıfı başlatırsınız ve sınıf kendini istenen işlevlere sahip bir çalışma durumuna sokar.
    • Bu kurucu, herhangi bir çarpışma olmadığını ve varsa iptal edildiğini doğrular.
    • Kusursuz karmanın bulunmadığı durumlarda, giriş tablonun sıralı bir sürümünde ikili bir aramaya dönüşür.

    Etki alanımdaki diziler için bu çok iyi çalışıyor gibi görünüyor. Gelecekteki olası bir optimizasyon, girişin alt dizileri üzerinde aynı tür testleri yapmaktır. Örnek olayda, her müzisyen isminin ilk harfi, birbirinden ayırmak için yeterlidir. Daha sonra, gerçek hash fonksiyonunun maliyetini, kullanılan hafızaya karşı dengelemek gerekir.

    Fikir veren herkese teşekkür ederim. Evil