দুটি স্ট্যাক ব্যবহার করে কীভাবে একটি সারি কার্যকর করা যায়?


394

ধরুন আমাদের দুটি স্ট্যাক রয়েছে এবং অন্য কোনও অস্থায়ী পরিবর্তনশীল নেই।

কেবলমাত্র দুটি স্ট্যাক ব্যবহার করে একটি সারি ডাটা স্ট্রাকচার "নির্মাণ" করা সম্ভব?

উত্তর:


701

2 টি স্ট্যাক রাখুন, আসুন তাদের কল করুন inboxএবং outbox

সারিবদ্ধ :

  • নতুন উপাদানটি পুশ করুন inbox

ডেকিউ :

  • যদি outboxখালি থাকে তবে প্রতিটি উপাদান থেকে পপিং করে inboxএটিকে আবার চাপিয়ে দিন refoutbox

  • শীর্ষস্থানীয় উপাদানটি পপ করুন এবং থেকে ফিরে আসুন outbox

এই পদ্ধতিটি ব্যবহার করে, প্রতিটি উপাদান প্রতিটি স্ট্যাকের মধ্যে ঠিক একবারে থাকবে - যার অর্থ প্রতিটি উপাদান দু'বার ধাক্কা দেওয়া হবে এবং দু'বার পপ করা হবে, নিয়মিত ধ্রুবক সময় ক্রিয়াকলাপ দেয়।

জাভাতে এখানে একটি বাস্তবায়ন রয়েছে:

public class Queue<E>
{

    private Stack<E> inbox = new Stack<E>();
    private Stack<E> outbox = new Stack<E>();

    public void queue(E item) {
        inbox.push(item);
    }

    public E dequeue() {
        if (outbox.isEmpty()) {
            while (!inbox.isEmpty()) {
               outbox.push(inbox.pop());
            }
        }
        return outbox.pop();
    }

}

13
সবচেয়ে খারাপ সময়ের জটিলতা এখনও ও (এন)। আমি এটি বলার পক্ষে অবিচল রয়েছি কারণ আমি আশা করি সেখানে কোনও শিক্ষার্থী বাইরে নেই (এটি হোমওয়ার্ক / শিক্ষাগত প্রশ্নের মতো মনে হচ্ছে) মনে হয় এটি একটি সারি বাস্তবায়নের একটি গ্রহণযোগ্য উপায়।
টাইলার

26
এটি সত্য যে একক পপ অপারেশনের জন্য সবচেয়ে খারাপ সময় হ'ল ও (এন) (যেখানে এন সারির বর্তমান আকার)। যাইহোক, এন কাতার ক্রিয়াকলাপগুলির সিক্যুয়েন্সের জন্য সবচেয়ে খারাপ সময়টি ও (এন )ও রয়েছে, যা আমাদের নিয়মিত ধ্রুবক সময় দেয়। আমি এইভাবে একটি সারি বাস্তবায়ন করব না, তবে এটি খুব খারাপ নয়।
ডেভ এল।

1
@ টাইলার যদি আপনার স্ট্যাকটি অ্যারে ভিত্তিক হয় তবে বেশিরভাগ ক্ষেত্রে, আপনি সর্বদা একক ক্রিয়াকলাপের জন্য ও (এন) সবচেয়ে খারাপ পরিস্থিতি পাবেন।
টমাস আহলে

2
@Tyler: চেক করুন sgi.com/tech/stl/Deque.html । Deque "উপাদানগুলিতে এলোমেলো অ্যাক্সেসকে সমর্থন করে"। সুতরাং ডেক এবং স্ট্যাক উভয়ই অ্যারে ভিত্তিক। কারণ এটি আপনাকে আরও ভাল রেফারেন্সের লোকেশন দেয় এবং তাই এটি অনুশীলনে দ্রুত।
থমাস আহলে

13
@ নিউটাং এ) সারি 1,2,3 => ইনবক্স [3,2,1] / আউটবক্স [] । খ) dequeue। আউটবক্স খালি, সুতরাং => ইনবক্স [] / আউটবক্স [1,2,3] পুনরায় পূরণ করুন । আউটবক্স থেকে পপ করুন, 1 => ইনবক্স [] / আউটবক্স [2,3] এ ফিরে আসুন । গ) কিউ 4,5 => ইনবক্স [5,4] / আউটবক্স [2,3] । d) ডিকুই। আউটবক্স খালি নয়, সুতরাং আউটবক্স থেকে পপ করুন, 2 => ইনবক্স [5,4] / আউটবক্স [3] এ ফিরে আসুন । এটি কি আরও অর্থবোধ করে?
ডেভ এল।

226

একটি - কিভাবে একটি স্ট্যাক বিপরীত

দুটি স্ট্যাক ব্যবহার করে কীভাবে একটি সারি তৈরি করবেন তা বোঝার জন্য, আপনাকে কীভাবে স্ট্যাকের স্ফটিকটিকে বিপরীত করতে হবে তা বুঝতে হবে। স্ট্যাকটি কীভাবে কাজ করে তা মনে রাখবেন, এটি আপনার রান্নাঘরের ডিশ স্ট্যাকের সাথে খুব মিল। সর্বশেষ ধুয়ে রাখা ডিশটি ক্লিন স্ট্যাকের শীর্ষে থাকবে, যাকে কম্পিউটার বিজ্ঞানে L ast I n F irst O ut (LIFO) বলা হয়।

নীচের মত আমাদের বোতল মত স্ট্যাক কল্পনা করা যাক;

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

আমরা যদি যথাক্রমে 1,2,3 পূর্ণসংখ্যার ধাক্কা দিয়ে রাখি তবে 3 টি স্ট্যাকের শীর্ষে থাকবে। 1 টি প্রথমে ধাক্কা দেওয়া হবে, তারপরে 2 টি 1 টি শীর্ষে রাখা হবে শেষ অবধি, 3 টি স্ট্যাকের শীর্ষে রাখা হবে এবং বোতল হিসাবে উপস্থাপিত আমাদের স্ট্যাকের সর্বশেষ অবস্থা নীচে থাকবে;

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

