আমি কীভাবে দক্ষতার সাথে ক্লাবটি সাফ করব?


166

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

আমি কীভাবে জবকিউ ক্লাসের জন্য পরিষ্কার পদ্ধতিটি দক্ষতার সাথে প্রয়োগ করব?

আমার কাছে একটি লুপে পপিংয়ের একটি সহজ সমাধান রয়েছে তবে আমি আরও ভাল উপায়গুলি খুঁজছি।

//Clears the job queue
void JobQueue ::clearJobs()
 {
  // I want to avoid pop in a loop
    while (!m_Queue.empty())
    {
        m_Queue.pop();
    }
}

3
দ্রষ্টব্য সাফdeque সমর্থন করে
বোবোবোলো

উত্তর:


257

স্ট্যান্ডার্ড পাত্রে সাফ করার জন্য একটি সাধারণ প্রতিমাটি ধারকটির খালি সংস্করণ দিয়ে অদলবদল করা হয়:

void clear( std::queue<int> &q )
{
   std::queue<int> empty;
   std::swap( q, empty );
}

কিছু ধারক (স্ট্যান্ড :: ভেক্টর) এর ভিতরে রাখা মেমরিটি আসলে পরিষ্কার করার একমাত্র উপায় এটি


41
আরও ভাল হয় std::queue<int>().swap(q)। অনুলিপি এবং অদলবদ প্রতিশব্দ সঙ্গে, এই সব সমতুল্য হওয়া উচিত q = std::queue<int>()
আলেকজান্দ্রি সি

12
std::queue<int>().swap(q)উপরের কোডের সমতুল্য হলেও এর সমতুল্য হওয়ার q = std::queue<int>()দরকার নেই। যেহেতু বরাদ্দ মেমরির অ্যাসাইনমেন্টে মালিকানার কোনও স্থানান্তর নেই তাই কিছু ধারক (যেমন ভেক্টর) কেবল আগের ধারণকৃত উপাদানগুলির ডেস্ট্রাক্টরদের কল করতে পারে এবং মেমরিটি ছাড়াই প্রকৃতির আকার (বা সঞ্চিত পয়েন্টারগুলির সাথে সমতুল্য অপারেশন) সেট করতে পারে ।
ডেভিড রদ্রিগেজ - ড্রিবিস

6
queueএকটি swap(other)পদ্ধতি নেই, তাই queue<int>().swap(q)সংকলন না। আমার মনে হয় আপনাকে জেনেরিক ব্যবহার করতে হবে swap(a, b)
ডাস্টিন বসওয়েল

3
@ থরবজর্নলিন্ডিজার: সি ++ ০৩ এ আপনি ঠিক বলেছেন, সি ++ এ 11 টি সারি সদস্য ফাংশন হিসাবে অদলবদল করে এবং অতিরিক্তভাবে একটি ফাংশন ওভারলোড রয়েছে যা একই ধরণের দুটি সারি অদলবদল করবে।
ডেভিড রদ্রিগেজ - ড্রিবিস

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

46

হ্যাঁ - আইএমএইচও, ক্যু শ্রেণীর কিছুটা ভুল ধারণা ature এই আমি কি কি:

#include <queue>
using namespace std;;

int main() {
    queue <int> q1;
    // stuff
    q1 = queue<int>();  
}

8
@ নাজতা দয়া করে কীভাবে swap"আরও কার্যকর" তা বিস্তারিতভাবে বর্ণনা করুন
বোবোবো

@ বোবোবো:q1.swap(queue<int>());
নাস্ত্তা

12
q1=queue<int>();উভয়ই খাটো এবং আরও পরিষ্কার (আপনি সত্যিকার অর্থে চেষ্টা করছেন না .swap, আপনি চেষ্টা করছেন .clear)।
বোবোবোবো

28
নতুন সি ++ সহ, কেবলমাত্র q1 = {}যথেষ্ট
মাইকোলা বোগদিউক

2
এ @Ari সিনট্যাক্স (2) list_initialization এবং (10) এ operator_assignment । ডিফল্ট queue<T>কনস্ট্রাক্টর খালি যুক্তি তালিকার সাথে মেলে {}এবং অন্তর্নিহিত, তাই এটি বলা হয়, তারপরে q1.operator=(queue<T>&&)সদ্য নির্মিত তৈরি গ্রাস করেqueue
মাইকোলা বোগদিউক

26

বিষয়টির লেখক জিজ্ঞাসা করলেন কীভাবে "দক্ষতার সাথে" সারিটি সাফ করবেন, সুতরাং আমি ধরে নিই যে তিনি লিনিয়ার ও (সারির আকার) এর চেয়ে আরও ভাল জটিলতা চান । ডেভিড রদ্রিগেজ দ্বারা প্রদত্ত পদ্ধতিগুলি , আননের একই জটিলতা রয়েছে: এসটিএল রেফারেন্স অনুসারে, operator =জটিলতা হে (সারির আকার) রয়েছে । আইএমএইচএও কারণ এটি যে প্রতিটি সারির উপাদান আলাদা আলাদাভাবে সংরক্ষিত থাকে এবং এটি ভেক্টরের মতো একটি বড় মেমরি ব্লকে বরাদ্দ করা হয় না। সুতরাং সমস্ত স্মৃতি সাফ করতে আমাদের প্রতিটি উপাদান আলাদাভাবে মুছতে হবে। সোজা করার সহজতম std::queueউপায়টি একটি লাইন:

