কেন std :: list :: বিপরীতে O (n) জটিলতা রয়েছে?


192

std::listC ++ স্ট্যান্ডার্ড লাইব্রেরিতে শ্রেণীর জন্য বিপরীত ফাংশন কেন রৈখিক রানটাইম আছে? আমি মনে করব যে দ্বিগুণ-লিঙ্কযুক্ত তালিকার জন্য বিপরীত ফাংশনটি ও (1) হওয়া উচিত।

দ্বিগুণ-সংযুক্ত তালিকার বিপরীতে কেবল মাথা এবং লেজের পয়েন্টারগুলি স্যুইচ করা জড়িত।


18
লোকেরা কেন এই প্রশ্নটিকে নিম্নচাপ দিচ্ছে তা আমি বুঝতে পারি না। এটি জিজ্ঞাসা করা একেবারে যুক্তিসঙ্গত প্রশ্ন is দ্বিগুণ লিঙ্কযুক্ত তালিকায় ফিরে আসতে ও (১) সময় নিতে হবে।
কৌতুহল

46
দুর্ভাগ্যক্রমে, কিছু লোক "প্রশ্নটি ভাল" এর ধারণার সাথে "প্রশ্নটির একটি ভাল ধারণা আছে" এর সাথে ধারণা বিভ্রান্ত করে। আমি এই জাতীয় প্রশ্ন পছন্দ করি, যেখানে মূলত "আমার বোধগম্যতা একটি সাধারণভাবে গৃহীত অনুশীলনের চেয়ে আলাদা বলে মনে হয়, দয়া করে এই দ্বন্দ্ব সমাধানে সহায়তা করুন", কারণ আপনার মতামতকে প্রসারিত করা আপনাকে রাস্তায় আরও অনেক সমস্যার সমাধান করতে সহায়তা করে! এটি অন্যরা "99.9999% ক্ষেত্রে প্রসেসিংয়ের অপচয় হ'ল এটি সম্পর্কে চিন্তা করবেন না বলে মনে হবে"। যদি এটি কোনও সান্ত্বনা থাকে তবে আমি অনেকের জন্য ডাউনওয়েটড হয়েছি, অনেক কম!
কর্সিকা

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

3
বা আমাকে আপনার কাছে প্রমাণের বোঝা চাপিয়ে দিতে দাও, @ করিয়াস: আমি এখানে দ্বিগুণ সংযুক্ত তালিকার প্রয়োগ বাস্তবায়ন করতে পেরেছি : আদর্শ one.com/c1 হিবো । আপনি কী Reverse(O) (1) এ ফাংশনটি বাস্তবায়িত হওয়ার প্রত্যাশা করবেন তা নির্দেশ করতে পারেন ?
CompuChip

2
@ কমপুকশিপ: বাস্তবে বাস্তবায়নের উপর নির্ভর করে এটি নাও পারে। কোন পয়েন্টারটি ব্যবহার করবেন তা জানতে আপনার কোনও অতিরিক্ত বুলিয়ান প্রয়োজন নেই: কেবল আপনাকেই আবার নির্দেশ করবেন না এমনটি ব্যবহার করুন ... যা এক্সওআর'এল লিঙ্কযুক্ত তালিকার মাধ্যমে স্বয়ংক্রিয়ভাবে হতে পারে। সুতরাং হ্যাঁ, এটি কীভাবে তালিকাটি কার্যকর করা হয় তার উপর নির্ভর করে এবং ওপির বিবৃতিটি পরিষ্কার করা যেতে পারে।
ম্যাথিউ এম।

উত্তর:


187

হাইপোথিটিকভাবে, ও (1)reverse হতে পারত । সেখানে (আবার অনুমানের সাথে) কোনও বুলিয়ান তালিকার সদস্য হতে পারে যা সূচিত করে যে লিঙ্কযুক্ত তালিকার দিকটি বর্তমানে তালিকাটি তৈরি করা হয়েছে এমন একটির সাথে একই বা বিপরীত কিনা।

দুর্ভাগ্যক্রমে, এটি মূলত অন্য কোনও ক্রিয়াকলাপের কার্যকারিতা হ্রাস করবে (যদিও অ্যাসিম্পটোটিক রানটাইম পরিবর্তন না করেই)। প্রতিটি ক্রিয়াকলাপে, কোনও লিঙ্কের "পরবর্তী" বা "পূর্ব" পয়েন্টারটি অনুসরণ করা উচিত কিনা তা বিবেচনা করার জন্য কোনও বুলিয়ানের পরামর্শ নেওয়া উচিত।

