কেন আনর্ডারড_সেটের পরিবর্তে কেউ সেট ব্যবহার করবেন?


145

সি ++ 0 এক্স প্রবর্তন করছে unordered_setযা উপলভ্য boostএবং অন্যান্য অনেক জায়গায়। আমি যা বুঝতে পারি তা unordered_setহ'ল হ্যাশ টেবিলটি O(1)লুকআপ জটিলতার সাথে। অন্যদিকে, দেখার জটিলতা setসহ একটি গাছ ছাড়া আর কিছুই নয় log(n)কেন পৃথিবীতে কেউ এর setপরিবর্তে ব্যবহার করবে unordered_set? অর্থাৎ setআর কি দরকার আছে ?


22
আপনার প্রশ্নটি মৌলিকভাবে জিজ্ঞাসা করছে যে এখন আর গাছের দরকার আছে কিনা।
ভিঙ্কো ভার্সালোভিক

2
আমি মনে করি আমি প্রথম লাইনে এটি স্পষ্টভাবে বলেছি, এটি কোনওভাবে বোকা প্রশ্ন। আমি কিছু মিস করছি এবং এখন আমি উত্তর পেয়েছি :)
আরাক

2
আসল কারণ হ'ল জিনিসগুলি বি-ডাব্লুডাব্লু যেমন মনে হয় তেমন নয়। এর মধ্যে প্রচুর গ্রে এবং অন্যান্য রঙ রয়েছে। আপনার মনে রাখতে হবে এই পাত্রে সরঞ্জামগুলি। কখনও কখনও কর্মক্ষমতা গুরুত্বপূর্ণ নয় এবং সুবিধা আরও বেশি অর্থবহ। যদি লোকেরা সকলেই সবচেয়ে কার্যকর সমাধানের সন্ধান করে তবে আমরা কখনই সি ++ (পাইথনের উল্লেখ না করে) প্রথমে ব্যবহার করি না এবং মেশিনের ভাষায় অবিচ্ছিন্নভাবে কোড লিখি এবং অনুকূলিত করি
আতুরস্যামস

(কেন পৃথিবীতে কেউ এই নাম দ্বারা উল্লিখিত প্রতিশ্রুতি ছাড়াই বাস্তবায়ন / ইন্টারফেসের জন্য জেনেরিক নাম ব্যবহার করবে, না ছাড়া যাদের জন্য একটি বিশ্রী পরিস্থিতি তৈরি হবে?)
গ্রেইবার্ড

উত্তর:


219

যখন, সেটের আইটেমগুলি নিয়ে পুনরাবৃত্তি করতে চায় এমন ব্যক্তির জন্য, অর্ডারটি গুরুত্বপূর্ণ।


এটি সন্নিবেশ আদেশ অনুসারে অর্ডার করা হয়েছে, বা অপারেটর ব্যবহার করে বাস্তব তুলনা অনুযায়ী < >?
SomethingSomething

2
এটি std :: ডিফল্টরূপে কম ব্যবহার করার আদেশ দেওয়া হয়েছে; আপনি এটিকে ওভাররাইড করতে পারেন এবং আপনার নিজস্ব তুলনা অপারেটর সরবরাহ করতে পারেন। cplusplus.com/references/set/set
moonshadow

বা কখনও কখনও যখন আপনি কেবল পুনরাবৃত্তি করতে চান, এমনকি যদি অর্ডারটি কোনও ব্যাপার না।
এমএফএনএক্স

319

আনঅর্ডারার্ড সেটগুলিকে তাদের ও (1) গড় অ্যাক্সেসের সময়টি কয়েকটি উপায়ে দিতে হবে:

  • setএকই সংখ্যক উপাদান সংরক্ষণ করার চেয়ে কম মেমরি ব্যবহার unordered_setকরে।
  • একটি জন্য উপাদানের অল্প সংখ্যক , একটি লুক- setহতে পারে দ্রুত একটি ইন লুক-চেয়ে unordered_set
  • যদিও অনেক অপারেশন দ্রুততর হয় গড় কেস জন্য unordered_setতারা প্রায়ই আছে গ্যারান্টী আছে ভাল সবচেয়ে খারাপ ক্ষেত্রে জটিলতার জন্য set(উদাহরণস্বরূপ insert)।
  • যে set প্রকারের উপাদানের যদি আপনি তাদের অনুক্রমে অ্যাক্সেস করতে চান দরকারী।
  • আপনি করতে পারেন lexicographically তুলনা বিভিন্ন setসঙ্গে গুলি <, <=, >এবং >=unordered_setএই ক্রিয়াকলাপগুলি সমর্থন করার প্রয়োজন নেই।


