স্টাড :: ভেক্টরের পুনরাবৃত্তির সূচক পাওয়ার সবচেয়ে কার্যকর উপায় কী?


439

আমি একটি ভেক্টর দিয়ে পুনরাবৃত্তি করছি এবং পুনরায় ইটারেটরটি নির্দেশ করে সূচকটি প্রয়োজন। আফাইক এই দুটি উপায়ে করা যেতে পারে:

  • it - vec.begin()
  • std::distance(vec.begin(), it)

এই পদ্ধতির উপকারিতা এবং কনসগুলি কী কী?

উত্তর:


558

আমি it - vec.begin()নবীন প্রদত্ত বিপরীত কারণে সুনির্দিষ্টভাবে পছন্দ করব : সুতরাং আপনি যদি ভেক্টরকে একটি তালিকায় পরিবর্তন করেন তবে এটি সংকলন হবে না । আপনি যদি প্রতিটি পুনরাবৃত্তির সময় এটি করেন, আপনি সহজেই একটি ও (এন) অ্যালগরিদমকে একটি ও (এন ^ 2) অ্যালগরিদমে পরিণত করতে পারেন।

আরেকটি বিকল্প, যদি আপনি পুনরাবৃত্তি চলাকালীন পাত্রে প্রায় লাফিয়ে না যান, তবে সূচকটিকে দ্বিতীয় লুপের কাউন্টার হিসাবে রাখতে হবে keep

দ্রষ্টব্য: itএকটি ধারক পুনরুক্তকারীর একটি সাধারণ নাম std::container_type::iterator it;,।


3
একমত। আমি বলব যে বিয়োগ চিহ্নটি সর্বোত্তম, তবে স্ট্যান্ড :: দূরত্ব ব্যবহার করার চেয়ে দ্বিতীয় লুপের কাউন্টার রাখা ভাল, কারণ এই ফাংশনটি ধীর হতে পারে।
স্টিভেন সুদিত

28
হেক কি it?
স্টেইনফিল্ড

32
@ স্টেইনফিল্ড এটি একটি পুনরুক্তি। std::container_type::iterator it;
ম্যাট মুনসন

2
দ্বিতীয় লুপের কাউন্টার যুক্ত করা এমন একটি সুস্পষ্ট সমাধান যা আমি বিব্রত বোধ করি আমি এটি ভাবিনি।
Mordred

3
@ স্বপনিল কারণ std::listতাদের অবস্থান অনুসারে উপাদানগুলিতে সরাসরি অ্যাক্সেসের প্রস্তাব দেয় না, তাই যদি আপনি না করতে পারেন তবে আপনার list[5]পক্ষে সক্ষম হবেন না list.begin() + 5
জোসে টমসের টোকিনো

135

আমি পছন্দ করব std::distance(vec.begin(), it)কেননা এটি কোনও কোড পরিবর্তন না করে পাত্রে পরিবর্তন করার অনুমতি দেবে। উদাহরণস্বরূপ, আপনি যদি তার std::listপরিবর্তে std::vectorকোনও এলোমেলো অ্যাক্সেস পুনরায় সরবরাহ না করে তা ব্যবহার করার সিদ্ধান্ত নেন তবে আপনার কোডটি এখনও সংকলিত হবে। যেহেতু স্ট্যান্ড :: দূরত্ব পুনরুক্তি বৈশিষ্ট্যের উপর নির্ভর করে অনুকূল পদ্ধতিটি গ্রহণ করে আপনার কোনও কার্যকারিতা হ্রাস পাবে না।


50
আপনি রেণ্ডম এক্সেস iterators ছাড়া একটি ধারক ব্যবহার করছেন, তখন তা সেরা না এমন দূরত্বের গনা কারণ এরা অকর্মণ্য এর
এলি Bendersky

6
@ এলি: আমি এটির সাথে একমত, তবে খুব বিশেষ ক্ষেত্রে যদি এটি সত্যই প্রয়োজন হয় তবে এখনও কোডটি কার্যকর হবে।
নবীন

9
আমি মনে করি কনটেইনার পরিবর্তন হলে কোডটি যে কোনওভাবেই পরিবর্তন করা উচিত - একটি স্ট্যান্ড :: তালিকা ভেরিয়েবলের নাম vecরাখা খারাপ খবর। যদি কোডটি আবার জেনেরিক হিসাবে লেখা থাকে, ধারক প্রকারটিকে একটি টেম্পলেট প্যারামিটার হিসাবে গ্রহণ করে, তখনই আমরা যখন র্যান্ডম-অ্যাক্সেস পুনরুদ্ধার পুনরুদ্ধারকারীদের পরিচালনা করতে (এবং হওয়া উচিত) ;-)
স্টিভ জেসোপ