while(!Q.empty()) Q.pop();

5
আপনি যদি সত্যিকারের ডেটাতে অপারেট করছেন তবে আপনি কেবল অপারেশনটির ও জটিলতার দিকে নজর দিতে পারবেন না। আমি একটি গ্রহণ করা হবে O(n^2)একটি ওভার অ্যালগরিদম O(n)অ্যালগরিদম যদি রৈখিক অপারেশন উপর ধ্রুবক এটা আরও ধীর সবার জন্য দ্বিঘাত চেয়ে n < 2^64, যদি না আমি কিছু শক্তিশালী আমি IPv6, অ্যাড্রেস স্পেস বা অন্য নির্দিষ্ট সমস্যা অনুসন্ধান করতে ছিল বিশ্বাস করার কারণ ছিল। সীমাবদ্ধতার চেয়ে পারফরম্যান্সের চেয়ে বাস্তবতার পারফরম্যান্স আমার কাছে বেশি গুরুত্বপূর্ণ।
ডেভিড স্টোন

2
গৃহীত উত্তরের চেয়ে এই আরও ভাল উত্তর কারণ ধ্বংস হওয়ার সময় অভ্যন্তরীণভাবে সারি এইভাবেই ঘটে। সুতরাং স্বীকৃত উত্তরটি হ'ল (এন) প্লাস এটি ব্র্যান্ড নিউ কাতারের জন্য অতিরিক্ত বরাদ্দ এবং প্রারম্ভিককরণ করে।
শীতল শাহ

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

15

স্পষ্টতই, দুটি পরিষ্কার করার জন্য সবচেয়ে সুস্পষ্ট উপায় রয়েছে std::queue: খালি বস্তুর সাথে অদলবদল এবং খালি অবজেক্টে অ্যাসাইনমেন্ট।

আমি অ্যাসাইনমেন্টটি ব্যবহার করার পরামর্শ দেব কারণ এটি কেবল দ্রুত, আরও পঠনযোগ্য এবং দ্ব্যর্থহীন।

আমি নিম্নলিখিত সাধারণ কোডটি ব্যবহার করে পারফরম্যান্সটি পরিমাপ করেছি এবং আমি দেখতে পেয়েছি যে সি ++ 03 সংস্করণে অদলবালি একটি খালি অবজেক্টের অ্যাসাইনমেন্টের চেয়ে 70-80% ধীর গতির কাজ করে। তবে C ++ 11 এ পারফরম্যান্সে কোনও পার্থক্য নেই। যাইহোক, আমি নিয়োগের সাথে যেতে হবে।

#include <algorithm>
#include <ctime>
#include <iostream>
#include <queue>
#include <vector>

int main()
{
    std::cout << "Started" << std::endl;

    std::queue<int> q;

    for (int i = 0; i < 10000; ++i)
    {
        q.push(i);
    }

    std::vector<std::queue<int> > queues(10000, q);

    const std::clock_t begin = std::clock();

    for (std::vector<int>::size_type i = 0; i < queues.size(); ++i)
    {
        // OK in all versions
        queues[i] = std::queue<int>();

        // OK since C++11
        // std::queue<int>().swap(queues[i]);

        // OK before C++11 but slow
        // std::queue<int> empty;
        // std::swap(empty, queues[i]);
    }

    const double elapsed = double(clock() - begin) / CLOCKS_PER_SEC;

    std::cout << elapsed << std::endl;

    return 0;
}

8

সি ++ 11 এ আপনি এটি করে কাতাকে সাফ করতে পারেন:

std::queue<int> queue;
// ...
queue = {};

4

আপনি একটি শ্রেণি তৈরি করতে পারেন যা সারি থেকে উত্তরাধিকার সূত্রে প্রাপ্ত এবং সরাসরি অন্তর্নিহিত ধারকটি সাফ করতে। এটি খুব দক্ষ।

template<class T>
class queue_clearable : public std::queue<T>
{
public:
    void clear()
    {
        c.clear();
    }
};

হতে পারে আপনার বাস্তবায়ন এছাড়াও আপনার ভেরিউজ অবজেক্টকে (এখানে JobQueue) std::queue<Job>সদস্য ভেরিয়েবল হিসাবে সারি করার পরিবর্তে উত্তরাধিকারী হতে দেয়। এইভাবে c.clear()আপনার নিজের সদস্য কার্যগুলিতে আপনার সরাসরি অ্যাক্সেস থাকবে ।