এখন আমরা আমাদের স্ট্যাকটি উপস্থাপন করেছি বোতল হিসাবে 3,2,1 মানগুলি রয়েছে। এবং আমরা স্ট্যাকটি বিপরীত করতে চাই যাতে স্ট্যাকের শীর্ষ উপাদানটি 1 হবে এবং স্ট্যাকের নীচের উপাদানটি 3 হবে we আমরা কী করতে পারি? আমরা বোতলটি নিতে পারি এবং এটিকে ধরে রাখতে পারি যাতে সমস্ত মান ক্রম অনুযায়ী বিপরীত হয়?

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

হ্যাঁ আমরা এটি করতে পারি তবে এটি একটি বোতল। একই প্রক্রিয়াটি করতে, আমাদের একটি দ্বিতীয় স্ট্যাক থাকা দরকার যা বিপরীত ক্রমে প্রথম স্ট্যাক উপাদান সংরক্ষণ করতে চলেছে। বামদিকে আমাদের জনবহুল স্ট্যাকটি এবং ডানদিকে আমাদের নতুন খালি স্ট্যাকটি রাখি। উপাদানগুলির ক্রমটি বিপরীত করতে, আমরা প্রতিটি উপাদান বাম স্ট্যাক থেকে পপ করতে যাচ্ছি এবং তাদের ডান স্ট্যাকের দিকে ঠেলাচ্ছি। নীচের চিত্রটিতে আমরা যা করি তা আপনি দেখতে পাচ্ছেন;

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

সুতরাং আমরা জানি কিভাবে একটি স্ট্যাক বিপরীত করতে।

বি - একটি সারি হিসাবে দুটি স্ট্যাক ব্যবহার করা

পূর্ববর্তী অংশে, আমি ব্যাখ্যা করেছি যে কীভাবে আমরা স্ট্যাক উপাদানগুলির ক্রমটিকে বিপরীত করতে পারি। এটি গুরুত্বপূর্ণ ছিল, কারণ যদি আমরা স্ট্যাকগুলিতে উপাদানগুলিকে ধাক্কা এবং পপ করি তবে আউটপুটটি একটি সারির বিপরীত ক্রমে হবে। একটি উদাহরণ বিবেচনা করে, আসুন {1, 2, 3, 4, 5}একটি স্ট্যাকের জন্য পূর্ণসংখ্যার অ্যারে টিপুন। যদি আমরা উপাদানগুলি পপ করি এবং স্ট্যাকটি খালি না হওয়া পর্যন্ত মুদ্রণ করি, তবে আমরা পুশিং ক্রমের বিপরীত ক্রমে অ্যারেটি পেয়ে যাব, যা {5, 4, 3, 2, 1}মনে রাখা হবে একই ইনপুটটির জন্য, যদি সারিটি খালি না হওয়া পর্যন্ত আমরা সারিটি সনাক্ত করি তবে আউটপুট হবে {1, 2, 3, 4, 5}। সুতরাং এটি স্পষ্টত যে উপাদানগুলির একই ইনপুট ক্রমের জন্য, সারির আউটপুট হ'ল স্ট্যাকের আউটপুটটির বিপরীত। যেহেতু আমরা জানি যে কীভাবে একটি অতিরিক্ত স্ট্যাক ব্যবহার করে কোনও স্ট্যাক বিপরীত করতে হয়, আমরা দুটি স্ট্যাক ব্যবহার করে একটি সারি তৈরি করতে পারি।

আমাদের সারির মডেলটিতে দুটি স্ট্যাক থাকবে। একটি স্ট্যাক enqueueঅপারেশনের জন্য ব্যবহৃত হবে (বাম দিকে স্ট্যাক # 1, ইনপুট স্ট্যাক হিসাবে ডাকা হবে), অপরটি স্ট্যাক dequeueঅপারেশনের জন্য ব্যবহৃত হবে (ডানদিকে স্ট্যাক # 2, আউটপুট স্ট্যাক নামে পরিচিত)। নীচের চিত্রটি দেখুন;

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

আমাদের সিউডো কোডটি নীচের মতো রয়েছে;


অপারেশন এনকুই

Push every input element to the Input Stack

অপারেশন ডেকিউ

If ( Output Stack is Empty)
    pop every element in the Input Stack
    and push them to the Output Stack until Input Stack is Empty

pop from Output Stack

আসুন {1, 2, 3}যথাক্রমে পূর্ণসংখ্যাগুলি সারিবদ্ধ করুন । পূর্ণসংখ্যাগুলি ইনপুট স্ট্যাকের উপর চাপ দেওয়া হবে ( স্ট্যাক # 1 ) যা বাম দিকে অবস্থিত;

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

তারপরে আমরা যদি কোনও ডিউইউ অপারেশন চালিয়ে যাই তবে কী হবে? যখনই কোনও ডীকু অপারেশন কার্যকর করা হবে তখন কাতারে আউটপুট স্ট্যাকটি খালি আছে কিনা তা পরীক্ষা করা হবে (উপরের সিউডো কোডটি দেখুন) আউটপুট স্ট্যাকটি খালি থাকলে ইনপুট স্ট্যাক আউটপুটটিতে বের করা যাচ্ছে তাই উপাদানগুলি ইনপুট স্ট্যাকটি বিপরীত হবে। কোনও মান ফেরত দেওয়ার আগে, সারির অবস্থা নীচের মতো হবে;

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

আউটপুট স্ট্যাকের উপাদানগুলির ক্রম দেখুন (স্ট্যাক # 2)। এটা সুস্পষ্ট যে আমরা আউটপুট স্ট্যাক থেকে উপাদানগুলি পপ করতে পারি যাতে আউটপুটটি একই রকম হয় যেন আমরা কোনও সারি থেকে বেরিয়ে এসেছি। এইভাবে, আমরা দুটি ডেকিউ অপারেশন চালিয়ে দিলে প্রথমে {1, 2}যথাক্রমে পাব । তারপরে উপাদান 3 আউটপুট স্ট্যাকের একমাত্র উপাদান হবে এবং ইনপুট স্ট্যাকটি খালি থাকবে। যদি আমরা 4 এবং 5 উপাদানগুলিকে সারিবদ্ধ করি, তবে সারিটির অবস্থা নিম্নরূপ হবে;

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

এখন আউটপুট স্ট্যাকটি খালি নয়, এবং আমরা যদি কোনও ডিউইউ ক্রিয়াকলাপ চালিয়ে থাকি তবে আউটপুট স্ট্যাক থেকে কেবল 3 টি পপআপ হয়ে যাবে। তারপরে রাজ্যটিকে নীচে হিসাবে দেখা যাবে;

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

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

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

দেখতে সহজ, দুটি dequeue অপারেশন আউটপুট হবে {4, 5}

সি - দুটি স্ট্যাকের সাহায্যে নির্মিত কাতারের বাস্তবায়ন

জাভাতে এখানে একটি বাস্তবায়ন দেওয়া আছে। আমি স্ট্যাকের বিদ্যমান প্রয়োগটি ব্যবহার করতে যাচ্ছি না সুতরাং উদাহরণটি হুইলটি পুনরায় উদ্বেগ করতে চলেছে;

সি - 1) মাইস্ট্যাক ক্লাস: একটি সাধারণ স্ট্যাক বাস্তবায়ন

public class MyStack<T> {

    // inner generic Node class
    private class Node<T> {
        T data;
        Node<T> next;

        public Node(T data) {
            this.data = data;
        }
    }

    private Node<T> head;
    private int size;

    public void push(T e) {
        Node<T> newElem = new Node(e);

        if(head == null) {
            head = newElem;
        } else {
            newElem.next = head;
            head = newElem;     // new elem on the top of the stack
        }

        size++;
    }

    public T pop() {
        if(head == null)
            return null;

        T elem = head.data;
        head = head.next;   // top of the stack is head.next

        size--;

        return elem;
    }

    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    public void printStack() {
        System.out.print("Stack: ");

        if(size == 0)
            System.out.print("Empty !");
        else
            for(Node<T> temp = head; temp != null; temp = temp.next)
                System.out.printf("%s ", temp.data);

        System.out.printf("\n");
    }
}

সি - 2) মাইকিউউ ক্লাস: দুটি স্ট্যাক ব্যবহার করে সারি প্রয়োগকরণ

public class MyQueue<T> {

    private MyStack<T> inputStack;      // for enqueue
    private MyStack<T> outputStack;     // for dequeue
    private int size;

    public MyQueue() {
        inputStack = new MyStack<>();
        outputStack = new MyStack<>();
    }

    public void enqueue(T e) {
        inputStack.push(e);
        size++;
    }

    public T dequeue() {
        // fill out all the Input if output stack is empty
        if(outputStack.isEmpty())
            while(!inputStack.isEmpty())
                outputStack.push(inputStack.pop());

        T temp = null;
        if(!outputStack.isEmpty()) {
            temp = outputStack.pop();
            size--;
        }

        return temp;
    }

    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0;
    }

}