1
এবং নির্দিষ্ট পাত্রে জন্য বিশেষীকরণ।
ScaryAardvark

19
@ স্টিভ জেসাপ: ভেক্টরের নাম vecরাখা খুব খারাপ খবর।
নদীর

74

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

it - vec.begin()ধ্রুবক সময় নেয়, তবে এটি operator -কেবল এলোমেলো অ্যাক্সেসের পুনরাবৃত্তকারীগুলিতে সংজ্ঞায়িত হয়, সুতরাং কোডটি পুনরাবৃত্তকারী তালিকার সাথে সংকলন করবে না, উদাহরণস্বরূপ।

std::distance(vec.begin(), it) সমস্ত পুনরাবৃত্তকারী ধরণের জন্য কাজ করে, তবে কেবল এলোমেলো অ্যাক্সেস পুনরুক্তিগুলিতে ব্যবহৃত হলে কেবল ধ্রুবক-সময় অপারেশন হবে।

কেউই "ভাল" নয়। আপনার প্রয়োজন অনুসারে এটি ব্যবহার করুন।


1
আমি অতীতে এই খারাপ লাগা। দুটি স্ট্যান্ড :: মানচিত্রের পুনরাবৃত্তির উপর এসটিডি :: দূরত্ব ব্যবহার করে এবং এটি ও (এন) হওয়ার প্রত্যাশা করে।
ScaryAardvark

6
@ এসকিআর্দ্বার্ক: আপনি এটি (O) হওয়ার আশা করছেন না?
জাল্ফ

12

আমি এটি পছন্দ করি: it - vec.begin()কারণ আমার কাছে এটি স্পষ্টভাবে "শুরু থেকে দূরত্ব" বলেছে। পুনরাবৃত্তকারীদের সাথে আমরা পাটিগণিতের দিক থেকে চিন্তাভাবনা করতে অভ্যস্ত, সুতরাং এখানে -চিহ্নটি সবচেয়ে পরিষ্কার সূচক।


19
শব্দটির ব্যবহারের চেয়ে দূরত্বটি খুঁজে পেতে বিয়োগফলকে আরও স্পষ্ট করে বলা হয়েছে distance?
ট্র্যাভিস গোকেল

4
@ ট্রাভিস, আমার কাছে এটি। এটি স্বাদ এবং রীতিন্যের বিষয়। আমরা বলি it++আর কিছু না std::increment(it), তাই না? এটিও কি কম পরিষ্কার হিসাবে গণনা করা হবে না?
এলি বেন্ডারস্কি

3
++অপারেটর কিভাবে আমরা পুনরুক্তিকারীর বাড়ায় যেমন STL সিকোয়েন্স অংশ হিসেবে সংজ্ঞায়িত করা হয়। std::distanceপ্রথম এবং শেষ উপাদানটির মধ্যে উপাদানের সংখ্যা গণনা করে। -অপারেটর যে কাজ করে তা কেবল একটি কাকতালীয় ঘটনা।
ট্র্যাভিস গোকেল

3
@ এসএমএল্টারস: এবং এখনও, আমরা ++ :-) ব্যবহার করি
এলি বেন্ডারস্কি

10

আপনি যদি ইতিমধ্যে আপনার অ্যালগরিদমকে কেবল std::vector::iteratorএবং std::vector::iteratorকেবলমাত্র ব্যবহারের জন্যই সীমাবদ্ধ / হার্ডকড করে থাকেন তবে আপনি কোন পদ্ধতিটি ব্যবহার করে শেষ করবেন তা আসলে কোনও ব্যাপার নয়। আপনার অ্যালগরিদম ইতিমধ্যে বিন্দুটি ছাড়িয়ে সংক্ষিপ্ত হয়ে গেছে যেখানে একে অপরের চয়ন করা কোনও পার্থক্য করতে পারে। তারা দুজনেই ঠিক একই কাজ করে। এটি কেবল ব্যক্তিগত পছন্দের বিষয়। আমি ব্যক্তিগতভাবে সুস্পষ্ট বিয়োগ ব্যবহার করব।

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

  • আপনি যদি সুস্পষ্ট বিয়োগটি ব্যবহার করেন তবে আপনার অ্যালগরিদম পুনরাবৃত্তির পরিবর্তে সংকীর্ণ শ্রেণীর মধ্যে সীমাবদ্ধ থাকবে: এলোমেলো অ্যাক্সেস পুনরাবৃত্তিকারী। (আপনি এখন থেকে এটি কি পেতে std::vector)

  • আপনি যদি ব্যবহার distance আপনার অ্যালগরিদম পুনরাবৃত্তির আরও বিস্তৃত শ্রেণিকে সমর্থন করবে: ইনপুট পুনরাবৃত্তকারী।