যেহেতু সম্ভবত এটি অপেক্ষাকৃত বিরল অপারেশন হিসাবে বিবেচিত হয়েছিল, মান (যা বাস্তবায়নের নির্দেশ দেয় না, কেবল জটিলতা), নির্দিষ্ট করে দেয় যে জটিলতাটি রৈখিক হতে পারে। এটি "পরবর্তী" পয়েন্টারগুলিকে সাধারণ দিকের ক্রিয়াকলাপকে ত্বরান্বিত করে, সর্বদা একই দিকটি নির্বিঘ্নে বোঝাতে দেয়।


29
@ মুজবয়েস: আমি আপনার সাদৃশ্যটির সাথে একমত নই। পার্থক্যটি হ'ল কোনও তালিকার ক্ষেত্রে, বাস্তবায়ন জটিলতার reverseসাথে জোগাতে পারে অন্য কোনও ক্রিয়াকলাপকে প্রভাবিত না করে, এই বুলিয়ান ফ্ল্যাগ ট্রিকটি ব্যবহার করে। তবে, বাস্তবে প্রযুক্তিগতভাবে ও (1) হলেও প্রতিটি ক্রিয়াকলাপে অতিরিক্ত শাখা ব্যয়বহুল। বিপরীতে, আপনি তালিকার কাঠামো তৈরি করতে পারবেন না যাতে ও (1) এবং অন্যান্য সমস্ত ক্রিয়াকলাপ একই ব্যয়। প্রশ্নের মুল বক্তব্যটি মনে হচ্ছে, আপাতদৃষ্টিতে, আপনি যদি কেবলমাত্র বড় ওকেই যত্নশীল করেন তবে আপনি নিখরচায় রিভার্স পেতে পারেন, তবে তারা কেন তা করেন নি। O(1)sortO(1)
ক্রিস বেক

9
আপনি যদি কোনও এক্সওআর-লিঙ্কযুক্ত-তালিকা ব্যবহার করেন তবে বিপরীতকরণগুলি ধ্রুবক সময় হয়ে যাবে। একটি পুনরুক্তিকারী যদিও বড় হবে, এবং বৃদ্ধি / হ্রাস এটি সামান্য আরও গণনামূলকভাবে ব্যয়বহুল হবে। এটি যে কোনও প্রকারের লিঙ্কযুক্ত তালিকার জন্য হলেও অপরিবর্তনীয় মেমরি-অ্যাক্সেসগুলি দ্বারা বামন হতে পারে ।
অনুচ্ছেদে

3
@ ইলিয়াপোপভ: প্রতিটি নোডের আসলে কি এটির প্রয়োজন হয়? ব্যবহারকারী কখনই তালিকার নোডের কোনও প্রশ্ন নিজেই জিজ্ঞাসা করে না, কেবলমাত্র প্রধান তালিকার প্রধান সংস্থা। সুতরাং ব্যবহারকারী যে কোনও পদ্ধতির জন্য কল করে বুলেয়ান অ্যাক্সেস করা সহজ। আপনি এই নিয়মটি তৈরি করতে পারেন যে তালিকার বিপরীত হলে পুনরাবৃত্তিগুলি অবৈধ হয় এবং উদাহরণস্বরূপ, বা / বা বুলিয়ানটির একটি অনুলিপি পুনরুক্তির সাথে সঞ্চয় করে। সুতরাং আমি মনে করি এটি অগত্যা বড় ওকে প্রভাবিত করবে না। আমি স্বীকার করব, আমি অনুমানের মাধ্যমে লাইন-লাইন যেতে পারিনি। :)
ক্রিস বেক