সি - 3) ডেমো কোড

public class TestMyQueue {

    public static void main(String[] args) {
        MyQueue<Integer> queue = new MyQueue<>();

        // enqueue integers 1..3
        for(int i = 1; i <= 3; i++)
            queue.enqueue(i);

        // execute 2 dequeue operations 
        for(int i = 0; i < 2; i++)
            System.out.println("Dequeued: " + queue.dequeue());

        // enqueue integers 4..5
        for(int i = 4; i <= 5; i++)
            queue.enqueue(i);

        // dequeue the rest
        while(!queue.isEmpty())
            System.out.println("Dequeued: " + queue.dequeue());
    }

}

সি - 4) নমুনা আউটপুট

Dequeued: 1
Dequeued: 2
Dequeued: 3
Dequeued: 4
Dequeued: 5

18
আমি পারলে সারা দিন এটি +1 করতাম। ধীরে ধীরে সময়টি কীভাবে অনুভূত হয়েছিল তা আমি বুঝতে পারি না। আপনার চিত্রগুলি প্রকৃতপক্ষে জিনিসগুলি পরিষ্কার করেছে, বিশেষত অবশিষ্ট উপাদানগুলি আউটপুট স্ট্যাকে রেখে দেওয়ার অংশ, এবং খালি হয়ে গেলে কেবল পুনরায় পূরণ করা।
শেন ম্যাককুইলান

1
এটি পপ চলাকালীন সময়সীমার ত্রুটিগুলি আটকাতে সত্যিই সহায়তা করেছিল। আমি উপাদানগুলিকে মূল স্ট্যাকটিতে ফিরিয়ে দিচ্ছিলাম তবে এটি করার দরকার নেই। যশ!
প্রাণিত বাঙ্কার

2
সমস্ত মন্তব্য এই পরে মডেল করা উচিত।
lolololol ওল

4
আমার সত্যিই এর সমাধানের দরকার নেই, কেবল ব্রাউজিং ... তবে যখন আমি এর মতো উত্তর দেখি তখন কেবল প্রেমে পড়ি .. দুর্দান্ত উত্তর !!!
ম্যাভেরিক

80

এমনকি আপনি কেবল একটি স্ট্যাক ব্যবহার করে একটি সারি অনুকরণ করতে পারেন। দ্বিতীয় (অস্থায়ী) স্ট্যাক সন্নিবেশ পদ্ধতিতে পুনরাবৃত্ত কলগুলির কল স্ট্যাকের মাধ্যমে সিমুলেটেড করা যায়।

কাতারে একটি নতুন উপাদান whenোকানোর সময় নীতিটি একই থাকে:

  • ক্রমগুলি বিপরীত করতে আপনাকে উপাদানগুলি একটি স্ট্যাক থেকে অন্য অস্থায়ী স্ট্যাকের মধ্যে স্থানান্তর করতে হবে।
  • তারপরে অস্থায়ী স্ট্যাকের উপরে নতুন উপাদানটি প্রবেশ করানোর জন্য চাপ দিন push
  • তারপরে উপাদানগুলিকে মূল স্ট্যাকে ফিরিয়ে দিন
  • নতুন উপাদানটি স্ট্যাকের নীচে থাকবে এবং প্রাচীনতম উপাদানটি শীর্ষে থাকবে (প্রথমে পপ করা হবে)

কেবলমাত্র একটি স্ট্যাক ব্যবহার করে একটি সারি শ্রেণি শ্রেণি নিম্নরূপ হবে:

public class SimulatedQueue<E> {
    private java.util.Stack<E> stack = new java.util.Stack<E>();

    public void insert(E elem) {
        if (!stack.empty()) {
            E topElem = stack.pop();
            insert(elem);
            stack.push(topElem);
        }
        else
            stack.push(elem);
    }

    public E remove() {
        return stack.pop();
    }
}