9
+1, সমস্ত দুর্দান্ত পয়েন্ট। লোকেরা হ্যাশ টেবিলগুলিতে ও-(1) গড়-কেস অ্যাক্সেস সময় রাখে এমন সত্যটি উপেক্ষা করার ঝোঁক থাকে , যার অর্থ তারা মাঝে মাঝে বড় বিলম্ব করতে পারে। পার্থক্যটি রিয়েল-টাইম সিস্টেমগুলির জন্য গুরুত্বপূর্ণ হতে পারে।
j_random_hacker

ভাল পয়েন্টগুলি, তবে এখানে ( en.cppreferences.com/w/cpp/container/unordered_set/operator_cmp ) বলা হয়েছে যে আমরা আনর্ডারড_সেটগুলি তুলনা করতে পারি।
মিচিয়েল হ'ল ব্রোক

5
একটি "অল্প সংখ্যক উপাদান" সংজ্ঞায়িত করুন
সানজয় ভার্মা

4
@ সঞ্জয়বর্মা সাধারণত দু'জনের মধ্যে 100 টি উপাদানই ভাল কাট-অফ হয়। সন্দেহ হলে আপনার নির্দিষ্ট ব্যবহারের ক্ষেত্রে দুজনের পরীক্ষার কার্যকারিতা প্রতিস্থাপন করতে পারে না।
নাট

3
@ মিচিয়েলুয়েটব্রোকে কেবল সমতার তুলনা বলা হয়েছে, অর্ডার না দিয়ে ( <)।
লিসিয়ারাস

26

আপনি যখনই হ্যাশ টেবিলে গাছ পছন্দ করেন।

উদাহরণস্বরূপ, হ্যাশ টেবিলগুলি সবচেয়ে খারাপ ক্ষেত্রে "O (n)"। ও (1) গড় ক্ষেত্রে। গাছগুলি সবচেয়ে খারাপভাবে "ও ( লগ এন)" হয়।


18
/ ভারসাম্যযুক্ত / গাছ সবচেয়ে খারাপ ক্ষেত্রে ও (ln এন) হয়। আপনি ও (এন) গাছগুলি (প্রয়োজনীয় লিঙ্কযুক্ত তালিকাগুলি) দিয়ে শেষ করতে পারেন।
স্টারগার

5
আপনি যদি যুক্তিসঙ্গত বুদ্ধিমান হ্যাশ ফাংশন লিখতে পারেন তবে আপনি প্রায়শই একটি হ্যাশটেবল থেকে ও (1) পারফ পেতে পারেন। আপনি যদি নিজের সেটটিতে "ক্রম" পুনরাবৃত্তি করতে চান তবে আপনি যদি একটি হ্যাশ ফাংশন লিখতে না পারেন তবে আপনার একটি গাছ ব্যবহার করা উচিত। তবে আপনার একটি গাছ ব্যবহার করা উচিত নয় কারণ আপনি "ও (এন) সবচেয়ে খারাপ ক্ষেত্রে"
জাস্টিন এল।

6
স্টেজার: পেডেন্টিক হতে, হ্যাঁ। তবে, আমরা সি ++ সেট সম্পর্কে কথা বলছি যা সাধারণত ভারসাম্যযুক্ত বাইনারি অনুসন্ধান গাছ হিসাবে প্রয়োগ করা হয় । জটিলতার বিষয়ে কথা বলার জন্য আমাদের আসল অপারেশনটি নির্দিষ্ট করা উচিত। এই প্রসঙ্গে এটি সুস্পষ্ট যে আমরা অনুসন্ধানের বিষয়ে কথা বলছি।
মেহরদাদ আফশারি

1
জাস্টিন এল: এটি সম্ভবত একটি কারণ যা আপনি গাছ পছন্দ করেন। আমার উত্তরের মূলটি প্রথম লাইন। আপনি যখনই কোনও হ্যাশ টেবিলের জন্য একটি ট্রি ডেটা কাঠামো পছন্দ করেন। হ্যাশ টেবিলের তুলনায় গাছগুলি বেশিরভাগ ক্ষেত্রে পছন্দ হয়। হ্যাশ টেবিলগুলি বিশেষত "পরিসীমা ছেদগুলি" এর মতো জিনিসগুলিতে স্তন্যপান করে।
মেহরদাদ আফশারি