4
@ কেভিন: এইচ এম, কি? আপনি সরাসরি যাহাই হউক না কেন দুই পয়েন্টার XOR, আপনি (টাইপ এর স্পষ্টত প্রথম পূর্ণসংখ্যার তাদের রূপান্তর করতে হবে করতে পারবেন std::uintptr_tতারপর আপনি তাদের XOR পারবেন না।
Deduplicator

3
@ কেভিন, আপনি অবশ্যই সি ++ এ একটি এক্সওআর লিঙ্কযুক্ত তালিকা তৈরি করতে পারেন, এটি কার্যত এই জাতীয় জিনিসের জন্য পোস্টার-শিশু ভাষা language কিছুই আপনাকে ব্যবহার করতে হবে বলে না std::uintptr_t, আপনি একটি charঅ্যারেতে কাস্ট করতে পারেন এবং তারপরে উপাদানগুলি এক্সওআর করতে পারেন। এটি ধীর হতে পারে তবে 100% বহনযোগ্য। সম্ভবত আপনি এই দুটি বাস্তবায়নগুলির মধ্যে এটি নির্বাচন করতে পারেন এবং uintptr_tঅনুপস্থিত থাকলে কেবল দ্বিতীয়টি ফ্যালব্যাক হিসাবে ব্যবহার করতে পারেন । কিছু যদি এই উত্তরে বর্ণিত হয়: stackoverflow.com/questions/14243971/…
ক্রিস বেক

61

এটি (1) হতে পারে যদি তালিকায় কোনও পতাকা সংরক্ষণ করা হয় যা প্রতিটি নোডের " " এবং " " পয়েন্টারের অর্থ অদলবদল করতে দেয় । যদি তালিকাটি উল্টানো একটি ঘন ঘন অপারেশন হয়ে থাকে, তবে এই জাতীয় সংযোজন সত্যিকার অর্থে কার্যকর হতে পারে এবং বর্তমান মান দ্বারা এটি প্রয়োগ করা নিষিদ্ধ হওয়ার কোনও কারণ আমি জানি না । যাইহোক, এই জাতীয় পতাকা থাকলে তালিকার সাধারণ ট্র্যাভারসালকে আরও ব্যয়বহুল করে তুলবে (যদি কেবল ধ্রুবক ফ্যাক্টর দ্বারা থাকে) তবে পরিবর্তেprevnext

current = current->next;

মধ্যে operator++তালিকা পুনরুক্তিকারীর, আপনি পেতে হবে

if (reversed)
  current = current->prev;
else
  current = current->next;

যা এমন কিছু নয় যা আপনি সহজেই যুক্ত করার সিদ্ধান্ত নেবেন। প্রদত্ত যে তালিকাগুলি সাধারণত বিপরীত হয় তার চেয়ে অনেক বেশি বার বিভ্রান্ত হয়, মানটিকে এই কৌশলটির আদেশ দেওয়ার পক্ষে এটি খুব বুদ্ধিমানের কাজ হবে । সুতরাং, বিপরীত অপারেশন লিনিয়ার জটিলতা অনুমোদিত। নোট না, তবে, যে টিহে (1) ⇒ টিহে ( ) তাই হয়, আগে উল্লেখ করেছে, আপনার "অপ্টিমাইজেশান" বাস্তবায়নে টেকনিক্যালি অনুমতি দেওয়া হবে।

আপনি যদি জাভা বা অনুরূপ ব্যাকগ্রাউন্ড থেকে এসে থাকেন তবে আপনি ভাবতে পারেন যে কেন পুনরুক্তিকারীকে প্রতিবার পতাকাটি পরীক্ষা করতে হবে। আমরা কি এর পরিবর্তে দুটি স্বতন্ত্র পুনরাবৃত্তকারী টাইপগুলি উভয়ই একটি সাধারণ বেস টাইপ থেকে প্রাপ্ত std::list::beginএবং std::list::rbeginবহুবারিকভাবে যথাযথ পুনরাবৃত্তিকে ফিরিয়ে দিতে পারি না? সম্ভব হওয়ার পরে এটি পুরো জিনিসটিকে আরও খারাপ করে দেবে কারণ পুনরাবৃত্তিকে অগ্রসর করা এখন পরোক্ষ (ইনলাইন করা শক্ত) ফাংশন কল হবে। জাভাতে, আপনি যাইহোক যাইহোক এই দামটি প্রদান করছেন, কিন্তু তারপরে আবারও, পারফরম্যান্স সমালোচিত হওয়ার পরে অনেকে সি ++ এ পৌঁছানোর এই কারণগুলির মধ্যে একটি।

মন্তব্যে বেনজামিন লিন্ডলি যেমন উল্লেখ করেছেন , যেহেতু reverseপুনরাবৃত্তিকারীদের অকার্যকর করার অনুমতি দেওয়া হচ্ছে না, কেবলমাত্র স্ট্যান্ডার্ডের দ্বারা অনুমোদিত অনুমতিটি পুনরাবৃত্তির ভিতরে তালিকার মধ্যে একটি পয়েন্টার সংরক্ষণ করে যা দ্বি-পরোক্ষ মেমরির অ্যাক্সেসের কারণ হয়ে থাকে।


7
@ গেগিনেট: পুনরাবৃত্তিকারীদের std::list::reverseঅকার্যকর করে না।
বেনিয়ামিন লিন্ডলি 21

1
@galinette দুঃখিত, আমি "প্রতি পতাকা হিসাবে আপনার আগের মন্তব্য ভুল পড়া পুনরুক্তিকারীর " হিসাবে "প্রতি পতাকা উল্টোদিকে নোড " হিসাবে আপনি এটা লিখেছিলেন। অবশ্যই, নোডের জন্য একটি পতাকাটি প্রতি -উত্পাদনশীল হবে কারণ আপনাকে আবার এগুলি ফ্লিপ করতে একটি রৈখিক ট্র্যাভারসাল করতে হবে।
5gon12eder

2
@ 5gon12eder: আপনি খুব হারিয়ে যাওয়া ব্যয়ে ব্রাঞ্চিংটি দূর করতে পারবেন: স্টোর nextএবং prevপয়েন্টারগুলিকে একটি অ্যারেতে সংরক্ষণ করুন এবং দিকটি একটি হিসাবে 0বা স্টোর হিসাবে সংরক্ষণ করুন 1। এগিয়ে যাওয়ার জন্য, আপনি অনুসরণ pointers[direction]করতে এবং বিপরীতে pointers[1-direction](বা বিপরীতে) পুনরাবৃত্তি করতে চাই । এটি এখনও ওভারহেডের একটি সামান্য বিট যোগ করবে, তবে সম্ভবত একটি শাখার চেয়ে কম।
জেরি কফিন

4
আপনি সম্ভবত পুনরাবৃত্তির ভিতরে তালিকার কোনও পয়েন্টার সংরক্ষণ করতে পারবেন না। swap()স্থির সময় হিসাবে নির্দিষ্ট করা হয় এবং কোনও পুনরাবৃত্তিকারীকে অবৈধ না করে।
তাভিয়ান বার্নস

1
@ তাভিয়ানবার্নস! ওয়েল, ট্রিপল ইন্ডিরিশন তাহলে ... (আমি বলতে চাইছি আসলে ট্রিপল নয়। আপনি পতাকাটি গতিশীলভাবে বরাদ্দকৃত বস্তুতে সংরক্ষণ করতে চান তবে পুনরুক্তিকারীটির পয়েন্টার অবশ্যই তালিকার উপরের নির্দেশের পরিবর্তে সরাসরি সেই বস্তুটিতে সরাসরি নির্দেশ করতে পারে))
5gon12eder