51
সম্ভবত কোডটি মার্জিত দেখায় তবে এটি খুব অদক্ষ (ও (এন ** 2) সন্নিবেশ করা) এবং এটি এখনও দুটি স্ট্যাক রয়েছে, একটি গাদা এবং একটি কল স্ট্যাকের মধ্যে রয়েছে, যেমন @ স্পাইথনউইকটি উল্লেখ করেছে। একটি পুনরাবৃত্তিমূলক অ্যালগরিদমের জন্য, আপনি সর্বদা পুনরাবৃত্তি সমর্থনকারী ভাষাগুলিতে কল স্ট্যাক থেকে একটি "অতিরিক্ত" স্ট্যাক ধরতে পারেন।
অ্যান্টি হুইমা

1
@ antti.huima এবং আপনি কীভাবে ব্যাখ্যা করতে পারেন যে এটি কীভাবে চতুর্ভুজ ratোকানো যেতে পারে ?! আমি যা বুঝি সেগুলি থেকে, সন্নিবেশ করানো এন পপ এবং এন ক্রিয়াকলাপগুলি তাই এটি একেবারে লিনিয়ার হে (এন) অ্যালগোরিদম।
এলপি_

1
@ এলপি_ n itemsউপরের ডেটা কাঠামোটি ব্যবহার করে কাতারে প্রবেশ করতে চতুর্ভুজ সময় O (n ^ 2) লাগে । যোগফল (1 + 2 + 4 + 8 + .... + 2(n-1))ফলাফল ~O(n^2)। আমি আশা করি আপনি পয়েন্ট পাবেন।
অঙ্কিত কুমার

1
@ antti.huima আপনি সন্নিবেশ ফাংশনটির জটিলতার কথা বলছিলেন (আপনি "ও (এন 2) সন্নিবেশ" বলেছেন - আপনি সম্ভবত "ও (এন 2) পূরণ") বোঝাচ্ছেনকনভেনশন অনুসারে , "জটিলতা সন্নিবেশ" হ'ল একটি সন্নিবেশের সময়টি , যা এখানে ইতিমধ্যে উপস্থিত উপাদানগুলির সংখ্যার মধ্যে লিনিয়ার। আমরা যদি এন আইটেমগুলি সন্নিবেশ করার জন্য প্রয়োজনীয় সময়ে কথা বলি, আমরা বলব একটি হ্যাশ টেবিলের লিনিয়ার সন্নিবেশ রয়েছে has কোন ঘটনা না।
এলপি_

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

11

যদিও সময় জটিলতাগুলি আরও খারাপ হবে। একটি ভাল সারি বাস্তবায়ন স্থির সময়ে সবকিছু করে।

সম্পাদন করা

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

আরও কিছু বিশদ বিবরণ : কেন দুটি স্ট্যাক ব্যবহার করা কেবল একটি সারির চেয়ে খারাপ: আপনি যদি দুটি স্ট্যাক ব্যবহার করেন এবং কেউ যদি আউটবক্সটি খালি অবস্থায় ডিক্যু বলে থাকেন তবে আপনাকে ইনবক্সের নীচে পৌঁছানোর জন্য রৈখিক সময় প্রয়োজন (যেমন আপনি দেখতে পাচ্ছেন) ডেভের কোডে)।

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


গড় ক্ষেত্রে নয়। ব্রায়ানের উত্তরে এমন একটি সারি বর্ণিত হয়েছে যা ধীরে ধীরে সারিবদ্ধভাবে কাজ করত এবং তাত্পর্যপূর্ণ কার্য সম্পাদন করত ।
ড্যানিয়েল স্পিওক

সেটা সত্য. আপনার গড় কেস এবং মোড়িত সময়ের জটিলতা একই রকম। তবে ডিফল্টটি সাধারণত প্রতি-অপারেশন সবচেয়ে খারাপ হয় এবং এটি O (n) হয় যেখানে n কাঠামোর বর্তমান আকার।
টাইলার

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

1
"সবচেয়ে খারাপ কেস" এবং "amorised" সময় জটিলতা দুটি বিভিন্ন ধরণের। "সবচেয়ে খারাপ-কেসটি সূক্ষ্মভাবে তৈরি করা যেতে পারে" তা বলার অর্থ নেই - আপনি যদি সবচেয়ে খারাপ-কেস = অ্যামোরিটাইজড করতে পারেন তবে এটি একটি উল্লেখযোগ্য উন্নতি হবে; আপনি কেবল খারাপ পরিস্থিতি সম্পর্কে কথা বলবেন, কোনও গড় নেই।
টাইলার

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

8

কিউ প্রয়োগ করা হবে এবং কিউ স্ট্যাক 1 এবং স্ট্যাক 2 প্রয়োগ করতে ব্যবহৃত স্ট্যাকগুলি প্রয়োগ করা হবে।

q দুটি উপায়ে প্রয়োগ করা যেতে পারে :

পদ্ধতি 1 (এনকুইউ অপারেশন ব্যয়বহুল করে)

এই পদ্ধতিটি নিশ্চিত করে যে সদ্য প্রবেশ করা উপাদানটি সর্বদা স্ট্যাক 1 এর শীর্ষে থাকে, যাতে ডিউইউ ক্রিয়াকলাপটি স্ট্যাক 1 থেকে পপ হয় just উপাদানটিকে স্ট্যাক 1 এর শীর্ষে রাখতে স্ট্যাক 2 ব্যবহার করা হয়।

enQueue(q, x)
1) While stack1 is not empty, push everything from stack1 to stack2.
2) Push x to stack1 (assuming size of stacks is unlimited).
3) Push everything back to stack1.
deQueue(q)
1) If stack1 is empty then error
2) Pop an item from stack1 and return it.

পদ্ধতি 2 (DeQueue অপারেশন ব্যয়বহুল করে)

এই পদ্ধতিতে, এন-সারি ক্রিয়াকলাপে, নতুন উপাদানটি স্ট্যাক 1 এর শীর্ষে প্রবেশ করা হয়। ডি-ক্যু অপারেশনে, যদি স্ট্যাক 2 খালি থাকে তবে সমস্ত উপাদান স্ট্যাক 2 এ সরানো হবে এবং অবশেষে স্ট্যাক 2 এর শীর্ষস্থান ফিরে আসবে।

enQueue(q,  x)
 1) Push x to stack1 (assuming size of stacks is unlimited).

deQueue(q)
 1) If both stacks are empty then error.
 2) If stack2 is empty
   While stack1 is not empty, push everything from stack1 to stack2.
 3) Pop the element from stack2 and return it.

