আমি জানি যে এসটিএলের একটি হ্যাশম্যাপ এপিআই রয়েছে, তবে এ সম্পর্কিত ভাল উদাহরণ সহ আমি কোনও ভাল এবং পুঙ্খানুপুঙ্খ ডকুমেন্টেশন পাই না।
যে কোনও ভাল উদাহরণ প্রশংসা করা হবে।
আমি জানি যে এসটিএলের একটি হ্যাশম্যাপ এপিআই রয়েছে, তবে এ সম্পর্কিত ভাল উদাহরণ সহ আমি কোনও ভাল এবং পুঙ্খানুপুঙ্খ ডকুমেন্টেশন পাই না।
যে কোনও ভাল উদাহরণ প্রশংসা করা হবে।
উত্তর:
স্ট্যান্ডার্ড লাইব্রেরিতে অর্ডারযুক্ত এবং অযৌক্তিক মানচিত্র ( std::map
এবং std::unordered_map
) পাত্রে অন্তর্ভুক্ত রয়েছে। অর্ডার করা মানচিত্রে উপাদানগুলি কী দ্বারা বাছাই করা হয়, সন্নিবেশ করা এবং অ্যাক্সেস ও (লগ এন) এ থাকে । সাধারণত মানক পাঠাগারটি অভ্যন্তরীণভাবে অর্ডার করা মানচিত্রের জন্য লাল কালো গাছ ব্যবহার করে। তবে এটি কেবল একটি বাস্তবায়ন বিশদ। একটি অ-নিয়ন্ত্রিত মানচিত্রে সন্নিবেশ করুন এবং অ্যাক্সেস ও (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
।
অন্যথায়, যদি আপনার সত্যিই একটি হ্যাশ-টেবিল (O (1) সন্নিবেশ / অ্যাক্সেস) প্রয়োজন হয় তবে দেখুন std::unordered_map
, যা std::map
এপিআই এর অনুরূপ (যেমন উপরের উদাহরণে আপনাকে কেবল অনুসন্ধান এবং এর সাথে প্রতিস্থাপন map
করতে হবে unordered_map
)।
unordered_map
ধারক সঙ্গে চালু করা হয় সি ++ 11 মান সংস্করণ। সুতরাং, আপনার সংকলকটির উপর নির্ভর করে আপনাকে সি ++ ১১ টি বৈশিষ্ট্য সক্ষম করতে হবে (যেমন জিসিসি ৪.৮ ব্যবহার -std=c++11
করার সময় আপনাকে সিএক্সএক্সএফএলএজিএসে যুক্ত করতে হবে)।
সি ++ 11 প্রকাশের আগেও জিসিসি সমর্থিত unordered_map
- নেমস্পেসে std::tr1
। সুতরাং, পুরানো জিসিসি সংকলকগুলির জন্য আপনি এটি এটি ব্যবহার করার চেষ্টা করতে পারেন:
#include <tr1/unordered_map>
std::tr1::unordered_map<std::string, int> m;
এটি বুস্টেরও একটি অংশ, অর্থাত্ আপনি আরও ভাল বহনযোগ্যতার জন্য সংশ্লিষ্ট বুস্ট-শিরোনামটি ব্যবহার করতে পারেন ।
hash_map
unordered_map
। সুতরাং, অ-মানক বিবেচনা করার কোনও কারণ নেই hash_map
।
একটি hash_map
একটি পুরোনো, প্রমিতকরণ উদ্দেশ্যে কি বলা হয় একটি এর unstandardized সংস্করণ unordered_map
(মূলত TR1, এবং যেহেতু সি ++ 11 মান অন্তর্ভুক্ত)। নাম থেকেই বোঝা যায়, তা থেকে ভিন্ন std::map
unordered হচ্ছে প্রাথমিকভাবে - যদি, উদাহরণস্বরূপ, আপনি পুনরুক্তি থেকে একটি মানচিত্র মাধ্যমে begin()
করতে end()
, আপনি মূল দ্বারা অনুক্রমে আইটেম পাওয়া 1 , কিন্তু আপনি বারবার একটি মাধ্যমে যদি unordered_map
থেকে begin()
থেকে end()
, আপনি একটি আইটেম পেতে কমবেশি স্বেচ্ছাসেবী ক্রম।
একটি unordered_map
সাধারণত ধ্রুবক জটিলতা প্রত্যাশিত হয়। এটি কোনও সন্নিবেশ, অনুসন্ধান ইত্যাদি সাধারণত টেবিলে থাকা কতগুলি আইটেমই নির্বিশেষে মূলত একটি নির্দিষ্ট পরিমাণ সময় নেয়। একটিতে std::map
এমন জটিলতা রয়েছে যা সংরক্ষণ করা হচ্ছে এমন আইটেমের সংখ্যার উপর লোগারিথমিক - যার অর্থ একটি আইটেম সন্নিবেশ করানো বা পুনরুদ্ধারের সময়টি বৃদ্ধি পায় তবে মানচিত্রটি বড় হওয়ার সাথে সাথে ধীরে ধীরে । উদাহরণস্বরূপ, যদি 1 মিলিয়ন আইটেমগুলির মধ্যে একটি অনুসন্ধান করতে 1 মাইক্রোসেকেন্ড লাগে তবে আপনি আশা করতে পারেন যে এটি 2 মিলিয়ন আইটেমের মধ্যে একটি অনুসন্ধান করতে প্রায় 2 মাইক্রোসেকেন্ড নেবে, 4 মিলিয়ন আইটেমের মধ্যে 3 টি মাইক্রোসেকেন্ড, 8 মিলিয়নের একটির জন্য 4 মাইক্রোসেকেন্ড আইটেম, ইত্যাদি
ব্যবহারিক দৃষ্টিকোণ থেকে, যদিও এটি পুরো গল্পটি নয়। প্রকৃতির দ্বারা, একটি সাধারণ হ্যাশ টেবিলের একটি নির্দিষ্ট আকার থাকে। সাধারণ উদ্দেশ্যে ধারকটির জন্য পরিবর্তনশীল-আকারের প্রয়োজনীয়তার সাথে এটি মানিয়ে নেওয়া কিছুটা তুচ্ছ নয় is ফলস্বরূপ, টেবিলগুলি বাড়ানো (সম্ভাব্যভাবে) যে ক্রিয়াকলাপগুলি (উদাহরণস্বরূপ, সন্নিবেশ) সম্ভবত তুলনামূলকভাবে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে বেড়ে যায়। চেহারাগুলি, যা টেবিলের আকার পরিবর্তন করতে পারে না, সাধারণত অনেক দ্রুত হয়। ফলস্বরূপ, সন্নিবেশনের সংখ্যার তুলনায় আপনি অনেকগুলি অনুসন্ধান করতে গেলে বেশিরভাগ হ্যাশ-ভিত্তিক টেবিলগুলি তাদের সেরা হতে থাকে। এমন পরিস্থিতিতে যেখানে আপনি প্রচুর ডেটা সন্নিবেশ করান, তারপরে ফলাফল পুনরুদ্ধার করতে একবার টেবিলের মাধ্যমে পুনরাবৃত্তি করুন (উদাহরণস্বরূপ, কোনও ফাইলে অনন্য শব্দের সংখ্যা গণনা করা) সম্ভাবনাগুলি হ'লstd::map
ঠিক তত দ্রুত এবং খুব সম্ভবত আরও দ্রুত হবে (তবে, আবার গণনা জটিলতা আলাদা, যাতে এটি ফাইলের অনন্য শব্দের সংখ্যার উপরও নির্ভর করতে পারে)।
1 আপনি যখন মানচিত্র তৈরি করবেন তখন তৃতীয় টেম্পলেট প্যারামিটার দিয়ে অর্ডার সংজ্ঞায়িত std::less<T>
করা হবে default
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
জিসিসি stdlibc ++ 6.4 এ হ্যাশ ম্যাপ ব্যবহার করার প্রমাণ
এটি এখানে উল্লেখ করা হয়েছিল: https://stackoverflow.com/a/3578247/895245 তবে নিম্নলিখিত উত্তরে: সি ++ তে স্ট্যান্ড :: মানচিত্রের অভ্যন্তরে কোন ডেটা কাঠামো রয়েছে? আমি জিসিসি 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);
}
};
}
আমরা যারা স্ট্যান্ডার্ড টেম্পলেট ব্যবহার করে এখনও আমাদের নিজস্ব ক্লাস হ্যাশ করব তা বোঝার চেষ্টা করার জন্য, একটি সহজ সমাধান রয়েছে:
আপনার শ্রেণিতে আপনাকে একটি সমতা অপারেটর ওভারলোড বোঝাতে হবে ==
। আপনি যদি এটি করতে না জানেন তবে গিকসফোরগিক্সের একটি দুর্দান্ত টিউটোরিয়াল রয়েছে https://www.geeksforgeeks.org/operator-overloading-c/
স্ট্যান্ডার্ড নেমস্পেসের অধীনে, আপনার শ্রেণীর নাম সহ হ্যাশ নামে একটি টেম্পলেট কাঠামো প্রকার হিসাবে ঘোষণা করুন (নীচে দেখুন)) আমি একটি দুর্দান্ত ব্লগপোস্ট পেয়েছি যা এক্সওআর এবং বিটশিফিং ব্যবহার করে হ্যাশ গণনা করার উদাহরণও দেখায়, তবে এটি এই প্রশ্নের ক্ষেত্রের বাইরে নয়, তবে এটিতে হ্যাশ ফাংশনগুলি কীভাবে কীভাবে সম্পন্ন করা যায় সে সম্পর্কে বিস্তারিত নির্দেশাবলীও অন্তর্ভুক্ত রয়েছে https://prateekvjoshi.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) ব্যবহার করা হবে আপনার চাবি#include <unordered_map>
int main() {
std::unordered_map<my_type, other_type> my_map;
}