2
stl গাছ প্রায় সর্বজনীনভাবে লাল-কালো গাছ প্রয়োগ করা হয়, একটি উন্নত স্ব-ভারসাম্য গাছ tree সত্যিই এমন কেস রয়েছে যেখানে ও (এন) আরও খারাপ ক্ষেত্রে সন্ধান করবে তা গ্রহণযোগ্য নয়। কোনও ওয়েব সার্ভিস যা ব্যবহারকারীর মানগুলি সংরক্ষণ করার জন্য ইন্টারফেস সরবরাহ করে এবং হ্যাশ ম্যাপ ব্যবহার করা উচিত নয়, কারণ দূষিত ব্যবহারকারী কার্যকরভাবে বিশেষভাবে তৈরি করা মানগুলি সংরক্ষণ করে একটি ডস তৈরি করতে পারে। সমালোচনামূলক, সময় সংবেদনশীল সিস্টেমগুলি ও (এন) অনুসন্ধান, এয়ার ট্র্যাফিক নিয়ন্ত্রণ ইত্যাদির জন্যও মঞ্জুরি দিতে পারে না যদিও সাধারণভাবে আপনি ঠিক থাকেন তবে হ্যাশ মানচিত্রগুলি ডিফল্টরূপে ব্যবহার করুন এবং যখন আপনার আসল প্রয়োজন হবে কেবলমাত্র ট্রি সংস্করণটি স্যুইচ করুন।
ডিফ্ট_কোড

14

সেটটি ব্যবহার করুন যখন:

  1. আমাদের অর্ডার করা ডেটা (স্বতন্ত্র উপাদান) প্রয়োজন।
  2. আমাদের ডেটা মুদ্রণ / অ্যাক্সেস করতে হবে (সাজানো ক্রমে)।
  3. আমাদের পূর্বসূরি / উপাদানগুলির উত্তরসূরি প্রয়োজন।

আনর্ডারড_সেট ব্যবহার করুন যখন:

  1. আমাদের স্বতন্ত্র উপাদানগুলির একটি সেট রাখতে হবে এবং কোনও অর্ডারের প্রয়োজন নেই।
  2. আমাদের একক উপাদান অ্যাক্সেস প্রয়োজন অর্থাত্ কোনও ট্র্যাভারসাল নেই।

উদাহরণ:

সেট:

ইনপুট: 1, 8, 2, 5, 3, 9

আউটপুট: 1, 2, 3, 5, 8, 9

Unordered_set:

ইনপুট: 1, 8, 2, 5, 3, 9

আউটপুট: 9 3 1 8 2 5 (সম্ভবত এই আদেশ, হ্যাশ ফাংশন দ্বারা প্রভাবিত)

মূলত পার্থক্য:

এখানে চিত্র বর্ণনা লিখুন

দ্রষ্টব্য: (কিছু ক্ষেত্রে setআরও সুবিধাজনক) উদাহরণ vectorহিসাবে কী হিসাবে ব্যবহার করুন

set<vector<int>> s;
s.insert({1, 2});
s.insert({1, 3});
s.insert({1, 2});

for(const auto& vec:s)
    cout<<vec<<endl;   // I have override << for vector
// 1 2
// 1 3 

কারণ vector<int>কী হিসাবে হতে পারে setকারণ vectorওভাররাইড operator<

তবে আপনি যদি ব্যবহার করেন তবে আপনাকে এর unordered_set<vector<int>>জন্য একটি হ্যাশ ফাংশন তৈরি করতে হবে vector<int>, কারণ ভেক্টরটির একটি হ্যাশ ফাংশন নেই, সুতরাং আপনাকে এটির মতো একটি সংজ্ঞা দিতে হবে:

struct VectorHash {
    size_t operator()(const std::vector<int>& v) const {
        std::hash<int> hasher;
        size_t seed = 0;
        for (int i : v) {
            seed ^= hasher(i) + 0x9e3779b9 + (seed<<6) + (seed>>2);
        }
        return seed;
    }
};

vector<vector<int>> two(){
    //unordered_set<vector<int>> s; // error vector<int> doesn't  have hash function
    unordered_set<vector<int>, VectorHash> s;
    s.insert({1, 2});
    s.insert({1, 3});
    s.insert({1, 2});

    for(const auto& vec:s)
        cout<<vec<<endl;
    // 1 2
    // 1 3
}

