std :: মানচিত্র সন্নিবেশ করুন বা std :: মানচিত্র সন্ধান করবেন?


93

এমন একটি মানচিত্র ধরে নেওয়া যেখানে আপনি বিদ্যমান প্রবেশগুলি সংরক্ষণ করতে চান। 20% সময়, আপনি প্রবেশ করা প্রবেশটি নতুন ডেটা। ফেরত পুনরুক্তি ব্যবহার করে স্ট্যান্ড :: ম্যাপ :: সন্ধান করুন এসডিডি :: ম্যাপ :: সন্নিবেশ করার কোনও সুবিধা আছে কি? অথবা sertোকানোর চেষ্টা করা এবং তারপরে পুনরাবৃত্তিটি রেকর্ডটি প্রবেশ করানো বা না করা ইঙ্গিতকারীটি নির্দেশ করে কিনা তার উপর ভিত্তি করে কাজ করা দ্রুত হয়?


4
আমি সংশোধন করেছিলাম এবং স্ট্যান্ড :: মানচিত্র :: স্ট্যান্ড :: ম্যাপ :: এর পরিবর্তে লোয়ার_বাউন্ড ব্যবহার করার ইচ্ছা করেছি।
সুপারপলক

উত্তর:


148

উত্তর আপনি হয় না। পরিবর্তে আপনি স্কট মায়ার্স দ্বারা কার্যকর এসটিএল এর আইটেম 24 দ্বারা প্রস্তাবিত কিছু করতে চান :

typedef map<int, int> MapType;    // Your map type may vary, just change the typedef

MapType mymap;
// Add elements to map here
int k = 4;   // assume we're searching for keys equal to 4
int v = 0;   // assume we want the value 0 associated with the key of 4

MapType::iterator lb = mymap.lower_bound(k);

if(lb != mymap.end() && !(mymap.key_comp()(k, lb->first)))
{
    // key already exists
    // update lb->second if you care to
}
else
{
    // the key does not exist in the map
    // add it to the map
    mymap.insert(lb, MapType::value_type(k, v));    // Use lb as a hint to insert,
                                                    // so it can avoid another lookup
}

4
প্রকৃতপক্ষে এটি কীভাবে কাজ করে তা কৌশলটি হ'ল এটি অনুসন্ধান এবং সন্নিবেশকরণের দ্বারা প্রয়োজনীয় অনুসন্ধানকে একত্রিত করে। অবশ্যই, এটি কেবল সন্নিবেশ ব্যবহার করে এবং তারপরে দ্বিতীয় রিটার্ন মানটি দেখে।
puetzk

4
দুটি প্রশ্ন: 1) মানচিত্রের জন্য কীভাবে নিম্ন_বাউন্ড ব্যবহার করে আলাদা? ২) কোনও 'মানচিত্রের' জন্য, 'এলবি! = মাইম্যাপ.এন্ড ()' এর ক্ষেত্রে ডান হাতের ও & ডান হাতটি সর্বদা সত্য হয় না?
রিচার্ড কর্ডেন