37

অবশ্যই যেহেতু দ্বিদ্বিদী পুনরুক্তিকারীদের সমর্থনকারী সমস্ত ধারকগুলির মধ্যে rbegin () এবং রেন্ড ()) ধারণা রয়েছে, তাই এই প্রশ্নটি কি মোট?

এমন একটি প্রক্সি তৈরি করা তুচ্ছ যা পুনরাবৃত্তকারীদের বিপরীত করে এবং এর মাধ্যমে ধারকটিতে প্রবেশ করে।

এই অপারেশনটি আসলে ও (1)।

যেমন:

#include <iostream>
#include <list>
#include <string>
#include <iterator>

template<class Container>
struct reverse_proxy
{
    reverse_proxy(Container& c)
    : _c(c)
    {}

    auto begin() { return std::make_reverse_iterator(std::end(_c)); }
    auto end() { return std::make_reverse_iterator(std::begin(_c)); }

    auto begin() const { return std::make_reverse_iterator(std::end(_c)); }
    auto end() const { return std::make_reverse_iterator(std::begin(_c)); }

    Container& _c;
};

template<class Container>
auto reversed(Container& c)
{
    return reverse_proxy<Container>(c);
}

int main()
{
    using namespace std;
    list<string> l { "the", "cat", "sat", "on", "the", "mat" };

    auto r = reversed(l);
    copy(begin(r), end(r), ostream_iterator<string>(cout, "\n"));

    return 0;
}