পদ্ধতি 2 পদ্ধতিটির তুলনায় অবশ্যই ভাল is


আপনার পদ্ধতি 2 ব্যতীত আমি যে সমাধানগুলি বুঝলাম সেগুলির কোনওটিই আমি পছন্দ করি না you
দ্য গ্রিনক্যাবেজ


3

সি # তে একটি সমাধান

public class Queue<T> where T : class
{
    private Stack<T> input = new Stack<T>();
    private Stack<T> output = new Stack<T>();
    public void Enqueue(T t)
    {
        input.Push(t);
    }

    public T Dequeue()
    {
        if (output.Count == 0)
        {
            while (input.Count != 0)
            {
                output.Push(input.Pop());
            }
        }

        return output.Pop();
    }
}

2

সারিতে দুই stacks হিসাবে সংজ্ঞায়িত করা হয় stack1 এবং stack2

এনকুই : ইউকিউযুক্ত উপাদানগুলি সর্বদা স্ট্যাক 1 এ ঠেলা হয়

ডেকিউ: স্ট্যাক 2 এর শীর্ষটি পপআপ করা যেতে পারে কারণ স্ট্যাক 2 খালি না থাকলে কাতারে এটি প্রথম উপাদান .োকানো হয়। যখন স্ট্যাক 2 খালি থাকে, আমরা স্ট্যাক 1 থেকে সমস্ত উপাদান পপ করি এবং একে একে স্ট্যাক 2-এ ঠেলে দেই । একটি সারিতে প্রথম উপাদানটি স্ট্যাক 1 এর নীচে ঠেলা যায় । এটি পপিং এবং প্যাশিং অপারেশনের পরে সরাসরি পপ আউট করা যায় যেহেতু এটি স্ট্যাক 2 এর শীর্ষে রয়েছে

নিম্নলিখিত একই সি ++ নমুনা কোড:

template <typename T> class CQueue
{
public:
    CQueue(void);
    ~CQueue(void);

    void appendTail(const T& node); 
    T deleteHead();                 

private:
    stack<T> stack1;
    stack<T> stack2;
};

template<typename T> void CQueue<T>::appendTail(const T& element) {
    stack1.push(element);
} 

template<typename T> T CQueue<T>::deleteHead() {
    if(stack2.size()<= 0) {
        while(stack1.size()>0) {
            T& data = stack1.top();
            stack1.pop();
            stack2.push(data);
        }
    }


    if(stack2.size() == 0)
        throw new exception("queue is empty");


    T head = stack2.top();
    stack2.pop();


    return head;
}

এই সমাধানটি আমার ব্লগ থেকে ধার করা হয়েছে । ধাপে ধাপে অপারেশন সিমুলেশনগুলির সাথে আরও বিশদ বিশ্লেষণ আমার ব্লগ ওয়েবপৃষ্ঠায় উপলব্ধ।


2

নীচের উপাদানটি পেতে আপনাকে প্রথম স্ট্যাকের বাইরে সমস্ত কিছু পপ করতে হবে। তারপরে প্রতিটি "ডিকিউ" ক্রিয়াকলাপের জন্য সেগুলি আবার দ্বিতীয় স্ট্যাকের দিকে রেখে দিন।


3
হ্যাঁ তুমিই ঠিক. আমি অবাক, আপনি এত ডাউন ভোট পেয়েছেন কিভাবে? আমি আপনার উত্তরটিকে উজাড় করে দিয়েছি
বিনিতা ভারতী

এটি চূড়ান্তভাবে দেখার জন্য যে এটিই তাঁর শেষ উত্তর এবং তখন থেকেই এটি এক দশক হয়ে গেছে।
শানু গুপ্ত

2

সি # বিকাশকারীর জন্য এখানে সম্পূর্ণ প্রোগ্রামটি রয়েছে:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace QueueImplimentationUsingStack
{
    class Program
    {
        public class Stack<T>
        {
            public int size;
            public Node<T> head;
            public void Push(T data)
            {
                Node<T> node = new Node<T>();
                node.data = data;
                if (head == null)
                    head = node;
                else
                {
                    node.link = head;
                    head = node;
                }
                size++;
                Display();
            }
            public Node<T> Pop()
            {
                if (head == null)
                    return null;
                else
                {
                    Node<T> temp = head;
                    //temp.link = null;
                    head = head.link;
                    size--;
                    Display();
                    return temp;
                }
            }
            public void Display()
            {
                if (size == 0)
                    Console.WriteLine("Empty");
                else
                {
                    Console.Clear();
                    Node<T> temp = head;
                    while (temp!= null)
                    {
                        Console.WriteLine(temp.data);
                        temp = temp.link;
                    }
                }
            }
        }

        public class Queue<T>
        {
            public int size;
            public Stack<T> inbox;
            public Stack<T> outbox;
            public Queue()
            {
                inbox = new Stack<T>();
                outbox = new Stack<T>();
            }
            public void EnQueue(T data)
            {
                inbox.Push(data);
                size++;
            }
            public Node<T> DeQueue()
            {
                if (outbox.size == 0)
                {
                    while (inbox.size != 0)
                    {
                        outbox.Push(inbox.Pop().data);
                    }
                }
                Node<T> temp = new Node<T>();
                if (outbox.size != 0)
                {
                    temp = outbox.Pop();
                    size--;
                }
                return temp;
            }

        }
        public class Node<T>
        {
            public T data;
            public Node<T> link;
        }

        static void Main(string[] args)
        {
            Queue<int> q = new Queue<int>();
            for (int i = 1; i <= 3; i++)
                q.EnQueue(i);
           // q.Display();
            for (int i = 1; i < 3; i++)
                q.DeQueue();
            //q.Display();
            Console.ReadKey();
        }
    }
}

2

স্ট্যাকগুলি ব্যবহার করে একটি সারির নিম্নলিখিত ক্রিয়াকলাপগুলি বাস্তবায়ন করুন।

পুশ (এক্স) - সারির পিছনে এলিমেন্ট এক্স চাপুন।

পপ () - সারির সামনে থেকে উপাদানটি সরিয়ে দেয়।

উঁকি দেওয়া () - সামনের উপাদান পান।

খালি () - সারিটি খালি কিনা তা ফিরিয়ে দিন।

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

class MyQueue {