12
@ রিচার্ড: সন্ধান (() রিটার্নটি শেষ () কীটি উপস্থিত না থাকলে, নিম্ন_বাউন্ডটি সেই আইটেমটি যেখানে থাকা উচিত (যা ঘুরিয়ে দেওয়ার ইঙ্গিত হিসাবে ব্যবহার করা যেতে পারে) ফিরে আসে। @ পিতুজেক: বিদ্যমান কীগুলির জন্য আলাদা মানটিকে "কেবল সন্নিবেশ" করতে হবে না? ওপি এটি চায় কিনা তা নিশ্চিত নয়।
পিটারচেন

4
আনর্ডার্ড_ম্যাপের জন্য অনুরূপ কিছু আছে কি কেউ জানেন?
জিওভানি ফানচাল

4
@ পেটারচেন ম্যাপ :: সন্নিবেশ বিদ্যমান মানটি ওভাররাইট করে না যদি এটি বিদ্যমান থাকে তবে দেখুন cplusplus.com/references/map/map/insert
ক্রিস ড্রিউ

11

আপনি মানচিত্রে যে মান ধরণের সঞ্চয় করছেন তা তৈরি করা কতটা ব্যয়বহুল তার উপর এই প্রশ্নের উত্তরও নির্ভর করে:

typedef std::map <int, int> MapOfInts;
typedef std::pair <MapOfInts::iterator, bool> IResult;

void foo (MapOfInts & m, int k, int v) {
  IResult ir = m.insert (std::make_pair (k, v));
  if (ir.second) {
    // insertion took place (ie. new entry)
  }
  else if ( replaceEntry ( ir.first->first ) ) {
    ir.first->second = v;
  }
}

কোনও int এর মতো মানের ধরণের জন্য, উপরেরগুলি সন্নিবেশের পরে অনুসন্ধানের চেয়ে আরও কার্যকর হবে (সংকলক অপ্টিমাইজেশনের অভাবে)। উপরে বর্ণিত হিসাবে, মানচিত্রের মাধ্যমে অনুসন্ধান কেবল একবারে ঘটেছিল কারণ এটি।

যাইহোক, সন্নিবেশ করানোর কলটির জন্য আপনার ইতিমধ্যে নতুন "মান" নির্মিত হয়েছে তা প্রয়োজন:

class LargeDataType { /* ... */ };
typedef std::map <int, LargeDataType> MapOfLargeDataType;
typedef std::pair <MapOfLargeDataType::iterator, bool> IResult;

void foo (MapOfLargeDataType & m, int k) {

  // This call is more expensive than a find through the map:
  LargeDataType const & v = VeryExpensiveCall ( /* ... */ );

  IResult ir = m.insert (std::make_pair (k, v));
  if (ir.second) {
    // insertion took place (ie. new entry)
  }
  else if ( replaceEntry ( ir.first->first ) ) {
    ir.first->second = v;
  }
}

'সন্নিবেশ' কল করার জন্য আমরা আমাদের মূল্য প্রকারটি তৈরি করতে ব্যয়বহুল কলটির জন্য অর্থ প্রদান করছি - এবং আপনি যে প্রশ্নে বলেছেন তা থেকে আপনি এই নতুন মানটি 20% ব্যবহার করবেন না। উপরের ক্ষেত্রে মানচিত্রের মান প্রকার পরিবর্তন করা যদি কোনও বিকল্প না হয় তবে আমাদের উপাদানটি তৈরি করতে হবে কিনা তা যাচাই করার জন্য প্রথমে 'ফাইন্ড' সম্পাদন করা আরও দক্ষ।

বিকল্পভাবে, মানচিত্রের মান ধরণের আপনার প্রিয় স্মার্ট পয়েন্টার টাইপ ব্যবহার করে ডেটাগুলিতে হ্যান্ডলগুলি সঞ্চয় করতে পরিবর্তন করা যেতে পারে। সন্নিবেশ করানোর কলটিতে একটি নাল পয়েন্টার (নির্মাণের জন্য খুব সস্তা) ব্যবহার করা হয় এবং প্রয়োজনে কেবল নতুন ডেটা টাইপই নির্মিত হয়।


8

2 এর মধ্যে গতির মধ্যে সবেমাত্র কোনও পার্থক্য থাকবে, একটি পুনরুক্তিকারীর ফেরত আসবে, সারণি একইভাবে সন্নিবেশ করবে এবং এন্ট্রি ইতিমধ্যে বিদ্যমান কিনা তা নির্ধারণের জন্য মানচিত্রটি অনুসন্ধান করবে।

সুতরাং .. এটি ব্যক্তিগত পছন্দ নিচে। আমি সর্বদা sertোকানোর চেষ্টা করি এবং তারপরে প্রয়োজনে আপডেট করি তবে কিছু লোক ফিরে আসা জোড়াটি পরিচালনা করতে পছন্দ করে না।


5

আমি মনে করি আপনি যদি সন্নিবেশ সন্ধান করেন তবে অতিরিক্ত কী খরচ হবে যখন আপনি কীটি খুঁজে না পেয়ে এবং পরে সন্নিবেশ সম্পাদন করছেন। এটি একরকম হ'ল বর্ণানুক্রমিক বইগুলিতে সন্ধান করা এবং বইটি খুঁজে না পাওয়া, আবার কোথায় বইটি সন্নিবেশ করা যায় তা দেখতে আবার বইগুলি সন্ধান করে। আপনি কীগুলি কীভাবে পরিচালনা করছেন এবং যদি তারা ক্রমাগত পরিবর্তন করে চলেছে তবে এটিকে উত্সাহিত করে। এখন এতে কিছুটা নমনীয়তা রয়েছে যা যদি আপনি এটি না পান তবে আপনি লগ করতে পারেন, ব্যতিক্রম করতে পারেন, আপনি যা চান তা করতে পারেন ...


1

আপনি যদি দক্ষতার বিষয়ে উদ্বিগ্ন হন তবে আপনি হ্যাশ_ম্যাপ <> পরীক্ষা করে দেখতে চাইতে পারেন ।

সাধারণত মানচিত্র <> বাইনারি ট্রি হিসাবে প্রয়োগ করা হয়। আপনার প্রয়োজনের উপর নির্ভর করে একটি হ্যাশ_ম্যাপ আরও কার্যকর হতে পারে।


পছন্দ হত। তবে সি ++ স্ট্যান্ডার্ড লাইব্রেরিতে কোনও হ্যাশ_ম্যাপ নেই এবং পিএইচবি এর বাইরে কোডের অনুমতি দেয় না।
সুপারপলক

4
std :: tr1 :: unordered_map হ্যাশ মানচিত্র যা পরবর্তী স্ট্যান্ডার্ডে যুক্ত করার প্রস্তাব করা হয়েছে এবং এটি এসটিএল-এর বেশিরভাগ বর্তমান বাস্তবায়নের মধ্যে থাকা উচিত।
বেলডাজ

1

কোনও মন্তব্য করার মতো পর্যাপ্ত পয়েন্ট আমার কাছে নেই বলে মনে হচ্ছে, তবে টিক দেওয়া উত্তরটি আমার কাছে দীর্ঘায়িত বলে মনে হচ্ছে - যখন আপনি বিবেচনা করেন যে সন্নিবেশটি যেভাবেই পুনরুক্তি ফেরত দেয়, কেন আপনি নীচের দিকে ফিরে যান, যখন আপনি কেবল পুনরাবৃত্তিটি ব্যবহার করতে পারবেন। অদ্ভুত।


4
কারণ (অবশ্যই প্রাক-সি ++ 11) সন্নিবেশ ব্যবহারের অর্থ আপনাকে এখনও একটি std::map::value_typeঅবজেক্ট তৈরি করতে হবে , গৃহীত উত্তরটি তা এড়িয়ে চলে।
কিলিয়ানডিস

-1

দক্ষতা সম্পর্কে কোনও উত্তর আপনার এসটিএলের সঠিক প্রয়োগের উপর নির্ভর করবে। নিশ্চিতভাবে জানার একমাত্র উপায় হ'ল এটি উভয় উপায়ে বেনমার্ক করা। আমি অনুমান করব যে পার্থক্যটি উল্লেখযোগ্য হওয়ার সম্ভাবনা কম, তাই আপনার পছন্দ অনুসারে শৈলীর ভিত্তিতে সিদ্ধান্ত নিন।


4
এটা ঠিক সত্য নয়। এসটিএল বেশিরভাগ অন্যান্য গ্রন্থাগারের বিপরীতে যেটি এটির বেশিরভাগ ক্রিয়াকলাপের জন্য সুস্পষ্ট বিগ-ও প্রয়োজনীয়তা সরবরাহ করে। 2 (ও (লগ এন) এবং 1 * হে (লগ এন) এর মধ্যে একটি গ্যারান্টিযুক্ত পার্থক্য রয়েছে, নির্ধারিতভাবে যে ও (লগ এন) আচরণটি অর্জন করতে ফাংশনগুলি কী প্রয়োগ করে। আপনার প্ল্যাটফর্মে সেই পার্থক্যটি তাৎপর্যপূর্ণ কিনা তা ভিন্ন প্রশ্ন is তবে পার্থক্য সবসময় থাকবে।
srm

@ এসআরএম বিগ-ও প্রয়োজনীয়তা সংজ্ঞায়িত করে এখনও আপনাকে জানায় না যে কোনও ক্রিয়াকলাপ নিরঙ্কুশ শর্তে কতটা সময় নেবে। আপনি যে গ্যারান্টিযুক্ত পার্থক্যের কথা বলছেন তা বিদ্যমান নেই।
মার্ক র্যানসোম

-2

মানচিত্র [কী] - এসটিএল এটি সাজিয়ে নেওয়া যাক। এটি আপনার উদ্দেশ্যটি সবচেয়ে কার্যকরভাবে যোগাযোগ করছে।

হ্যাঁ, যথেষ্ট ন্যায্য।

যদি আপনি একটি সন্ধান করেন এবং তারপরে একটি সন্নিবেশ করান যখন আপনি 2 এক্স ও (লগ এন) করছেন যখন আপনি কোনও মিস পেয়ে গেলে সন্ধানটি কেবল আপনাকে জানতে দেয় যে সন্নিবেশটি কোথায় যাওয়া উচিত নয় সেখানে সন্নিবেশ করা প্রয়োজন কিনা (নীচের দিকে আপনি সেখানে সহায়তা করতে পারেন) । কেবল একটি সরল sertোকানো এবং তারপরে ফলাফলটি পরীক্ষা করা।


না, এন্ট্রি বিদ্যমান থাকলে এটি বিদ্যমান প্রবেশের রেফারেন্স দেয়।
ক্রিস কুমার

4
এই উত্তরের জন্য -1। ক্রিস কে যেমন বলেছিলেন, মানচিত্র [কী] = মান ব্যবহার করে বিদ্যমান এন্ট্রিটি ওভাররাইট হয়ে যাবে, প্রশ্নের হিসাবে এটি "সংরক্ষণ" হবে না। আপনি মানচিত্র [কী] ব্যবহার করে অস্তিত্বের জন্য পরীক্ষা করতে পারবেন না, কারণ কী উপস্থিত না থাকলে এটি একটি ডিফল্ট নির্মান বস্তু ফিরিয়ে দেয় এবং কীটির প্রবেশদ্বার হিসাবে এটি তৈরি করে
নেটজেফ

বিন্দুটি পরীক্ষা করার জন্য মানচিত্রটি ইতিমধ্যে পপুলেটেড রয়েছে এবং এটি সেখানে না থাকলে কেবল যুক্ত / ওভাররাইট করুন। মানচিত্র [কী] ব্যবহার করে ধরে নেওয়া হয় মানটি ইতিমধ্যে সর্বদা রয়েছে।
srm
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.