C++
std :: नक्शा
खोज…
टिप्पणियों
किसी भी
std::map
याstd::multimap
शीर्षक फ़ाइल का उपयोग करने के लिए<map>
शामिल होना चाहिए।std::map
andstd::multimap
दोनों अपने तत्वों को कुंजी के आरोही क्रम के अनुसार क्रमबद्ध रखते हैं।std::multimap
मामले में, समान कुंजी के मानों के लिए कोई छँटाई नहीं होती है।std::map
औरstd::multimap
बीच मूल अंतर यह है किstd::map
एक ही कुंजी के लिए डुप्लिकेट मान की अनुमति नहीं देता है जहाँstd::multimap
करता है।नक्शे को बाइनरी सर्च ट्री के रूप में लागू किया जाता है। इसलिए औसत में
search()
,insert()
,erase()
एन (लॉग एन) समय लेता है। निरंतर समय संचालन के लिएstd::unordered_map
उपयोग करें।size()
औरempty()
फ़ंक्शन में Θ (1) समय की जटिलता है, नोड्स की संख्या को हर बार पेड़ से चलने से बचने के लिए कैश किया जाता है, जब ये फ़ंक्शन कहलाते हैं।
तत्वों तक पहुंचना
एक std::map
इनपुट के रूप में (key, value)
जोड़े लेता है।
निम्न उदाहरण पर विचार करें std::map
आरंभीकरण:
std::map < std::string, int > ranking { std::make_pair("stackoverflow", 2),
std::make_pair("docs-beta", 1) };
एक std::map
, तत्वों को इस प्रकार डाला जा सकता है:
ranking["stackoverflow"]=2;
ranking["docs-beta"]=1;
उपरोक्त उदाहरण में, यदि कुंजी stackoverflow
पहले से मौजूद है, तो इसका मान 2 में अपडेट किया जाएगा। यदि यह पहले से मौजूद नहीं है, तो एक नई प्रविष्टि बनाई जाएगी।
एक std::map
, तत्वों को एक इंडेक्स के रूप में कुंजी देकर सीधे एक्सेस किया जा सकता है:
std::cout << ranking[ "stackoverflow" ] << std::endl;
मानचित्र पर operator[]
का उपयोग करते हुए ध्यान दें कि वास्तव में नक्शे में queried कुंजी के साथ एक नया मूल्य सम्मिलित करेगा। इसका मतलब यह है कि आप इसे एक const std::map
पर उपयोग नहीं कर सकते हैं, भले ही वह की पहले से ही मैप में स्टोर हो। इस प्रविष्टि को रोकने के लिए, जाँच करें कि क्या तत्व मौजूद है (उदाहरण के लिए find()
का उपयोग करके) या नीचे दिए गए अनुसार at()
उपयोग करें।
एक std::map
तत्व std::map
at()
साथ पहुँचा जा सकता है:
std::cout << ranking.at("stackoverflow") << std::endl;
ध्यान दें कि at()
एक std::out_of_range
फेंक देगा std::out_of_range
अपवाद यदि कंटेनर में अनुरोधित तत्व नहीं है।
दोनों कंटेनरों में std::map
and std::multimap
, तत्वों का उपयोग करके इसे एक्सेस किया जा सकता है:
// Example using begin()
std::multimap < int, std::string > mmp { std::make_pair(2, "stackoverflow"),
std::make_pair(1, "docs-beta"),
std::make_pair(2, "stackexchange") };
auto it = mmp.begin();
std::cout << it->first << " : " << it->second << std::endl; // Output: "1 : docs-beta"
it++;
std::cout << it->first << " : " << it->second << std::endl; // Output: "2 : stackoverflow"
it++;
std::cout << it->first << " : " << it->second << std::endl; // Output: "2 : stackexchange"
// Example using rbegin()
std::map < int, std::string > mp { std::make_pair(2, "stackoverflow"),
std::make_pair(1, "docs-beta"),
std::make_pair(2, "stackexchange") };
auto it2 = mp.rbegin();
std::cout << it2->first << " : " << it2->second << std::endl; // Output: "2 : stackoverflow"
it2++;
std::cout << it2->first << " : " << it2->second << std::endl; // Output: "1 : docs-beta"
एक std :: मैप या std :: मल्टीपैप को इनिशियलाइज़ करना
std::map
और std::multimap
दोनों को कॉमा द्वारा अलग किए गए कुंजी-मूल्य जोड़े प्रदान करके आरंभ किया जा सकता है। कुंजी-मूल्य जोड़े या तो {key, value}
द्वारा प्रदान किए जा सकते हैं या std::make_pair(key, value)
द्वारा स्पष्ट रूप से बनाए जा सकते हैं। जैसा कि std::map
डुप्लिकेट कुंजियों की अनुमति नहीं देता है और अल्पविराम ऑपरेटर बाएं से दाएं प्रदर्शन करता है, दाईं ओर की जोड़ी बाईं ओर समान कुंजी के साथ जोड़ी के साथ ओवरराइट की जाएगी।
std::multimap < int, std::string > mmp { std::make_pair(2, "stackoverflow"),
std::make_pair(1, "docs-beta"),
std::make_pair(2, "stackexchange") };
// 1 docs-beta
// 2 stackoverflow
// 2 stackexchange
std::map < int, std::string > mp { std::make_pair(2, "stackoverflow"),
std::make_pair(1, "docs-beta"),
std::make_pair(2, "stackexchange") };
// 1 docs-beta
// 2 stackoverflow
दोनों को पुनरावृत्ति के साथ आरंभ किया जा सकता है।
// From std::map or std::multimap iterator
std::multimap< int , int > mmp{ {1, 2}, {3, 4}, {6, 5}, {8, 9}, {6, 8}, {3, 4},
{6, 7} };
// {1, 2}, {3, 4}, {3, 4}, {6, 5}, {6, 8}, {6, 7}, {8, 9}
auto it = mmp.begin();
std::advance(it,3); //moved cursor on first {6, 5}
std::map< int, int > mp(it, mmp.end()); // {6, 5}, {8, 9}
//From std::pair array
std::pair< int, int > arr[10];
arr[0] = {1, 3};
arr[1] = {1, 5};
arr[2] = {2, 5};
arr[3] = {0, 1};
std::map< int, int > mp(arr,arr+4); //{0 , 1}, {1, 3}, {2, 5}
//From std::vector of std::pair
std::vector< std::pair<int, int> > v{ {1, 5}, {5, 1}, {3, 6}, {3, 2} };
std::multimap< int, int > mp(v.begin(), v.end());
// {1, 5}, {3, 6}, {3, 2}, {5, 1}
तत्वों को हटाना
सभी तत्वों को हटाना:
std::multimap< int , int > mmp{ {1, 2}, {3, 4}, {6, 5}, {8, 9}, {3, 4}, {6, 7} };
mmp.clear(); //empty multimap
तत्व की मदद से कहीं से तत्व निकालना:
std::multimap< int , int > mmp{ {1, 2}, {3, 4}, {6, 5}, {8, 9}, {3, 4}, {6, 7} };
// {1, 2}, {3, 4}, {3, 4}, {6, 5}, {6, 7}, {8, 9}
auto it = mmp.begin();
std::advance(it,3); // moved cursor on first {6, 5}
mmp.erase(it); // {1, 2}, {3, 4}, {3, 4}, {6, 7}, {8, 9}
सभी तत्वों को एक सीमा में निकालना:
std::multimap< int , int > mmp{ {1, 2}, {3, 4}, {6, 5}, {8, 9}, {3, 4}, {6, 7} };
// {1, 2}, {3, 4}, {3, 4}, {6, 5}, {6, 7}, {8, 9}
auto it = mmp.begin();
auto it2 = it;
it++; //moved first cursor on first {3, 4}
std::advance(it2,3); //moved second cursor on first {6, 5}
mmp.erase(it,it2); // {1, 2}, {6, 5}, {6, 7}, {8, 9}
कुंजी के रूप में प्रदान किए गए सभी तत्वों को हटाना:
std::multimap< int , int > mmp{ {1, 2}, {3, 4}, {6, 5}, {8, 9}, {3, 4}, {6, 7} };
// {1, 2}, {3, 4}, {3, 4}, {6, 5}, {6, 7}, {8, 9}
mmp.erase(6); // {1, 2}, {3, 4}, {3, 4}, {8, 9}
उन तत्वों को हटाना जो एक विधेय pred
संतुष्ट करते हैं:
std::map<int,int> m;
auto it = m.begin();
while (it != m.end())
{
if (pred(*it))
it = m.erase(it);
else
++it;
}
तत्वों को सम्मिलित करना
एक तत्व को एक std::map
तभी डाला जा सकता है, जब उसकी कुंजी मैप में पहले से मौजूद न हो। उदाहरण के लिए दिया गया:
std::map< std::string, size_t > fruits_count;
एक कुंजी-मूल्य जोड़ी को एक सम्मिलित
std::map
मेंinsert()
सदस्य फ़ंक्शन के माध्यम से डाला जाता है। इसके लिए एक तर्क के रूप में एकpair
आवश्यकता होती है:fruits_count.insert({"grapes", 20}); fruits_count.insert(make_pair("orange", 30)); fruits_count.insert(pair<std::string, size_t>("banana", 40)); fruits_count.insert(map<std::string, size_t>::value_type("cherry", 50));
insert()
फ़ंक्शन एकpair
को पुनरावृत्त और एकbool
मान सेbool
:- यदि सम्मिलन सफल रहा, तो पुनरावृत्त नव सम्मिलित तत्व को इंगित करता है, और
bool
मानtrue
। - यदि पहले से ही एक ही
key
साथ एक तत्व था, तो सम्मिलन विफल रहता है। जब ऐसा होता है, तो इट्रेटर तत्व को संघर्ष का कारण बताता है, औरbool
मानfalse
।
प्रविष्टि और खोज ऑपरेशन को संयोजित करने के लिए निम्न विधि का उपयोग किया जा सकता है:
auto success = fruits_count.insert({"grapes", 20}); if (!success.second) { // we already have 'grapes' in the map success.first->second += 20; // access the iterator to update the value }
- यदि सम्मिलन सफल रहा, तो पुनरावृत्त नव सम्मिलित तत्व को इंगित करता है, और
सुविधा के लिए,
std::map
कंटेनर, सबस्क्रिप्ट ऑपरेटर को मानचित्र में तत्वों तक पहुँचने के लिए और यदि वे मौजूद नहीं हैं तो नए को सम्मिलित करने के लिए प्रदान करते हैं:fruits_count["apple"] = 10;
सरल होते हुए, यह उपयोगकर्ता को यह जाँचने से रोकता है कि क्या तत्व पहले से मौजूद है। यदि कोई तत्व अनुपलब्ध है, तो
std::map::operator[]
अंतर्निहित रूप से इसे बनाता है, इसे आपूर्ति किए गए मान के साथ अधिलेखित करने से पहले डिफ़ॉल्ट निर्माणकर्ता के साथ प्रारंभ करता है।
insert()
का उपयोग एक साथ कई तत्वों को जोड़ने के लिए किया जा सकता है जब एक जोड़े की लट सूची का उपयोग किया जाता है। डालने का यह संस्करण () शून्य देता है:fruits_count.insert({{"apricot", 1}, {"jackfruit", 1}, {"lime", 1}, {"mango", 7}});
insert()
का उपयोग तत्वों को जोड़ने के लिए किया जा सकता है, जोvalue_type
का उपयोग करकेvalue_type
मानों के आरंभ और अंत कोvalue_type
हैं:std::map< std::string, size_t > fruit_list{ {"lemon", 0}, {"olive", 0}, {"plum", 0}}; fruits_count.insert(fruit_list.begin(), fruit_list.end());
उदाहरण:
std::map<std::string, size_t> fruits_count;
std::string fruit;
while(std::cin >> fruit){
// insert an element with 'fruit' as key and '1' as value
// (if the key is already stored in fruits_count, insert does nothing)
auto ret = fruits_count.insert({fruit, 1});
if(!ret.second){ // 'fruit' is already in the map
++ret.first->second; // increment the counter
}
}
एक सम्मिलन ऑपरेशन के लिए समय जटिलता हे (लॉग एन) है क्योंकि std::map
पेड़ों के रूप में लागू किया जाता है।
एक pair
का निर्माण स्पष्ट रूप से make_pair()
और emplace()
का उपयोग करके किया जा सकता है:
std::map< std::string , int > runs;
runs.emplace("Babe Ruth", 714);
runs.insert(make_pair("Barry Bonds", 762));
हम जानते हैं कि जहां नए तत्व सम्मिलित किया जाएगा, तो हम उपयोग कर सकते हैं emplace_hint()
पुनरावर्तक निर्दिष्ट करने के लिए hint
। यदि नए तत्व को hint
से ठीक पहले डाला जा सकता है, तो निरंतर समय में सम्मिलन किया जा सकता है। अन्यथा यह उसी तरह से व्यवहार करता है जैसे कि emplace()
:
std::map< std::string , int > runs;
auto it = runs.emplace("Barry Bonds", 762); // get iterator to the inserted element
// the next element will be before "Barry Bonds", so it is inserted before 'it'
runs.emplace_hint(it, "Babe Ruth", 714);
एसटीडी पर नक्शा :: नक्शा या एसटीडी :: मल्टीमैप
std::map
या std::multimap
निम्नलिखित तरीकों से पता std::multimap
जा सकता है:
std::multimap< int , int > mmp{ {1, 2}, {3, 4}, {6, 5}, {8, 9}, {3, 4}, {6, 7} };
//Range based loop - since C++11
for(const auto &x: mmp)
std::cout<< x.first <<":"<< x.second << std::endl;
//Forward iterator for loop: it would loop through first element to last element
//it will be a std::map< int, int >::iterator
for (auto it = mmp.begin(); it != mmp.end(); ++it)
std::cout<< it->first <<":"<< it->second << std::endl; //Do something with iterator
//Backward iterator for loop: it would loop through last element to first element
//it will be a std::map< int, int >::reverse_iterator
for (auto it = mmp.rbegin(); it != mmp.rend(); ++it)
std::cout<< it->first <<" "<< it->second << std::endl; //Do something with iterator
एक std::map
या एक std::multimap
पर पुनरावृति करते समय, बेकार निहित रूपांतरण से बचने के लिए auto
का उपयोग पसंद किया जाता है (अधिक विवरण के लिए यह SO उत्तर देखें)।
एसटीडी में खोज :: नक्शा या एसटीडी में :: मल्टीमैप
std::map
या std::multimap
में कुंजी खोजने के कई तरीके हैं।
कुंजी की पहली घटना का पुनरावृत्ति प्राप्त करने के लिए,
find()
फ़ंक्शन का उपयोग किया जा सकता है। यदि कुंजी मौजूद नहीं है तो यहend()
देता है।std::multimap< int , int > mmp{ {1, 2}, {3, 4}, {6, 5}, {8, 9}, {3, 4}, {6, 7} }; auto it = mmp.find(6); if(it!=mmp.end()) std::cout << it->first << ", " << it->second << std::endl; //prints: 6, 5 else std::cout << "Value does not exist!" << std::endl; it = mmp.find(66); if(it!=mmp.end()) std::cout << it->first << ", " << it->second << std::endl; else std::cout << "Value does not exist!" << std::endl; // This line would be executed.
यह पता लगाने का एक और तरीका है कि क्या कोई प्रविष्टि
std::map
याstd::map
में मौजूद हैstd::multimap
count()
फ़ंक्शन का उपयोग कर रहा है, जो यह बताता है कि किसी दिए गए कुंजी के साथ कितने मान जुड़े हैं। चूंकिstd::map
प्रत्येक कुंजी के साथ केवल एक मान को जोड़ता है, इसकीcount()
फ़ंक्शन केवल 0 (यदि कुंजी मौजूद नहीं है) या 1 (यदि यह है) वापस कर सकता है।std::multimap
,count()
1 से अधिक मान लौटा सकते हैं क्योंकि एक ही कुंजी से जुड़े कई मान हो सकते हैं।std::map< int , int > mp{ {1, 2}, {3, 4}, {6, 5}, {8, 9}, {3, 4}, {6, 7} }; if(mp.count(3) > 0) // 3 exists as a key in map std::cout << "The key exists!" << std::endl; // This line would be executed. else std::cout << "The key does not exist!" << std::endl;
आप केवल परवाह कुछ तत्व मौजूद है या नहीं, तो
find
के लिए अपने इरादे और, के लिए यह दस्तावेज: सख्ती से बेहतर हैmultimaps
, यह एक बार पहले मिलान तत्व पाया गया है रोक सकता है।std::multimap
के मामले में, एक ही कुंजी वाले कई तत्व हो सकते हैं। इस श्रेणी को प्राप्त करने के लिए,equal_range()
फ़ंक्शन का उपयोग किया जाता है, जो क्रमशःstd::pair
को निम्नतर बाउंड (सम्मिलित) और ऊपरी बाउंड (अनन्य) देता है। यदि कुंजी मौजूद नहीं है, तो दोनों पुनरावृत्तियों कोend()
करने के लिए इंगित करेंगेend()
।auto eqr = mmp.equal_range(6); auto st = eqr.first, en = eqr.second; for(auto it = st; it != en; ++it){ std::cout << it->first << ", " << it->second << std::endl; } // prints: 6, 5 // 6, 7
तत्वों की संख्या की जाँच
कंटेनर std::map
में एक सदस्य फ़ंक्शन empty()
, जो true
या false
, यह निर्भर करता है कि नक्शा खाली है या नहीं। सदस्य फ़ंक्शन size()
एक std::map
में संग्रहीत तत्व की संख्या देता है std::map
कंटेनर:
std::map<std::string , int> rank {{"facebook.com", 1} ,{"google.com", 2}, {"youtube.com", 3}};
if(!rank.empty()){
std::cout << "Number of elements in the rank map: " << rank.size() << std::endl;
}
else{
std::cout << "The rank map is empty" << std::endl;
}
नक्शे के प्रकार
नियमित मानचित्र
नक्शा एक सहयोगी कंटेनर है, जिसमें कुंजी-मूल्य जोड़े हैं।
#include <string>
#include <map>
std::map<std::string, size_t> fruits_count;
उपरोक्त उदाहरण में, std::string
प्रमुख प्रकार है, और size_t
एक मान है ।
मुख्य नक्शे में एक सूचकांक के रूप में कार्य करता है। प्रत्येक कुंजी अद्वितीय होनी चाहिए, और आदेशित होनी चाहिए।
यदि आपको एक ही कुंजी के साथ
multimap
तत्वों की आवश्यकता है, तोmultimap
का उपयोग करने पर विचार करें (नीचे समझाया गया है)यदि आपका मूल्य प्रकार कोई आदेश निर्दिष्ट नहीं करता है, या आप डिफ़ॉल्ट आदेश को ओवरराइड करना चाहते हैं, तो आप एक प्रदान कर सकते हैं:
#include <string> #include <map> #include <cstring> struct StrLess { bool operator()(const std::string& a, const std::string& b) { return strncmp(a.c_str(), b.c_str(), 8)<0; //compare only up to 8 first characters } } std::map<std::string, size_t, StrLess> fruits_count2;
यदि
StrLess
तुलनित्र दो कुंजी के लिएfalse
, तो उन्हें समान माना जाता है, भले ही उनकी वास्तविक सामग्री अलग हो।
मल्टी मानचित्र
मल्टीमैप एक ही कुंजी के साथ कई कुंजी-मूल्य जोड़े को मानचित्र में संग्रहीत करने की अनुमति देता है। अन्यथा, इसका इंटरफ़ेस और निर्माण नियमित मानचित्र के समान है।
#include <string>
#include <map>
std::multimap<std::string, size_t> fruits_count;
std::multimap<std::string, size_t, StrLess> fruits_count2;
हैश-मैप (अनियंत्रित मानचित्र)
एक हैश मानचित्र एक नियमित मानचित्र के समान कुंजी-मूल्य जोड़े संग्रहीत करता है। यह कुंजी के संबंध में तत्वों का आदेश नहीं देता है। इसके बजाय, कुंजी के लिए एक हैश मूल्य का उपयोग आवश्यक कुंजी-मूल्य जोड़े को जल्दी से एक्सेस करने के लिए किया जाता है।
#include <string>
#include <unordered_map>
std::unordered_map<std::string, size_t> fruits_count;
अनियंत्रित नक्शे आमतौर पर तेज़ होते हैं, लेकिन तत्व किसी भी अनुमानित क्रम में संग्रहीत नहीं होते हैं। उदाहरण के लिए, एक unordered_map
में सभी तत्वों से अधिक पुनरावृति तत्वों को एक प्रतीत होता है यादृच्छिक क्रम में देता है।
कुंजी के रूप में उपयोगकर्ता परिभाषित प्रकार के साथ एसटीडी :: नक्शा बनाना
किसी मानचित्र में कुंजी के रूप में एक वर्ग का उपयोग करने में सक्षम होने के लिए, कुंजी की आवश्यकता होती है, यह सब copiable
और assignable
। मानचित्र के भीतर आदेश को तीसरे तर्क द्वारा टेम्पलेट में परिभाषित किया गया है (और यदि उपयोग किया जाता है, तो तर्क निर्माता के लिए)। यह डिफॉल्ट्स को std::less<KeyType>
, जो डिफॉल्ट करता है <
ऑपरेटर, लेकिन डिफॉल्ट्स का उपयोग करने की कोई आवश्यकता नहीं है। बस एक तुलना ऑपरेटर (अधिमानतः एक कार्यात्मक वस्तु के रूप में) लिखें:
struct CmpMyType
{
bool operator()( MyType const& lhs, MyType const& rhs ) const
{
// ...
}
};
सी ++ में, "तुलना" विधेय एक सख्त कमजोर आदेश होना चाहिए। विशेष रूप से, compare(X,X)
किसी भी X
लिए false
लौटना चाहिए। यानी अगर CmpMyType()(a, b)
सही लौटाता है, तो CmpMyType()(b, a)
को गलत लौटना चाहिए, और यदि दोनों गलत हैं, तो तत्वों को समान माना जाता है (समान समतुल्य वर्ग के सदस्य)।
सख्त कमजोर आदेश
यह दो वस्तुओं के बीच संबंध को परिभाषित करने के लिए एक गणितीय शब्द है।
इसकी परिभाषा है:
दो वस्तुएं x और y समतुल्य हैं यदि f (x, y) और f (y, x) दोनों गलत हैं। ध्यान दें कि एक वस्तु हमेशा (अपने आप के समतुल्य अपरिवर्तनीयता द्वारा) होती है।
C ++ के संदर्भ में इसका मतलब है कि यदि आपके पास दिए गए प्रकार की दो वस्तुएं हैं, तो आपको ऑपरेटर के साथ तुलना करते समय निम्नलिखित मान वापस करने चाहिए।
X a;
X b;
Condition: Test: Result
a is equivalent to b: a < b false
a is equivalent to b b < a false
a is less than b a < b true
a is less than b b < a false
b is less than a a < b false
b is less than a b < a true
आप किस प्रकार समकक्ष / कम परिभाषित करते हैं, यह पूरी तरह से आपकी वस्तु के प्रकार पर निर्भर करता है।