আপনি দেখতে পাচ্ছেন যে কোনও ক্ষেত্রে unordered_setএটি আরও জটিল।

প্রধানত এর থেকে উদ্ধৃত: https://www.geeksforgeeks.org/set-vs-unordered_set-c-stl/ https://stackoverflow.com/a/29855973/6329006


6

কারণ স্ট্যান্ড :: সেট স্ট্যান্ডার্ড সি ++ এর অংশ এবং আনর্ডারড_সেটটি নয়। সি ++ 0x একটি মান নয় এবং এটি বুস্টও নয়। আমাদের মধ্যে অনেকের জন্য বহনযোগ্যতা প্রয়োজনীয় এবং এর অর্থ মানকে আটকে দেওয়া।


2
যদি আমি তাকে সঠিকভাবে বুঝতে পারি তবে লোকেরা বর্তমানে কেন সেট ব্যবহার করছে তা তিনি জিজ্ঞাসা করছেন না। সে নিজেকে সি ++ 0 এক্স সম্পর্কে অবহিত করছে।
জোহানেস স্কাউব -

2
হতে পারে. আমি ভেবেছিলাম সবাই হ্যাশ টেবিল এবং গাছগুলি জানত বিভিন্ন সমস্যা সমাধান করে।

21
ওয়েল, এটা একটি আদর্শ এখন (মাত্র কয়েক বছর সময় লেগেছিল)
ক্লেটন হিউজেস

6

সুইপলাইন অ্যালগরিদম বিবেচনা করুন। এই অ্যালগরিদমগুলি হ্যাশ টেবিলগুলির সাথে পুরোপুরি ব্যর্থ হবে তবে ভারসাম্যযুক্ত গাছগুলির সাথে সুন্দরভাবে কাজ করবে। আপনাকে একটি সুইপলাইন অ্যালগরিদমের একটি দৃ concrete় উদাহরণ দেওয়ার জন্য ভাগ্যের অ্যালগরিদম বিবেচনা করুন। http://en.wikipedia.org/wiki/Fortune%27s_algorithm


1
আমি মনে করি যে এই ধরণের রেফারেন্স খুব জটিল প্রশ্ন। (আমাকে এটি সন্ধান করতে হবে)
হেক্টরপল

3

আরও একটি বিষয়, অন্যান্য ব্যক্তিরা ইতিমধ্যে যা উল্লেখ করেছে তা ছাড়াও। সময় একটি unordered_set একটি উপাদান ঢোকাতে জন্য প্রত্যাশিত amortized জটিলতা হে (1), হরদম এটা হবে হে (ঢ) নিতে কারণ হ্যাশ টেবিল চাহিদা পুনর্গঠন করা (পরিবর্তন বাকেট চাহিদা সংখ্যা) - এমনকি সঙ্গে একটি 'ভাল' হ্যাশ ফাংশন। ঠিক তেমন কোনও ভেক্টরে কোনও উপাদান োকাতে ও (এন) প্রতি এখনই লাগে কারণ অন্তর্নিহিত অ্যারেটি পুনরায় স্থানান্তরিত করা দরকার।

একটি সেট সন্নিবেশ করা সর্বদা সর্বাধিক O (লগ এন) লাগে। এটি কিছু অ্যাপ্লিকেশনগুলিতে পছন্দনীয় হতে পারে।


3

আমাকে ক্ষমা করুন, বাছাই করা সম্পত্তি সম্পর্কে আরও একটি বিষয় লক্ষ্য করার মতো:

আপনি যদি ধারকটিতে একটি ব্যাপ্তি ডেটা চান , উদাহরণস্বরূপ: আপনি সেটে সময় সঞ্চয় করেছেন এবং আপনি 2013-01-01 থেকে 2014-01-01 পর্যন্ত সময় চান।

জন্য unordered_set এটা অসম্ভব।

অবশ্যই, এই উদাহরণটি মানচিত্র এবং আনর্ডারড_ম্যাপের মধ্যে ব্যবহারের ক্ষেত্রে আরও দৃ inc়প্রবণ হবে


3

g++ 6.4 স্টিলিবিসি ++ অর্ডারেড বনাম আনর্ডার্ড সেট বেঞ্চমার্ক

পার্থক্যটি দেখতে আমি এই প্রভাবশালী লিনাক্স সি ++ বাস্তবায়নটিকে বেঞ্চমার্ক করেছি:

এখানে চিত্র বর্ণনা লিখুন