  Stack<Integer> input;
  Stack<Integer> output;

  /** Initialize your data structure here. */
  public MyQueue() {
    input = new Stack<Integer>();
    output = new Stack<Integer>();
  }

  /** Push element x to the back of queue. */
  public void push(int x) {
    input.push(x);
  }

  /** Removes the element from in front of queue and returns that element. */
  public int pop() {
    peek();
    return output.pop();
  }

  /** Get the front element. */
  public int peek() {
    if(output.isEmpty()) {
        while(!input.isEmpty()) {
            output.push(input.pop());
        }
    }
    return output.peek();
  }

  /** Returns whether the queue is empty. */
  public boolean empty() {
    return input.isEmpty() && output.isEmpty();
  }
}

1
// Two stacks s1 Original and s2 as Temp one
    private Stack<Integer> s1 = new Stack<Integer>();
    private Stack<Integer> s2 = new Stack<Integer>();

    /*
     * Here we insert the data into the stack and if data all ready exist on
     * stack than we copy the entire stack s1 to s2 recursively and push the new
     * element data onto s1 and than again recursively call the s2 to pop on s1.
     * 
     * Note here we can use either way ie We can keep pushing on s1 and than
     * while popping we can remove the first element from s2 by copying
     * recursively the data and removing the first index element.
     */
    public void insert( int data )
    {
        if( s1.size() == 0 )
        {
            s1.push( data );
        }
        else
        {
            while( !s1.isEmpty() )
            {
                s2.push( s1.pop() );
            }
            s1.push( data );
            while( !s2.isEmpty() )
            {
                s1.push( s2.pop() );
            }
        }
    }

    public void remove()
    {
        if( s1.isEmpty() )
        {
            System.out.println( "Empty" );
        }
        else
        {
            s1.pop();

        }
    }

1

সুইফটে দুটি স্ট্যাক ব্যবহার করে একটি সারি কার্যকর করা:

struct Stack<Element> {
    var items = [Element]()

    var count : Int {
        return items.count
    }

    mutating func push(_ item: Element) {
        items.append(item)
    }

    mutating func pop() -> Element? {
        return items.removeLast()
    }

    func peek() -> Element? {
        return items.last
    }
}

struct Queue<Element> {
    var inStack = Stack<Element>()
    var outStack = Stack<Element>()

    mutating func enqueue(_ item: Element) {
        inStack.push(item)
    }

    mutating func dequeue() -> Element? {
        fillOutStack() 
        return outStack.pop()
    }

    mutating func peek() -> Element? {
        fillOutStack()
        return outStack.peek()
    }

    private mutating func fillOutStack() {
        if outStack.count == 0 {
            while inStack.count != 0 {
                outStack.push(inStack.pop()!)
            }
        }
    }
}

1

আপনি দুটি স্ট্যাক সহ একটি সারি প্রয়োগের সাথে সম্পর্কিত অনেকগুলি পোস্ট পাবেন: ১. হয় এনকুইউ প্রক্রিয়াটিকে আরও ব্যয়বহুল করে ২. বা ডিউইউ প্রক্রিয়াটিকে অনেক বেশি ব্যয়বহুল করে তোলে

https://www.geeksforgeeks.org/queue-using-stacks/

উপরের পোস্টটি থেকে আমি খুঁজে বের করার একটি গুরুত্বপূর্ণ উপায় হ'ল কেবল স্ট্যাক ডেটা স্ট্রাকচার এবং পুনরাবৃত্তি কল স্ট্যাক সহ সারি তৈরি করা।

যদিও কেউ যুক্তি দিতে পারে যে আক্ষরিকভাবে এটি এখনও দুটি স্ট্যাক ব্যবহার করছে তবে আদর্শভাবে এটি কেবল একটি স্ট্যাকের ডেটা স্ট্রাকচার ব্যবহার করছে।

নীচে সমস্যার ব্যাখ্যা দেওয়া হল:

  1. ডেটা এনকুইউয়েং এবং ডিকিউ করার জন্য একটি একক স্ট্যাক ঘোষণা করুন এবং স্ট্যাকের মধ্যে ডেটা পুশ করুন।

  2. যখন ডিউইউয়ের একটি বেস শর্ত রয়েছে যেখানে স্ট্যাকের আকার 1 থাকে তখন স্ট্যাকের উপাদানটি পপ হয় This

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

কোডটি নীচের মত দেখাবে:

