hash table c programs implement hash table
Bu Öğretici C ++ Karma Tabloları ve Karma Haritaları Açıklar. Ayrıca C ++ 'da Hash Tablo Uygulamaları ve Uygulaması Hakkında Bilgi Alacaksınız:
Hashing, büyük miktarda veriyi bir 'hash fonksiyonu' kullanarak daha küçük bir tabloya eşleyebileceğimiz bir tekniktir.
Hashing tekniğini kullanarak, verileri doğrusal ve ikili arama gibi diğer arama tekniklerine kıyasla daha hızlı ve verimli bir şekilde arayabiliriz.
Hashing tekniğini bu derste bir örnekle anlayalım.
=> Kolay C ++ Eğitim Serisini Okuyun.
Ne öğreneceksin:
C ++ 'da Hashing Oluşturma
Binlerce kitap barındıran bir üniversite kütüphanesi örneğini ele alalım. Kitaplar konulara, bölümlere vb. Göre düzenlenmiştir. Ancak yine de her bölümde çok sayıda kitap bulunacak ve bu nedenle kitap aramayı oldukça zorlaştıracaktır.
Bu nedenle, bu zorluğun üstesinden gelmek için her kitaba benzersiz bir numara veya anahtar atarız, böylece kitabın yerini anında biliriz. Bu gerçekten de hashing yoluyla elde edilir.
Kütüphane örneğimizden devam ederek, her kitabı çok uzun bir dizeyle sonuçlanabilecek bölümü, konusu, bölümü vb. Temelinde tanımlamak yerine, benzersiz bir işlev kullanarak kütüphanedeki her kitap için benzersiz bir tamsayı değeri veya anahtarı hesaplıyoruz ve bu anahtarları ayrı bir tabloda saklayın.
Yukarıda bahsedilen benzersiz işleve 'Karma işlevi' ve ayrı tablo 'Karma Tablosu' olarak adlandırılır. Verilen değeri Karma Tablosundaki belirli bir benzersiz anahtarla eşlemek için bir karma işlevi kullanılır. Bu, öğelere daha hızlı erişimle sonuçlanır. Karma işlevi ne kadar verimli olursa, her bir öğenin benzersiz anahtara eşlenmesi o kadar verimli olacaktır.
Bir hash fonksiyonu düşünelim h (x) değeri eşleyen ' x ',' x% 10 Dizide. Verilen veriler için, aşağıdaki diyagramda gösterildiği gibi, anahtarları veya Hash kodlarını veya Hash'leri içeren bir hash tablosu oluşturabiliriz.
Yukarıdaki diyagramda, dizideki girişlerin bir hash fonksiyonu kullanılarak hash tablosundaki konumlarına eşlendiğini görebiliriz.
Böylelikle hashing'in aşağıda belirtildiği gibi iki adımda uygulandığını söyleyebiliriz:
# 1) Değer, bir karma işlevi kullanılarak benzersiz bir tam sayı anahtarına veya karma değerine dönüştürülür. Hash tablosuna düşen orijinal elemanı saklamak için bir indeks olarak kullanılır.
Yukarıdaki diyagramda, karma tablodaki değer 1, diyagramın LHS'sinde verilen veri dizisinden eleman 1'i depolamak için benzersiz anahtardır.
#iki) Veri dizisindeki öğe, karma anahtar kullanılarak hızlı bir şekilde alınabileceği karma tablosunda saklanır. Yukarıdaki diyagramda, bir hash fonksiyonu kullanarak ilgili konumlarını hesapladıktan sonra, karma tablosundaki tüm öğeleri sakladığımızı gördük. Hash değerlerini ve indeksi almak için aşağıdaki ifadeleri kullanabiliriz.
hash = hash_func(key) index = hash % array_size
Özet fonksiyonu
Haritalamanın verimliliğinin, kullandığımız hash fonksiyonunun verimliliğine bağlı olduğundan bahsetmiştik.
Bir hash işlevi temelde aşağıdaki gereksinimleri karşılamalıdır:
- Hesaplaması Kolay: Bir hash işlevi, benzersiz anahtarları hesaplamak kolay olmalıdır.
- Daha Az Çarpışma: Öğeler aynı anahtar değerlere eşit olduğunda, bir çarpışma meydana gelir. Kullanılan hash fonksiyonunda mümkün olduğu kadar minimum çarpışmalar olmalıdır. Çarpışmaların meydana gelmesi kaçınılmaz olduğundan, çarpışmalarla ilgilenmek için uygun çarpışma çözme tekniklerini kullanmalıyız.
- Üniforma dağıtımı: Karma işlevi, karma tablo boyunca verilerin tekdüze bir dağılımıyla sonuçlanmalı ve böylece kümelenmeyi önlemelidir.
Karma Tablosu C ++
Karma tablo veya bir karma harita, orijinal veri dizisinin öğelerine işaretçileri depolayan bir veri yapısıdır.
Kütüphane örneğimizde, kütüphanenin karma tablosu, kütüphanedeki her bir kitap için işaretler içerecektir.
Karma tablosunda girişlerin olması, dizideki belirli bir öğeyi aramayı kolaylaştırır.
Daha önce görüldüğü gibi, hash tablosu, dizini, istenen değerin bulunabileceği kova veya yuva dizisi olarak hesaplamak için bir karma işlevi kullanır.
Aşağıdaki veri dizisine sahip başka bir örnek düşünün:
Aşağıda gösterildiği gibi 10 boyutunda bir hash tablomuz olduğunu varsayalım:
Şimdi aşağıda verilen hash fonksiyonunu kullanalım.
Hash_code = Key_value % size_of_hash_table
Bu Hash_code = Key_value% 10
Yukarıdaki işlevi kullanarak, anahtar değerleri aşağıda gösterildiği gibi karma tablo konumlarına eşleriz.
Veri öğesi | Özet fonksiyonu | Hash kodu |
---|---|---|
22 | % 22 10 = 2 | iki |
25 | % 25 10 = 5 | 5 |
27 | % 27 10 = 7 | 7 |
46 | % 46 10 = 6 | 6 |
70 | % 70 10 = 0 | 0 |
89 | % 89 10 = 9 | 9 |
31 | % 31 10 = 1 | bir |
Yukarıdaki tabloyu kullanarak hash tablosunu aşağıdaki gibi gösterebiliriz.
Bu nedenle, hash tablosundan bir elemana erişmemiz gerektiğinde, aramayı yapmak sadece O (1) zaman alacaktır.
Çarpışma
Anahtar değerini hash tablosundaki hash koduna eşleyebilmemiz için genellikle hash kodunu hash fonksiyonunu kullanarak hesaplıyoruz. Yukarıdaki veri dizisi örneğinde, bir 12 değeri girelim. Bu durumda, anahtar değeri 12 için hash_code 2 olacaktır. (12% 10 = 2).
Ancak hash tablosunda, hash_code 2 için aşağıda gösterildiği gibi 22 anahtar / değer çiftiyle zaten bir eşlememiz var:
Yukarıda gösterildiği gibi, 12 ve 22 olmak üzere iki değer için aynı hash koduna sahibiz, yani 2. Bir veya daha fazla anahtar değeri aynı konuma eşit olduğunda, bir çarpışma ile sonuçlanır. Bu nedenle, karma kod konumu zaten bir anahtar değeri tarafından işgal edilmiştir ve aynı konuma yerleştirilmesi gereken başka bir anahtar değeri vardır.
Hashing durumunda, çok büyük boyutta bir hash tablomuz olsa bile, o zaman bir çarpışma orada olmaya mahkumdur. Bunun nedeni, genel olarak büyük bir anahtar için küçük bir benzersiz değer bulmamızdır, dolayısıyla herhangi bir zamanda bir veya daha fazla değerin aynı karma koda sahip olması tamamen mümkündür.
Karıştırmada bir çarpışmanın kaçınılmaz olduğu düşünüldüğünde, her zaman çarpışmayı önlemenin veya çözmenin yollarını aramalıyız. Hashing sırasında meydana gelen çarpışmayı çözmek için kullanabileceğimiz çeşitli çarpışma çözümleme teknikleri vardır.
Çarpışma Çözüm Teknikleri
Aşağıdakiler, hash tablosunda çarpışmayı çözmek için kullanabileceğimiz tekniklerdir.
Ayrı Zincirleme (Açık Karma)
Bu, en yaygın çarpışma çözme tekniğidir. Bu aynı zamanda açık karma olarak da bilinir ve bağlantılı bir liste kullanılarak uygulanır.
Ayrı zincirleme tekniğinde, karma tablodaki her giriş bağlantılı bir listedir. Anahtar, karma kodla eşleştiğinde, söz konusu karma koda karşılık gelen bir listeye girilir. Böylece, iki anahtar aynı karma koduna sahip olduğunda, her iki giriş de bağlantılı listeye girilir.
Yukarıdaki örnek için, Ayrı Zincirleme aşağıda temsil edilmektedir.
Yukarıdaki şema zincirlemeyi temsil etmektedir. Burada mod (%) işlevini kullanıyoruz. İki anahtar değer aynı hash koduna eşit olduğunda, bu öğeleri bağlantılı bir liste kullanarak bu hash koduna bağladığımızı görüyoruz.
Anahtarlar karma tablo boyunca tek tip olarak dağıtılırsa, belirli bir anahtarı aramanın ortalama maliyeti o bağlantılı listedeki ortalama anahtar sayısına bağlıdır. Böylelikle ayrı zincirleme, girişlerin sayısında slotlardan daha fazla bir artış olduğunda bile etkin kalır.
Ayrı zincirleme için en kötü durum, tüm anahtarların aynı karma koda eşit olması ve bu nedenle yalnızca bir bağlantılı listeye eklenmesi durumudur. Bu nedenle, hash tablosundaki tüm girişleri ve tablodaki anahtar sayısı ile orantılı olan maliyeti aramamız gerekir.
Doğrusal İnceleme (Açık Adresleme / Kapalı Hashing)
Açık adresleme veya doğrusal araştırma tekniğinde, tüm giriş kayıtları hash tablosunun kendisinde saklanır. Anahtar / değer çifti bir karma kodla eşleştiğinde ve karma kodla gösterilen konum boş olduğunda, anahtar değer o konuma eklenir.
Pozisyon halihazırda dolu ise, o zaman bir araştırma dizisi kullanılarak anahtar değeri, hash tablosunda boş olan bir sonraki pozisyona eklenir.
Doğrusal inceleme için, hızlı arama işlevi aşağıda gösterildiği gibi değişebilir:
hash = hash% hashTableSize
hash = (hash + 1)% hashTableSize
hash = (hash + 2)% hashTableSize
hash = (hash + 3)% hashTableSize
Doğrusal problama durumunda, yuvalar veya ardışık problar arasındaki aralığın sabit olduğunu görüyoruz, yani 1.
Yukarıdaki diyagramda, bunu 0inci'hash = hash% hash_tableSize' fonksiyonunu kullanarak 10 giriyoruz.
Şimdi eleman (70), karma tablodaki konum 0'a da eşittir. Ama o yer zaten dolu. Dolayısıyla, doğrusal sondalama kullanarak, bir sonraki konumu bulacağız: 1. Bu konum boş olduğundan, bir okla gösterildiği gibi anahtarı 70 bu konuma yerleştiriyoruz.
Ortaya çıkan Karma Tablosu aşağıda gösterilmiştir.
Doğrusal problama, sürekli hücrelerin işgal edilme olasılığının olduğu ve yeni bir eleman ekleme olasılığının azaldığı “Birincil Kümeleme” probleminden zarar görebilir.
Ayrıca, iki eleman ilk hash fonksiyonunda aynı değeri alırsa, bu durumda her iki eleman da aynı araştırma sırasını takip edecektir.
Karesel Problama
Kuadratik problama, lineer problama ile aynıdır, tek fark prob ile ölçüm için kullanılan aralıktır. Adından da anlaşılacağı gibi, bu teknik, doğrusal mesafe yerine bir çarpışma meydana geldiğinde yuvaları işgal etmek için doğrusal olmayan veya ikinci dereceden mesafeyi kullanır.
İkinci dereceden araştırmada, dilimler arasındaki aralık, önceden karma indekse rastgele bir polinom değeri eklenerek hesaplanır. Bu teknik, birincil kümelenmeyi önemli ölçüde azaltır, ancak ikincil kümelemeyi geliştirmez.
Çift Hashing
Çift hashing tekniği, doğrusal problamaya benzer. Çift hashing ile lineer problama arasındaki tek fark, çift hashing tekniğinde problama için kullanılan aralığın iki hash fonksiyonu kullanılarak hesaplanmasıdır. Hash fonksiyonunu anahtara arka arkaya uyguladığımız için, birincil kümelemeyi ve ikincil kümelemeyi ortadan kaldırır.
Zincirleme (Açık Karma) ve Doğrusal İnceleme (Açık Adresleme) Arasındaki Fark
Zincirleme (Açık Hashing) | Doğrusal İnceleme (Açık Adresleme) |
---|---|
Anahtar değerler, ayrı bir bağlantılı liste kullanılarak tablonun dışında saklanabilir. | Anahtar değerler yalnızca tablonun içinde saklanmalıdır. |
Karma tablosundaki öğelerin sayısı, karma tablosunun boyutunu aşabilir. | Hash tablosunda bulunan elemanların sayısı, hash tablosundaki indislerin sayısını aşmayacaktır. |
Silme, zincirleme tekniğinde etkilidir. | Silme külfetli olabilir. Gerekmediği takdirde önlenebilir. |
Her konum için ayrı bir bağlantılı liste tutulduğundan, alınan alan büyüktür. | Tüm girişler aynı tabloda yer aldığından, alınan alan daha azdır. |
C ++ Karma Tablo Uygulaması
Hash tablolarını programlamak için dizileri veya bağlantılı listeleri kullanarak hashing uygulayabiliriz. C ++ 'da ayrıca, karma tabloya benzer bir yapı olan, ancak her giriş bir anahtar-değer çifti olan 'hash map' adlı bir özelliğimiz var. C ++ 'da hash haritası veya sadece bir harita olarak adlandırılır. C ++ 'da karma harita genellikle sırasızdır.
C ++ Standart Şablon Kitaplığı'nda (STL), haritaların işlevselliğini uygulayan bir başlık vardır. Biz kapladık STL Haritaları STL ile ilgili eğitimimizde ayrıntılı olarak.
Aşağıdaki uygulama, bağlı listeleri hash tablosu için bir veri yapısı olarak kullanarak hashing yapmak içindir. Bu uygulamada bir çarpışma çözme tekniği olarak 'Zincirleme' yi de kullanıyoruz.
#include #include using namespace std; class Hashing { int hash_bucket; // No. of buckets // Pointer to an array containing buckets list *hashtable; public: Hashing(int V); // Constructor // inserts a key into hash table void insert_key(int val); // deletes a key from hash table void delete_key(int key); // hash function to map values to key int hashFunction(int x) { return (x % hash_bucket); } void displayHash(); }; Hashing::Hashing(int b) { this->hash_bucket = b; hashtable = new list (hash_bucket); } //insert to hash table void Hashing::insert_key(int key) { int index = hashFunction(key); hashtable(index).push_back(key); } void Hashing::delete_key(int key) { // get the hash index for key int index = hashFunction(key); // find the key in (inex)th list list :: iterator i; for (i = hashtable(index).begin(); i != hashtable(index).end(); i++) { if (*i == key) break; } // if key is found in hash table, remove it if (i != hashtable(index).end()) hashtable(index).erase(i); } // display the hash table void Hashing::displayHash() { for (int i = 0; i ' << x; cout << endl; } } // main program int main() { // array that contains keys to be mapped int hash_array() = {11,12,21, 14, 15}; int n = sizeof(hash_array)/sizeof(hash_array(0)); Hashing h(7); // Number of buckets = 7 //insert the keys into the hash table for (int i = 0; i < n; i++) h.insert_key(hash_array(i)); // display the Hash table cout<<'Hash table created:'< Çıktı:
Karma tablo oluşturuldu:
0 -> 21 -> 14
1 -> 15
iki
3
4 -> 11
5 -> 12
6
Anahtar 12 silindikten sonra karma tablo:
0 -> 21 -> 14
1 -> 15
iki
3
4 -> 11
5
6
8 yıllık deneyim için oracle pl sql mülakat soruları
Çıktı, 7 boyutunda oluşturulmuş bir karma tablo gösterir. Çarpışmayı çözmek için zincirleme kullanırız. Anahtarlardan birini sildikten sonra hash tablosunu görüntüleriz.
Hashing Uygulamaları
# 1) Şifrelerin Doğrulanması: Şifrelerin doğrulanması genellikle kriptografik karma işlevler kullanılarak yapılır. Şifre girildiğinde, sistem şifrenin karmasını hesaplar ve ardından doğrulama için sunucuya gönderilir. Sunucuda, orijinal şifrelerin karma değerleri saklanır.
# 2) Veri Yapıları: C ++ 'da unordered_set ve unordered_map gibi farklı veri yapıları, python veya C #' da sözlükler, HashSet ve Java'daki hash map gibi farklı veri yapılarının tümü, anahtarların benzersiz değerler olduğu anahtar-değer çiftini kullanır. Değerler, farklı anahtarlar için aynı olabilir. Hashing, bu veri yapılarını uygulamak için kullanılır.
# 3) Mesaj Özeti: Bu, kriptografik bir hash kullanan başka bir uygulamadır. Mesaj özetlerinde, gönderilen ve alınan veriler ve hatta dosyalar için bir karma hesaplar ve veri dosyalarının kurcalanmamasını sağlamak için bunları saklanan değerlerle karşılaştırırız. Buradaki en yaygın algoritma 'SHA 256' dır.
# 4) Derleyici İşlemi: Derleyici bir programı derlediğinde, programlama dili için anahtar sözcükler diğer tanımlayıcılardan farklı şekilde depolanır. Derleyici, bu anahtar kelimeleri depolamak için bir karma tablo kullanır.
# 5) Veritabanı İndeksleme: Karma tablolar, veritabanı indeksleme ve disk tabanlı veri yapıları için kullanılır.
# 6) İlişkilendirilebilir Diziler: İlişkilendirilebilir diziler, indisleri tamsayı benzeri dizeler veya diğer nesne türleri dışında veri türünde olan dizilerdir. İlişkili dizileri uygulamak için karma tablolar kullanılabilir.
Sonuç
Karma oluşturma, ekleme, silme ve arama işlemleri için sabit O (1) süresi aldığı için en yaygın kullanılan veri yapısıdır. Karma oluşturma, çoğunlukla büyük veri girişleri için benzersiz bir küçük anahtar değeri hesaplayan bir karma işlevi kullanılarak gerçekleştirilir. Diziler ve bağlantılı listeleri kullanarak hashing uygulayabiliriz.
Bir veya daha fazla veri girişi aynı anahtar değerlerine eşit olduğunda, bir çarpışmaya neden olur. Doğrusal problama, zincirleme vb. Dahil olmak üzere çeşitli çarpışma çözümleme teknikleri gördük. Ayrıca, C ++ 'da hash uygulamasının uygulanmasını da gördük.
Sonuç olarak, hashing'in programlama dünyasındaki en verimli veri yapısı olduğunu söyleyebiliriz.
=> Tüm C ++ Eğitim Serisini Burada Arayın.
Önerilen Kaynaklar
- Karar Tablosu Tekniğini Kullanarak Karmaşık İş Mantığı Testi Senaryoları Nasıl Yazılır
- Alan Doğrulama Tablosu (FVT): Alan Doğrulaması İçin Bir Test Tasarım Tekniği
- QTP Eğitimi # 15 - QTP'de Metin Alanı, Tablo ve Sayfa Kontrol Noktalarını Kullanma
- STL'de HARİTALAR
- Yönlendiriciler Hakkında Her Şey: Yönlendirici Türleri, Yönlendirme Tablosu ve IP Yönlendirme
- En İyi 40 MySQL Mülakat Soruları ve Cevapları (2021 Soru)
- En İyi 90 SQL Mülakat Soruları ve Cevapları (EN SON)
- Unix Utilities Program Komutları: Hang, Man, Find Su, Sudo (Bölüm D)