मुझे पता है कि STL के पास एक HashMap API है, लेकिन मैं इस बारे में अच्छे उदाहरणों के साथ कोई अच्छा और संपूर्ण दस्तावेज नहीं ढूँढ सकता।
किसी भी अच्छे उदाहरण की सराहना की जाएगी।
मुझे पता है कि STL के पास एक HashMap API है, लेकिन मैं इस बारे में अच्छे उदाहरणों के साथ कोई अच्छा और संपूर्ण दस्तावेज नहीं ढूँढ सकता।
किसी भी अच्छे उदाहरण की सराहना की जाएगी।
जवाबों:
मानक लाइब्रेरी में ऑर्डर किए गए और बिना नक्शे वाले ( std::map
और std::unordered_map
) कंटेनर शामिल हैं। एक ऑर्डर किए गए नक्शे में तत्वों को कुंजी द्वारा सॉर्ट किया जाता है, डालने और एक्सेस ओ (लॉग एन) में होता है । आमतौर पर मानक पुस्तकालय आंतरिक रूप से आदेशित नक्शों के लिए लाल काले पेड़ों का उपयोग करता है । लेकिन यह सिर्फ एक कार्यान्वयन विवरण है। एक अनियंत्रित मानचित्र में डालने और पहुँच O (1) में है। हैशटेबल के लिए यह सिर्फ एक और नाम है।
(आदेशित) के साथ एक उदाहरण std::map
:
#include <map>
#include <iostream>
#include <cassert>
int main(int argc, char **argv)
{
std::map<std::string, int> m;
m["hello"] = 23;
// check if key is present
if (m.find("world") != m.end())
std::cout << "map contains key world!\n";
// retrieve
std::cout << m["hello"] << '\n';
std::map<std::string, int>::iterator i = m.find("hello");
assert(i != m.end());
std::cout << "Key: " << i->first << " Value: " << i->second << '\n';
return 0;
}
आउटपुट:
23 कुंजी: हैलो मान: 23
यदि आपको अपने कंटेनर में ऑर्डर करने की आवश्यकता है और ओ (लॉग एन) रनटाइम के साथ ठीक है तो बस उपयोग करें std::map
।
अन्यथा, यदि आपको वास्तव में हैश-टेबल (ओ (1) इंसर्ट / एक्सेस) की आवश्यकता है, तो देखें कि एपीआई के std::unordered_map
समान है std::map
(उदाहरण के लिए ऊपर दिए गए उदाहरण में आपको बस खोज करना है और उसके map
साथ बदलना है unordered_map
)।
unordered_map
कंटेनर के साथ पेश किया गया था सी ++ 11 मानक संशोधन। इस प्रकार, आपके कंपाइलर के आधार पर, आपको C ++ 11 सुविधाओं को सक्षम करना होगा (जैसे GCC 4.8 का उपयोग करते समय आपको -std=c++11
CXXFLAGS में जोड़ना होगा)।
C ++ 11 रिलीज़ से पहले ही GCC समर्थित unordered_map
- नेमस्पेस में std::tr1
। इस प्रकार, पुराने जीसीसी संकलक के लिए आप इसे इस तरह उपयोग करने का प्रयास कर सकते हैं:
#include <tr1/unordered_map>
std::tr1::unordered_map<std::string, int> m;
यह भी बढ़ावा देने का हिस्सा है, यानी आप बेहतर पोर्टेबिलिटी के लिए संबंधित बूस्टर-हेडर का उपयोग कर सकते हैं ।
hash_map
unordered_map
। इस प्रकार, गैर-मानक पर विचार करने का कोई कारण नहीं है hash_map
।
A hash_map
, मानकीकरण के उद्देश्यों के लिए जो कुछ भी करता है उसका एक पुराना, अविकसित संस्करण है unordered_map
(मूल रूप से TR1 में, और C ++ 11 के बाद से मानक में शामिल है)। जैसा कि नाम से पता चलता है, यह std::map
मुख्य रूप से अनियंत्रित होने से अलग है - यदि, उदाहरण के लिए, आप से मैप के माध्यम से पुनरावृति begin()
करते हैं end()
, तो आपको कुंजी 1 से क्रम में आइटम मिलते हैं , लेकिन यदि आप से unordered_map
से के माध्यम से पुनरावृत्ति begin()
करते हैं end()
, तो आपको आइटम मिलते हैं अधिक या कम मनमाना क्रम।
एक unordered_map
सामान्य रूप से निरंतर जटिलता होने की उम्मीद है। अर्थात्, एक प्रविष्टि, लुकअप, आदि, आमतौर पर तालिका में कितने आइटम हैं, चाहे वे निश्चित रूप से समय की एक निश्चित राशि लेते हैं। एक std::map
जटिलता है जो संग्रहीत किए जा रहे आइटमों की संख्या पर लघुगणक है - जिसका अर्थ है कि किसी आइटम को सम्मिलित करने या पुनर्प्राप्त करने का समय बढ़ता है, लेकिन धीरे-धीरे , जैसा कि मानचित्र बड़ा होता है। उदाहरण के लिए, यदि 1 मिलियन वस्तुओं में से एक को देखने के लिए 1 माइक्रोसेकंड लेता है, तो आप 2 मिलियन आइटमों में से किसी एक को देखने के लिए 2 माइक्रोसेकंड ले सकते हैं, 4 मिलियन आइटमों में से एक के लिए 3 माइक्रोसेकंड, 8 मिलियन में से एक के लिए 4 माइक्रोसेकंड आइटम, आदि
एक व्यावहारिक दृष्टिकोण से, यह वास्तव में पूरी कहानी नहीं है। स्वभाव से, एक साधारण हैश तालिका का एक निश्चित आकार होता है। एक सामान्य प्रयोजन कंटेनर के लिए चर-आकार की आवश्यकताओं के लिए इसे अपनाना कुछ हद तक गैर-तुच्छ है। नतीजतन, संचालन जो (संभावित रूप से) तालिका को बढ़ाते हैं (जैसे, सम्मिलन) संभावित रूप से अपेक्षाकृत धीमी गति से होते हैं (यानी, ज्यादातर काफी तेज होते हैं, लेकिन समय-समय पर एक बहुत धीमी हो जाएगी)। लुकअप, जो तालिका का आकार नहीं बदल सकता है, आम तौर पर बहुत तेज होते हैं। परिणामस्वरूप, जब आप सम्मिलन की संख्या की तुलना में बहुत सारे लुकअप करते हैं, तो अधिकांश हैश-आधारित तालिकाएँ अपने सबसे अच्छे रूप में होती हैं। उन स्थितियों के लिए जहां आप बहुत अधिक डेटा सम्मिलित करते हैं, फिर परिणाम प्राप्त करने के लिए एक बार तालिका के माध्यम से पुनरावृत्ति करें (उदाहरण के लिए, किसी फ़ाइल में अद्वितीय शब्दों की संख्या की गिनती) संभावना है कि एstd::map
बस के रूप में तेजी से होगा, और काफी संभवतः भी तेजी से (लेकिन, फिर से, कम्प्यूटेशनल जटिलता अलग है, ताकि फ़ाइल में अद्वितीय शब्दों की संख्या पर भी निर्भर हो सके)।
1 जहां आप std::less<T>
डिफ़ॉल्ट रूप से नक्शा बनाते समय तीसरे टेम्पलेट पैरामीटर द्वारा आदेश को परिभाषित किया जाता है।
rehash
। जब आप कॉल करते हैं rehash
, तो आप तालिका के लिए एक आकार निर्दिष्ट करते हैं। उस आकार का उपयोग तब तक किया जाएगा जब तक कि ऐसा करने से तालिका के लिए निर्दिष्ट अधिकतम लोड कारक से अधिक न हो (जिस स्थिति में, लोड फैक्टर को सीमा के भीतर रखने के लिए आकार स्वचालित रूप से बढ़ जाएगा)।
यहाँ एक और अधिक पूर्ण और लचीला उदाहरण है जो आवश्यक नहीं छोड़ता है जिसमें संकलन त्रुटियाँ उत्पन्न करना शामिल है:
#include <iostream>
#include <unordered_map>
class Hashtable {
std::unordered_map<const void *, const void *> htmap;
public:
void put(const void *key, const void *value) {
htmap[key] = value;
}
const void *get(const void *key) {
return htmap[key];
}
};
int main() {
Hashtable ht;
ht.put("Bob", "Dylan");
int one = 1;
ht.put("one", &one);
std::cout << (char *)ht.get("Bob") << "; " << *(int *)ht.get("one");
}
अभी भी कुंजी के लिए विशेष रूप से उपयोगी नहीं है, जब तक कि वे संकेत के रूप में पूर्वनिर्धारित नहीं हैं, क्योंकि एक मिलान मूल्य ऐसा नहीं करेगा! (हालांकि, जब से मैं सामान्य रूप से कुंजी के लिए तार का उपयोग करता हूं, कुंजी की घोषणा में "कॉन्स्ट शून्य" के लिए "स्ट्रिंग" को प्रतिस्थापित करना चाहिए, इस समस्या को हल करना चाहिए।)
void*
। शुरुआत के लिए, unordered_map
मानक के हिस्से के रूप में इसे लपेटने का कोई कारण नहीं है और कोड रखरखाव को कम करता है। अगला, यदि इसे लपेटने पर जोर दिया जाए, तो उपयोग करें templates
। ठीक यही तो वे हैं।
साक्ष्य जो std::unordered_map
GCC stdlibc ++ 6.4 में हैश मैप का उपयोग करता है
इस पर उल्लेख किया गया था: https://stackoverflow.com/a/3578247/895245 लेकिन निम्नलिखित उत्तर में: क्या डेटा संरचना std के अंदर है :: C ++ में नक्शा? मैंने आगे GCC stdlibc ++ 6.4 कार्यान्वयन के लिए इस तरह के साक्ष्य दिए हैं:
यहाँ उस उत्तर में वर्णित प्रदर्शन विशेषता ग्राफ का पूर्वावलोकन दिया गया है:
कस्टम क्लास और हैश फ़ंक्शन का उपयोग कैसे करें unordered_map
यह उत्तर देता है कि यह: C ++ बिना किसी कस्टम क्लास प्रकार के कुंजी का उपयोग करता है
अंश: समानता:
struct Key
{
std::string first;
std::string second;
int third;
bool operator==(const Key &other) const
{ return (first == other.first
&& second == other.second
&& third == other.third);
}
};
हैश फंकशन:
namespace std {
template <>
struct hash<Key>
{
std::size_t operator()(const Key& k) const
{
using std::size_t;
using std::hash;
using std::string;
// Compute individual hash values for first,
// second and third and combine them using XOR
// and bit shifting:
return ((hash<string>()(k.first)
^ (hash<string>()(k.second) << 1)) >> 1)
^ (hash<int>()(k.third) << 1);
}
};
}
हम में से उन लोगों के लिए यह पता लगाने की कोशिश कर रहे हैं कि मानक टेम्पलेट का उपयोग करते हुए अभी भी हमारी अपनी कक्षाएं कैसे चल रही हैं, एक सरल उपाय है:
अपनी कक्षा में आपको एक समानता ऑपरेटर अधिभार को परिभाषित करने की आवश्यकता होती है ==
। यदि आप यह नहीं जानते कि यह कैसे करना है, तो GeeksforGeeks में एक महान ट्यूटोरियल है https://www.geeksforgeeks.org/operator-overloading-c/
मानक नाम स्थान के तहत, अपने वर्गनाम के साथ हैश नामक एक टेम्प्लेट संरचना घोषित करें (नीचे देखें)। मुझे एक महान ब्लॉगपोस्ट मिला जो XOR और बिटशिफ्टिंग का उपयोग करके हैश की गणना करने का एक उदाहरण दिखाता है, लेकिन यह इस प्रश्न के दायरे से बाहर है, लेकिन इसमें हैश कार्यों के साथ-साथ https://prateekvj.com/ 2014/06/05 / का उपयोग कर-हैश समारोह-इन-सी के लिए उपयोगकर्ता परिभाषित वर्गों /
namespace std {
template<>
struct hash<my_type> {
size_t operator()(const my_type& k) {
// Do your hash function here
...
}
};
}
std::map
या ऐसा बनाना std::unordered_map
होगा जैसे आप सामान्य रूप से करते हैं और my_type
कुंजी के रूप में उपयोग करते हैं , मानक पुस्तकालय स्वचालित रूप से हैश फ़ंक्शन को चरण 2 में आपके द्वारा पहले (चरण 2 में) परिभाषित करेगा। आपकी चाभियां।#include <unordered_map>
int main() {
std::unordered_map<my_type, other_type> my_map;
}