পূর্ণ মানদণ্ডের বিশদ এবং বিশ্লেষণ এখানে দেওয়া হয়েছে: সি ++ এ একটি এসটিএল সেটটির অন্তর্নিহিত ডেটা কাঠামো কী? এবং আমি তাদের এখানে পুনরাবৃত্তি করব না।

"বিএসটি" এর অর্থ "পরীক্ষিত std::setএবং" হ্যাশ ম্যাপ "এর অর্থ" পরীক্ষিত std::unordered_set। "হিপ" হল std::priority_queueযার জন্য আমি এখানে বিশ্লেষণ করেছি: হিপ বনাম বাইনারি অনুসন্ধান ট্রি (বিএসটি)

দ্রুত সংক্ষিপ্তসার হিসাবে:

  • গ্রাফটি পরিষ্কারভাবে দেখায় যে এই শর্তগুলির অধীনে হ্যাশম্যাপ সন্নিবেশটি সবসময় খুব দ্রুত ছিল যখন 100 কেরও বেশি আইটেম থাকে এবং আইটেমের সংখ্যা বাড়ার সাথে তফাত বাড়তে থাকে

    এই গতি বাড়ানোর ব্যয়টি হ'ল আপনি দক্ষতার সাথে ক্রমকে অতিক্রম করতে সক্ষম নন।

  • বক্ররেখা পরিষ্কারভাবে নির্দেশ করে যে আদেশ দেওয়া হয়েছে std::setবিএসটি-ভিত্তিক এবং std::unordered_setহ্যাশম্যাপ ভিত্তিক। রেফারেন্স উত্তরে, আমি আরও নিশ্চিত করেছি যে জিডিবি পদক্ষেপ দ্বারা কোডটি ডিবাগ করছে।

একই প্রশ্নের জন্য mapবনাম unordered_map: সেখানে তুচ্ছ কী ক্ষেত্রে unordered_map উপর মানচিত্র ব্যবহারের কোনো সুবিধা আছে কি?


1

হাতছাড়া, আমি বলব যদি আপনি এটিকে অন্য কোনও ফর্ম্যাটে রূপান্তর করতে চান তবে কোনও সম্পর্কের ক্ষেত্রে জিনিসগুলি রাখা সুবিধাজনক।

এটি অ্যাক্সেস করার ক্ষেত্রে দ্রুত হওয়া সত্ত্বেও, সূচি তৈরির সময় বা মেমরিটি তৈরি করার সময় এবং / অথবা অ্যাক্সেস করার সময়টি বেশি il


+1, বিগ ওহ স্বরলিপি ধ্রুবক কারণগুলি লুকায় এবং সাধারণ সমস্যার আকারের জন্য এটি প্রায়শই ধ্রুব কারণগুলির মধ্যে সর্বাধিক গুরুত্বপূর্ণ।
j_random_hacker

1

আপনি যদি জিনিসগুলি বাছাই করতে চান তবে আপনি আনর্ডারড_সেটের পরিবর্তে সেটটি ব্যবহার করবেন। অন ​​অর্ডারড_সেট সেট ওভার ব্যবহার করা হয় যখন সঞ্চিত অর্ডার দেওয়ার বিষয়টি বিবেচনা করে না।


1

যদিও এই উত্তরটি 10 ​​বছর দেরীতে হতে পারে, তবে এটিতেও উল্লেখ করা উচিত যে std::unordered_setএটির নিরাপত্তা ডাউনসাইডও রয়েছে।

যদি হ্যাশ ফাংশনটি অনুমানযোগ্য হয় (এটি সাধারণত এমন হয় যদি না এটি এলোমেলো লবণের মতো প্রতিরোধ ব্যবস্থা প্রয়োগ না করে), আক্রমণকারীরা হ্যাশ-ক্র্যাফ্ট ডেটা তৈরি করতে পারে যা হ্যাশের সংঘর্ষ তৈরি করে এবং সমস্ত সন্নিবেশ এবং চেহারাগুলি ও (এন) সময় নিতে পারে ।

এটি খুব দক্ষ এবং মার্জিত অস্বীকৃত-পরিষেবার আক্রমণগুলির জন্য ব্যবহার করা যেতে পারে।

অভ্যন্তরীণভাবে হ্যাশ মানচিত্র নিয়োগ করা ভাষাগুলির অনেকগুলি (সর্বাধিক?) এর প্রয়োগ হয়েছে:

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.