if (s1.isEmpty())
System.out.println("The Queue is empty");
        else if (s1.size() == 1)
            return s1.pop();
        else {
            int x = s1.pop();
            int result = deQueue();
            s1.push(x);
            return result;

এইভাবে আপনি একটি একক স্ট্যাক ডেটা কাঠামো এবং পুনরাবৃত্তি কল স্ট্যাক ব্যবহার করে একটি সারি তৈরি করতে পারেন।


1

নীচে ES6 সিনট্যাক্স ব্যবহার করে জাভাস্ক্রিপ্ট ভাষায় সমাধান দেওয়া হয়েছে।

Stack.js

//stack using array
class Stack {
  constructor() {
    this.data = [];
  }

  push(data) {
    this.data.push(data);
  }

  pop() {
    return this.data.pop();
  }

  peek() {
    return this.data[this.data.length - 1];
  }

  size(){
    return this.data.length;
  }
}

export { Stack };

QueueUsingTwoStacks.js

import { Stack } from "./Stack";

class QueueUsingTwoStacks {
  constructor() {
    this.stack1 = new Stack();
    this.stack2 = new Stack();
  }

  enqueue(data) {
    this.stack1.push(data);
  }

  dequeue() {
    //if both stacks are empty, return undefined
    if (this.stack1.size() === 0 && this.stack2.size() === 0)
      return undefined;

    //if stack2 is empty, pop all elements from stack1 to stack2 till stack1 is empty
    if (this.stack2.size() === 0) {
      while (this.stack1.size() !== 0) {
        this.stack2.push(this.stack1.pop());
      }
    }

    //pop and return the element from stack 2
    return this.stack2.pop();
  }
}

export { QueueUsingTwoStacks };

নীচে ব্যবহার:

index.js

import { StackUsingTwoQueues } from './StackUsingTwoQueues';

let que = new QueueUsingTwoStacks();
que.enqueue("A");
que.enqueue("B");
que.enqueue("C");

console.log(que.dequeue());  //output: "A"

এটি বাগড আপনি যদি শনাক্ত করার পরে আরও উপাদান সজ্জিত করেন তবে আপনি সেগুলিতে প্রবেশ করুন stack1। আপনি যখন dequeueআবার যান , আপনি তাদের আইটেমগুলিতে সরিয়ে নিয়ে যাবেন stack2সেখানে ইতিমধ্যে যা আছে তার আগে রেখে দিন।
আলেকজান্ডার - মনিকা পুনরায়

0

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

যেহেতু একটি স্ট্যাক বাস্তবায়নের পক্ষে সহজ, আমি ভেবেছিলাম যে আমি একটি ডাবল শেষ সারিটি সম্পাদন করতে দুটি স্ট্যাক ব্যবহার করে চেষ্টা করব। আমার উত্তরে আমি কীভাবে পৌঁছেছি তা আরও ভালভাবে বুঝতে আমি বাস্তবায়নটি দুটি ভাগে বিভক্ত করেছি, প্রথম অংশটি আশা করা সহজ আশাবাদী তবে এটি অসম্পূর্ণ।

type IntQueue struct {
    front       []int
    back        []int
}

func (q *IntQueue) PushFront(v int) {
    q.front = append(q.front, v)
}

func (q *IntQueue) Front() int {
    if len(q.front) > 0 {
        return q.front[len(q.front)-1]
    } else {
        return q.back[0]
    }
}

func (q *IntQueue) PopFront() {
    if len(q.front) > 0 {
        q.front = q.front[:len(q.front)-1]
    } else {
        q.back = q.back[1:]
    }
}

func (q *IntQueue) PushBack(v int) {
    q.back = append(q.back, v)
}

func (q *IntQueue) Back() int {
    if len(q.back) > 0 {
        return q.back[len(q.back)-1]
    } else {
        return q.front[0]
    }
}

func (q *IntQueue) PopBack() {
    if len(q.back) > 0 {
        q.back = q.back[:len(q.back)-1]
    } else {
        q.front = q.front[1:]
    }
}

এটি মূলত দুটি স্ট্যাক যেখানে আমরা স্ট্যাকের নীচে একে অপরের দ্বারা ম্যানিপুলেট করার অনুমতি দিই। আমি এসটিএল নামকরণের কনভেনশনগুলিও ব্যবহার করেছি, যেখানে stতিহ্যবাহী ধাক্কা, পপ, একটি স্ট্যাকের পিক অপারেশনগুলির সামনের / পিছনের উপসর্গ থাকে যদিও তারা সারিটির সামনের দিকে বা পিছনে উল্লেখ করে।

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

type IntQueue struct {
    front       []int
    frontOffset int
    back        []int
    backOffset  int
}

func (q *IntQueue) PushFront(v int) {
    if q.backOffset > 0 {
        i := q.backOffset - 1
        q.back[i] = v
        q.backOffset = i
    } else {
        q.front = append(q.front, v)
    }
}

func (q *IntQueue) Front() int {
    if len(q.front) > 0 {
        return q.front[len(q.front)-1]
    } else {
        return q.back[q.backOffset]
    }
}

func (q *IntQueue) PopFront() {
    if len(q.front) > 0 {
        q.front = q.front[:len(q.front)-1]
    } else {
        if len(q.back) > 0 {
            q.backOffset++
        } else {
            panic("Cannot pop front of empty queue.")
        }
    }
}

func (q *IntQueue) PushBack(v int) {
    if q.frontOffset > 0 {
        i := q.frontOffset - 1
        q.front[i] = v
        q.frontOffset = i
    } else {
        q.back = append(q.back, v)
    }
}

func (q *IntQueue) Back() int {
    if len(q.back) > 0 {
        return q.back[len(q.back)-1]
    } else {
        return q.front[q.frontOffset]
    }
}

func (q *IntQueue) PopBack() {
    if len(q.back) > 0 {
        q.back = q.back[:len(q.back)-1]
    } else {
        if len(q.front) > 0 {
            q.frontOffset++
        } else {
            panic("Cannot pop back of empty queue.")
        }
    }
}

এটি অনেক ছোট ফাংশন তবে এর মধ্যে 6 টি ফাংশন 3 এর মধ্যে অন্যটির কেবল আয়না।


আপনি এখানে অ্যারে ব্যবহার করছেন। আপনার স্ট্যাকগুলি কোথায় আছে তা আমি দেখতে পাচ্ছি না।
মেলপোমেন

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

@ মেলপোমেন আসলে, এটি ঠিক অর্ধেক ঠিক, আমি দ্বিগুণ সমাপ্ত স্ট্যাকগুলি ধরে নিচ্ছি। আমি কিছু শর্তে নীচে থেকে স্ট্যান্ডটিকে একটি মানহীন উপায়ে পরিবর্তন করার অনুমতি দিচ্ছি।
জন লিডেগ্রেন

0

এখানে লিঙ্কযুক্ত তালিকা ব্যবহার করে জাভাতে আমার সমাধানটি দেওয়া আছে।

class queue<T>{
static class Node<T>{
    private T data;
    private Node<T> next;
    Node(T data){
        this.data = data;
        next = null;
    }
}
Node firstTop;
Node secondTop;

void push(T data){
    Node temp = new Node(data);
    temp.next = firstTop;
    firstTop = temp;
}

void pop(){
    if(firstTop == null){
        return;
    }
    Node temp = firstTop;
    while(temp != null){
        Node temp1 = new Node(temp.data);
        temp1.next = secondTop;
        secondTop = temp1;
        temp = temp.next;
    }
    secondTop = secondTop.next;
    firstTop = null;
    while(secondTop != null){
        Node temp3 = new Node(secondTop.data);
        temp3.next = firstTop;
        firstTop = temp3;
        secondTop = secondTop.next;
    }
}

}

দ্রষ্টব্য: এই ক্ষেত্রে, পপ অপারেশন খুব সময়সাপেক্ষ। সুতরাং আমি দুটি স্ট্যাক ব্যবহার করে একটি সারি তৈরি করার পরামর্শ দেব না।


0

সাথে O(1) dequeue(), যা পাইথনকুইকের উত্তর হিসাবে একই :

// time: O(n), space: O(n)
enqueue(x):
    if stack.isEmpty():
        stack.push(x)
        return
    temp = stack.pop()
    enqueue(x)
    stack.push(temp)

// time: O(1)
x dequeue():
    return stack.pop()

সহ O(1) enqueue()(এটি এই পোস্টে উল্লেখ করা হয়নি তাই এই উত্তর), যা বুদ্বুদ আপ করতে এবং নীচেরতম আইটেমটি ফিরে পেতে ব্যাকট্র্যাকিং ব্যবহার করে।

// O(1)
enqueue(x):
    stack.push(x)

// time: O(n), space: O(n)
x dequeue():
    temp = stack.pop()
    if stack.isEmpty():
        x = temp
    else:
        x = dequeue()
        stack.push(temp)
    return x

স্পষ্টতই, এটি একটি দুর্দান্ত কোডিং অনুশীলন হিসাবে এটি এটি অদক্ষ তবে মার্জিত।


0

** সহজ জেএস সমাধান **

  • দ্রষ্টব্য: আমি অন্যান্য লোকদের মন্তব্য থেকে ধারণা নিয়েছি

/*

enQueue(q,  x)
 1) Push x to stack1 (assuming size of stacks is unlimited).

deQueue(q)
 1) If both stacks are empty then error.
 2) If stack2 is empty
   While stack1 is not empty, push everything from stack1 to stack2.
 3) Pop the element from stack2 and return it.

*/
class myQueue {
    constructor() {
        this.stack1 = [];
        this.stack2 = [];
    }

    push(item) {
        this.stack1.push(item)
    }

    remove() {
        if (this.stack1.length == 0 && this.stack2.length == 0) {
            return "Stack are empty"
        }

        if (this.stack2.length == 0) {

            while (this.stack1.length != 0) {
                this.stack2.push(this.stack1.pop())
            }
        }
        return this.stack2.pop()
    }


    peek() {
        if (this.stack2.length == 0 && this.stack1.length == 0) {
            return 'Empty list'
        }

        if (this.stack2.length == 0) {
            while (this.stack1.length != 0) {
                this.stack2.push(this.stack1.pop())
            }
        }

        return this.stack2[0]
    }

    isEmpty() {
        return this.stack2.length === 0 && this.stack1.length === 0;
    }

}

const q = new myQueue();
q.push(1);
q.push(2);
q.push(3);
q.remove()

console.log(q)


-1
public class QueueUsingStacks<T>
{
    private LinkedListStack<T> stack1;
    private LinkedListStack<T> stack2;

    public QueueUsingStacks()
    {
        stack1=new LinkedListStack<T>();
        stack2 = new LinkedListStack<T>();

    }
    public void Copy(LinkedListStack<T> source,LinkedListStack<T> dest )
    {
        while(source.Head!=null)
        {
            dest.Push(source.Head.Data);
            source.Head = source.Head.Next;
        }
    }
    public void Enqueue(T entry)
    {

       stack1.Push(entry);
    }
    public T Dequeue()
    {
        T obj;
        if (stack2 != null)
        {
            Copy(stack1, stack2);
             obj = stack2.Pop();
            Copy(stack2, stack1);
        }
        else
        {
            throw new Exception("Stack is empty");
        }
        return obj;
    }

    public void Display()
    {
        stack1.Display();
    }


}

প্রতিটি এনকুই অপারেশনের জন্য, আমরা স্ট্যাক 1 এর শীর্ষে যুক্ত করি। প্রতিটি ডিকুয়ের জন্য, আমরা স্ট্যাক 1 এর সামগ্রীটি স্ট্যাক 2 এ খালি করি এবং স্ট্যাকের শীর্ষে থাকা উপাদানটি সরিয়ে ফেলি ime ডাইউয়ের জন্য সময় জটিলতা হ'ল (এন), কারণ আমাদের স্ট্যাক 1 কে স্ট্যাক 2 এ অনুলিপি করতে হবে। এনকুইয়ের সময় জটিলতা নিয়মিত স্ট্যাকের সমান


এই কোডটি অকার্যকর (অপ্রয়োজনীয় অনুলিপি করা) এবং ভাঙ্গা: if (stack2 != null)সর্বদা সত্য কারণ stack2কনস্ট্রাক্টরে ইনস্ট্যান্টেশনযুক্ত।
মেলপোমেন

-2

দুটি java.util.Stack অবজেক্ট ব্যবহার করে সারি প্রয়োগকরণ:

public final class QueueUsingStacks<E> {

        private final Stack<E> iStack = new Stack<>();
        private final Stack<E> oStack = new Stack<>();

        public void enqueue(E e) {
            iStack.push(e);
        }

        public E dequeue() {
            if (oStack.isEmpty()) {
                if (iStack.isEmpty()) {
                    throw new NoSuchElementException("No elements present in Queue");
                }
                while (!iStack.isEmpty()) {
                    oStack.push(iStack.pop());
                }
            }
            return oStack.pop();
        }

        public boolean isEmpty() {
            if (oStack.isEmpty() && iStack.isEmpty()) {
                return true;
            }
            return false;
        }

        public int size() {
            return iStack.size() + oStack.size();
        }

}

3
এই কোডটি কার্যত ড্যাভ এল এর উত্তরের সাথে সমান It এটি নতুন কিছু যোগ করে না, এমনকি কোনও ব্যাখ্যাও দেয় না।
মেলপোমেন

এটি মৌলিক ব্যতিক্রম হ্যান্ডলিংয়ের সাথে আইসপিটি () এবং আকার () পদ্ধতি যুক্ত করে। আমি ব্যাখ্যা যুক্ত করতে সম্পাদনা করব।
রিয়েলপিকে

1
এই অতিরিক্ত পদ্ধতিগুলির জন্য কেউ জিজ্ঞাসা করেনি এবং তারা তুচ্ছ (প্রতিটি লাইন প্রতিটি): return inbox.isEmpty() && outbox.isEmpty()এবং return inbox.size() + outbox.size()যথাক্রমে। ডেভ এল এর কোড ইতিমধ্যে একটি ব্যতিক্রম ছুঁড়েছে যখন আপনি একটি খালি সারি থেকে প্রস্থান করেন। মূল প্রশ্নটি জাভা সম্পর্কেও ছিল না; এটি সাধারণভাবে ডেটা স্ট্রাকচার / অ্যালগরিদম সম্পর্কে ছিল। জাভা বাস্তবায়ন ছিল মাত্র একটি অতিরিক্ত চিত্রণ।
মেলপোমেন

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

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