অবশ্যই, distanceনন-এলোমেলো-অ্যাক্সেস পুনরাবৃত্তির জন্য গণনা করা সাধারণ ক্ষেত্রে একটি অকার্যকর ক্রিয়াকলাপ (যখন আবার, এলোমেলো অ্যাক্সেসের ক্ষেত্রে এটি বিয়োগের মতো দক্ষ)। এটা তোলে সিদ্ধান্ত নিতে আপনার অ্যালগরিদম কিনা আপনার ব্যাপার ইন্দ্রিয় তোলে অ র্যান্ডম অ্যাক্সেস iterators দক্ষতা ভিত্তিক জন্য। দক্ষতার ফলে ফলস্বরূপ ক্ষতি আপনার অ্যালগরিদম সম্পূর্ণরূপে অকেজো করার মতো বিন্দুতে ধ্বংসাত্মক, তারপরে আপনার আরও ভাল বিয়োগকে আঁকড়ে রাখা উচিত, এইভাবে অদৃশ্য ব্যবহারগুলিকে নিষিদ্ধ করা এবং ব্যবহারকারীকে অন্যান্য পুনরাবৃত্তকারী প্রকারের বিকল্প সমাধান খুঁজতে বাধ্য করা। যদি নন-এলোমেলো-অ্যাক্সেস পুনরুদ্ধারকারীগুলির সাথে দক্ষতা এখনও ব্যবহারযোগ্য সীমার মধ্যে থাকে তবে আপনার distanceঅ্যালগরিদম এলোমেলো-অ্যাক্সেস পুনরুক্তিগুলির সাথে আরও ভাল কাজ করে তা এই তথ্যটি ব্যবহার এবং নথিতে করা উচিত ।


4

মতে http://www.cplusplus.com/reference/std/iterator/distance/ , যেহেতু vec.begin()একটি হল রেণ্ডম এক্সেস পুনরুক্তিকারীর, দূরত্ব পদ্ধতি ব্যবহার -অপারেটর।

সুতরাং উত্তরটি হল, পারফরম্যান্সের দৃষ্টিকোণ থেকে, এটি একই, তবে distance()কারও আপনার কোডটি পড়তে এবং বুঝতে হবে কিনা তা ব্যবহার করা বোঝা আরও সহজ।


3

আমি কেবল -বৈকল্পিকটি ব্যবহার করতাম std::vector- এটি বোঝা যা বোঝানো হয়েছে তা সম্পূর্ণ পরিষ্কার এবং ক্রিয়াকলাপের সরলতা (যা পয়েন্টার বিয়োগফলের চেয়ে বেশি নয়) বাক্য গঠন দ্বারা প্রকাশ করা হয়েছে ( distanceঅন্যদিকে, পাইথাগোরাসগুলির মতো শব্দ) প্রথম পড়া, তাই না?)। আঙ্কেলবেইন যেমন উল্লেখ করেছেন, তেমন ক্ষেত্রে অচলভাবে পরিবর্তিত হওয়ার -ক্ষেত্রে স্থিতিশীল দাবি হিসাবেও কাজ vectorকরেlist

এছাড়াও আমি মনে করি এটি অনেক বেশি সাধারণ - যদিও এটি প্রমাণ করার মতো কোনও সংখ্যা নেই। মাস্টার আর্গুমেন্ট: it - vec.begin()উত্স কোডের চেয়ে কম - টাইপিংয়ের কাজ কম, কম জায়গা ব্যয় করা হয়েছে। যেমনটি স্পষ্ট যে আপনার প্রশ্নের সঠিক উত্তরটি স্বাদের বিষয় হিসাবে ফোটায়, এটিও একটি বৈধ যুক্তি হতে পারে।


0

সূচির পাশাপাশি 10 টির "সমস্ত" উপস্থিতি খুঁজে পাওয়ার জন্য এখানে একটি উদাহরণ। ভেবেছি এটি কিছুটা সাহায্য পাবে।

void _find_all_test()
{
    vector<int> ints;
    int val;
    while(cin >> val) ints.push_back(val);

    vector<int>::iterator it;
    it = ints.begin();
    int count = ints.size();
    do
    {
        it = find(it,ints.end(), 10);//assuming 10 as search element
        cout << *it << " found at index " << count -(ints.end() - it) << endl;
    }while(++it != ints.end()); 
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.