প্রত্যাশিত আউটপুট:

mat
the
on
sat
cat
the

এটি দেওয়া, আমার কাছে মনে হয় যে স্ট্যান্ডার্ড কমিটি কনটেইনারটি (1) রিভার্স-অর্ডারিংয়ের আদেশ দেওয়ার জন্য সময় নেয় নি কারণ এটি প্রয়োজনীয় নয়, এবং স্ট্যান্ডার্ড লাইব্রেরি কেবলমাত্র যা কঠোরভাবে প্রয়োজনীয় তা জারি করার নীতিতে মূলত নির্মিত হয়েছে সদৃশ এড়ানো।

শুধু আমার 2 সি।


18

কারণ এটিকে প্রতিটি নোড ( nমোট) অতিক্রম করতে হবে এবং তাদের ডেটা আপডেট করতে হবে (আপডেটের ধাপটি সত্যই O(1))। এটি পুরো অপারেশন করে O(n*1) = O(n)


27
কারণ আপনার প্রতিটি আইটেমের মধ্যে লিঙ্কগুলি আপডেট করতে হবে। একটি কাগজের টুকরো বের করুন এবং ডাউনভোটিংয়ের পরিবর্তে এটি আঁকুন।
অন্ধ 23

11
আপনি যদি তখন নিশ্চিত হন তবে কেন জিজ্ঞাসা করবেন? আপনি আমাদের উভয় সময় নষ্ট করছেন।
অন্ধ 23

28
@ করিয়াস ডাবলি লিঙ্কযুক্ত তালিকার নোডগুলির দিকনির্দেশ রয়েছে। সেখান থেকে কারণ।
জুতো

11
@ ব্লিন্ডি একটি ভাল উত্তর সম্পূর্ণ হওয়া উচিত। "কাগজের টুকরো টুকরো টুকরো টুকরো টানুন" সুতরাং ভাল উত্তরের প্রয়োজনীয় উপাদান হওয়া উচিত নয়। যে উত্তরগুলি ভাল উত্তর নয় সেগুলি ডাউনভোটের সাপেক্ষে।
আরএম

7
@ শো: তাদের কি আছে? দয়া করে এক্সওআর-লিঙ্কযুক্ত-তালিকা এবং এর মত গবেষণা করুন।
উত্সাহক

2

এটি প্রতিটি নোডের জন্য পূর্ববর্তী এবং পরবর্তী পয়েন্টারটিকেও অদলবদল করে। কেন এটি লিনিয়ার লাগে ts যদিও এটি ও (1) এ করা যেতে পারে যদি এই এলএলটি ব্যবহার করে ফাংশনটি এলএল সম্পর্কে ইনপুট হিসাবে তথ্য গ্রহণ করে যেমন এটি স্বাভাবিকভাবে অ্যাক্সেস করছে বা বিপরীত।


1

কেবল একটি অ্যালগরিদম ব্যাখ্যা। আপনার উপাদানগুলির সাথে একটি অ্যারে রয়েছে তা কল্পনা করুন, তারপরে আপনার এটি উল্টানো দরকার। প্রাথমিক ধারণাটি হ'ল প্রতিটি উপাদানকে প্রথম অবস্থানে সর্বশেষ অবস্থানে পরিবর্তন করে দ্বিতীয় উপাদানকে দ্বিতীয় পজিশনের উপাদানটি পেনাল্টিমেট পজিশনে পরিবর্তন করা ইত্যাদি। আপনি অ্যারের মাঝখানে পৌঁছালে আপনার সমস্ত উপাদান পরিবর্তিত হবে, এভাবে (n / 2) পুনরাবৃত্তিতে, যা ও (এন) হিসাবে বিবেচিত হবে।


1

এটি ও (এন) কেবলমাত্র কারণটি তালিকার বিপরীত ক্রমে কপি করা দরকার। প্রতিটি স্বতন্ত্র আইটেম অপারেশন হ'ল (1) তবে পুরো তালিকায় সেগুলির মধ্যে এন রয়েছে n

অবশ্যই নতুন তালিকার জন্য জায়গা নির্ধারণের জন্য এবং পরে পয়েন্টারগুলি পরিবর্তন করার জন্য কিছু ধ্রুবক-সময়মূলক ক্রিয়াকলাপ জড়িত রয়েছে etc.

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