9
এসটিএল ধারকগুলি উত্তরাধিকার সূত্রে ডিজাইন করা হয়নি। এই ক্ষেত্রে আপনি সম্ভবত ঠিক আছেন কারণ আপনি কোনও অতিরিক্ত সদস্য ভেরিয়েবল যোগ করছেন না, তবে সাধারণভাবে করা ভাল জিনিস নয়।
bstamour

2

আপনার m_Queueপূর্ণসংখ্যার সমন্বিত ধারণা:

std::queue<int>().swap(m_Queue)

অন্যথায়, যদি এটিতে Jobবস্তুর প্রতি উদাহরণ পয়েন্টার থাকে , তবে:

std::queue<Job*>().swap(m_Queue)

এইভাবে আপনি আপনার সাথে একটি খালি সারি অদলবদল করুন m_Queue, এভাবে m_Queueখালি হয়ে যাবে।


1

আমি বরং swap()একটি নতুন তৈরি করা কাতুর বস্তুর উপর নির্ভর বা কাতারে সেট করতে চাই না , কারণ সারি উপাদানগুলি সঠিকভাবে ধ্বংস হয় নি। কল করা pop()সম্পর্কিত উপাদানটির জন্য ডেস্ট্রাক্টরকে আহ্বান করে। এটি <int>কাতারে একটি সমস্যা নাও হতে পারে তবে অবজেক্টযুক্ত ক্যুগুলিতে খুব ভাল পার্শ্ব প্রতিক্রিয়া থাকতে পারে।

সুতরাং while(!queue.empty()) queue.pop();যদি আপনি সম্ভাব্য পার্শ্ব প্রতিক্রিয়াগুলি প্রতিরোধ করতে চান তবে একটি লুপ দুর্ভাগ্যবশত কমপক্ষে অবজেক্টযুক্ত ক্যুগুলির জন্য সবচেয়ে কার্যকর সমাধান বলে মনে হচ্ছে।


3
swap()বা অ্যাসাইনমেন্টটি এখন ডিফল্ট কাতারে ডেস্ট্রাক্টরকে কল করে, যা সারিতে থাকা সমস্ত বস্তুর ডেস্ট্রাক্টরকে ডাকে। এখন, যদি আপনার কাতারে এমন অবজেক্ট থাকে যা আসলে পয়েন্টার হয়, তবে এটি একটি ভিন্ন সমস্যা but তবে কোনও সরল pop()সেখানে আপনাকে সহায়তা করবে না।
jhfrontz

দুর্ভাগ্যক্রমে কেন? এটি মার্জিত এবং সহজ।
ওএস 2

1

আমি এটি করি (সি ++ 14 ব্যবহার করে):

std::queue<int> myqueue;
myqueue = decltype(myqueue){};

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


আপনি কেন স্পষ্টভাবে অ্যাসাইনমেন্ট অপারেটরে টাইপটি বর্ণনা করবেন? আমি ধরে নিই যে myqueue = { };ঠিক কাজ করবে।
জোয়েল বোডেনম্যান

0

একটি ব্যবহার unique_ptrঠিক আছে হতে পারে।
তারপরে আপনি খালি সারি পাওয়ার জন্য এটি পুনরায় সেট করুন এবং প্রথম সারির মেমরিটি প্রকাশ করুন। জটিলতা হিসাবে? আমি নিশ্চিত নই - তবে অনুমান করুন এটি ও (1)।

সম্ভাব্য কোড:

typedef queue<int> quint;

unique_ptr<quint> p(new quint);

// ...

p.reset(new quint);  // the old queue has been destroyed and you start afresh with an empty queue

আপনি এটা মুছে ফেলার মাধ্যমে কিউ, ঠিক আছে যে খালি যেতে চান, কিন্তু যে কোন প্রশ্নের সম্পর্কে নয়, এবং আমি দেখতে পাচ্ছি না কেন unique_ptr আসে।
manuell

0

আরেকটি বিকল্প হ'ল অন্তর্নিহিত ধারকটি পেতে std::queue::cএবং clearএটিতে কল করার জন্য একটি সাধারণ হ্যাক ব্যবহার করা। এই সদস্যটিকে অবশ্যই std::queueমান অনুযায়ী উপস্থিত থাকতে হবে , তবে দুর্ভাগ্যক্রমে protected। এই হ্যাক এই উত্তর থেকে নেওয়া হয়েছিল ।

#include <queue>

template<class ADAPTER>
typename ADAPTER::container_type& get_container(ADAPTER& a)
{
    struct hack : ADAPTER
    {
        static typename ADAPTER::container_type& get(ADAPTER& a)
        {
            return a .* &hack::c;
        }
    };
    return hack::get(a);
}

template<typename T, typename C>
void clear(std::queue<T,C>& q)
{
    get_container(q).clear();
}

#include <iostream>
int main()
{
    std::queue<int> q;
    q.push(3);
    q.push(5);
    std::cout << q.size() << '\n';
    clear(q);
    std::cout << q.size() << '\n';
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.