web-dev-qa-db-fra.com

Implémenter une pile à l'aide de deux files d'attente

Une question similaire avait été posée plus tôt , mais la question ici est l'inverse de celle-ci, utilisant deux files d'attente comme une pile. La question...

Étant donné deux files d'attente avec leurs opérations standard (enqueue, dequeue, isempty, size), implémente une pile avec ses opérations standard (pop, Push, isempty, size).

Il devrait y avoir deux versions de la solution.

  • Version [~ # ~] a [~ # ~] : la pile doit être efficace pour pousser un élément. et
  • Version [~ # ~] b [~ # ~] : la pile devrait être efficace lors de l'éclatement d'un élément.

L'algorithme m'intéresse plus que toute implémentation de langage spécifique. Cependant, je me félicite des solutions exprimées dans des langages que je connais bien ( Java , c # , python , vb , - javascript , php ).

134
TechTravelThink

Version A (Push efficace):

  • Pousser:
    • mettre en file d'attente dans la file d'attente1
  • pop:
    • tandis que la taille de queue1 est supérieure à 1, dirige les éléments de la file d'attente de la file d'attente1 vers la file d'attente2
    • retirez la file d'attente et renvoyez le dernier élément de queue1, puis basculez les noms de queue1 et file2

Version B (pop efficace):

  • Pousser:
    • mettre en file d'attente dans la file d'attente2
    • mettre en file d'attente tous les éléments de queue1 dans queue2, puis commuter les noms de queue1 et file2
  • pop:
    • deqeue de queue1
190
Svante

La manière la plus simple (et peut-être la seule) de procéder consiste à insérer de nouveaux éléments dans la file vide, puis à retirer de la file d'attente les autres éléments et à les placer dans la file précédemment vide. De cette façon, le dernier est toujours en tête de la file d'attente. Ce serait la version B, pour la version A, il suffit d'inverser le processus en retirant les éléments de la file d'attente dans la deuxième file d'attente, à l'exception de la dernière.

Étape 0:

"Stack"
+---+---+---+---+---+
|   |   |   |   |   |
+---+---+---+---+---+

Queue A                Queue B
+---+---+---+---+---+  +---+---+---+---+---+
|   |   |   |   |   |  |   |   |   |   |   |
+---+---+---+---+---+  +---+---+---+---+---+

Étape 1:

"Stack"
+---+---+---+---+---+
| 1 |   |   |   |   |
+---+---+---+---+---+

Queue A                Queue B
+---+---+---+---+---+  +---+---+---+---+---+
| 1 |   |   |   |   |  |   |   |   |   |   |
+---+---+---+---+---+  +---+---+---+---+---+

Étape 2:

"Stack"
+---+---+---+---+---+
| 2 | 1 |   |   |   |
+---+---+---+---+---+

Queue A                Queue B
+---+---+---+---+---+  +---+---+---+---+---+
|   |   |   |   |   |  | 2 | 1 |   |   |   |
+---+---+---+---+---+  +---+---+---+---+---+

Étape 3:

"Stack"
+---+---+---+---+---+
| 3 | 2 | 1 |   |   |
+---+---+---+---+---+

Queue A                Queue B
+---+---+---+---+---+  +---+---+---+---+---+
| 3 | 2 | 1 |   |   |  |   |   |   |   |   |
+---+---+---+---+---+  +---+---+---+---+---+
68
Samuel

Nous pouvons le faire avec une file d'attente:

Pousser:

  1. mettre en file d'attente un nouvel élément.
  2. Si n est le nombre d'éléments de la file d'attente, supprimez et insérez l'élément n-1 fois.

pop:

  1. déballer

.

Push 1


front                     
+----+----+----+----+----+----+
| 1  |    |    |    |    |    |    insert 1
+----+----+----+----+----+----+


Push2

front                     
+----+----+----+----+----+----+
| 1  | 2  |    |    |    |    |    insert 2
+----+----+----+----+----+----+

     front                     
+----+----+----+----+----+----+
|    | 2  |  1 |    |    |    |    remove and insert 1
+----+----+----+----+----+----+




 insert 3


      front                     
+----+----+----+----+----+----+
|    | 2  |  1 |  3 |    |    |    insert 3
+----+----+----+----+----+----+

           front                     
+----+----+----+----+----+----+
|    |    |  1 |  3 |  2 |    |    remove and insert 2
+----+----+----+----+----+----+

                front                     
+----+----+----+----+----+----+
|    |    |    |  3 |  2 |  1 |    remove and insert 1
+----+----+----+----+----+----+

Exemple de mise en œuvre:

int stack_pop (queue_data *q)
{
  return queue_remove (q);
}

void stack_Push (queue_data *q, int val)
{
  int old_count = queue_get_element_count (q), i;

  queue_insert (q, val);
  for (i=0; i<old_count; i++)
  {
    queue_insert (q, queue_remove (q));
  }
}
50
phoxis
import Java.util.*;

/**
 *
 * @author Mahmood
 */
public class StackImplUsingQueues {

    Queue<Integer> q1 = new LinkedList<Integer>();
    Queue<Integer> q2 = new LinkedList<Integer>();

    public int pop() {
        if (q1.peek() == null) {
            System.out.println("The stack is empty, nothing to return");
            int i = 0;
            return i;
        } else {
            int pop = q1.remove();
            return pop;
        }
    }

    public void Push(int data) {

        if (q1.peek() == null) {
            q1.add(data);
        } else {
            for (int i = q1.size(); i > 0; i--) {
                q2.add(q1.remove());
            }
            q1.add(data);
            for (int j = q2.size(); j > 0; j--) {
                q1.add(q2.remove());
            }

        }
    }

    public static void main(String[] args) {
        StackImplUsingQueues s1 = new StackImplUsingQueues();
        //       Stack s1 = new Stack();
        s1.Push(1);
        s1.Push(2);
        s1.Push(3);
        s1.Push(4);
        s1.Push(5);
        s1.Push(6);
        s1.Push(7);
        s1.Push(8);
        s1.Push(9);
        s1.Push(10);
        // s1.Push(6);
        System.out.println("1st = " + s1.pop());
        System.out.println("2nd = " + s1.pop());
        System.out.println("3rd = " + s1.pop());
        System.out.println("4th = " + s1.pop());
        System.out.println("5th = " + s1.pop());
        System.out.println("6th = " + s1.pop());
        System.out.println("7th = " + s1.pop());
        System.out.println("8th = " + s1.pop());
        System.out.println("9th = " + s1.pop());
        System.out.println("10th= " + s1.pop());
    }
}
9
Mahmood Akhtar

Pouvons-nous utiliser une seule file d'attente pour implémenter une pile? Je peux utiliser deux files d'attente, mais considérer une seule file d'attente serait plus efficace. Voici le code:

    public void Push(T val)
    {
        queLower.Enqueue(val);
    }

    public  T Pop()
    {

        if (queLower.Count == 0 )
        {
            Console.Write("Stack is empty!");
            return default(T);

         }
        if (queLower.Count > 0)
        {
            for (int i = 0; i < queLower.Count - 1;i++ )
            {
                queLower.Enqueue(queLower.Dequeue ());
           }
                    }

        return queLower.Dequeue();

    }
4
Min Zhou
queue<int> q1, q2;
int i = 0;

void Push(int v) {
  if( q1.empty() && q2.empty() ) {
     q1.Push(v);
     i = 0;
  }
  else {
     if( i == 0 ) {
        while( !q1.empty() ) q2.Push(q1.pop());
        q1.Push(v);
        i = 1-i;
     }
     else {
        while( !q2.empty() ) q1.Push(q2.pop());
        q2.Push(v);
        i = 1-i;
     }
  }
}

int pop() {
   if( q1.empty() && q2.empty() ) return -1;
   if( i == 1 ) {
      if( !q1.empty() )
           return q1.pop();
      else if( !q2.empty() )
           return q2.pop();
   }
   else {
      if( !q2.empty() )
           return q2.pop();
      else if( !q1.empty() )
           return q1.pop();
   }
}
3
hiddenboy

Voici ma solution qui fonctionne pour O(1) en moyenne. Il y a deux files d'attente: in et out. Voir le pseudo-code ci-dessous:

Push(X) = in.enqueue(X)

POP: X =
  if (out.isEmpty and !in.isEmpty)
    DUMP(in, out)
  return out.dequeue

DUMP(A, B) =
  if (!A.isEmpty)
    x = A.dequeue()
    DUMP(A, B)
    B.enqueue(x)
2
Vladimir Kostyukov

Voici ma réponse - où le "pop" est inefficace. Il semble que tous les algorithmes qui nous viennent immédiatement à l’esprit aient une complexité de N, où N est la taille de la liste: que vous choisissiez de travailler sur le "pop" ou de travailler sur le "push"

L'algorithme où les listes sont échangées et les quatrièmes peut être meilleur, car un calcul de taille n'est pas nécessaire, bien que vous ayez toujours besoin de boucler et de comparer avec des vides.

vous pouvez prouver que cet algorithme ne peut pas être écrit plus vite que N en notant que les informations sur le dernier élément d'une file d'attente sont uniquement disponibles en connaissant la taille de la file d'attente et que vous devez détruire les données pour accéder à cet élément, d'où la 2e file d'attente .

La seule façon de rendre cela plus rapide est de ne pas utiliser les files d'attente en premier lieu.

from data_structures import queue

class stack(object):
    def __init__(self):
        q1= queue 
        q2= queue #only contains one item at most. a temp var. (bad?)

    def Push(self, item):
        q1.enque(item) #just stick it in the first queue.

    #Pop is inefficient
    def pop(self):
        #'spin' the queues until q1 is ready to pop the right value. 
        for N 0 to self.size-1
            q2.enqueue(q1.dequeue)
            q1.enqueue(q2.dequeue)
        return q1.dequeue()

    @property
    def size(self):
        return q1.size + q2.size

    @property
    def isempty(self):
        if self.size > 0:
           return True
        else
           return False
2
FlipMcF

Comme on l'a mentionné, une seule file d'attente ne suffirait-elle pas? C'est probablement moins pratique, mais c'est un peu plus glissant.

Push(x):
enqueue(x)
for(queueSize - 1)
   enqueue(dequeue())

pop(x):
dequeue()
1
dhackner

Voici un pseudo-code simple, Push is O (n), pop/peek is O (1):

Qpush = Qinstance()
Qpop = Qinstance()

def stack.Push(item):
    Qpush.add(item)
    while Qpop.peek() != null: //transfer Qpop into Qpush
        Qpush.add(Qpop.remove()) 
    swap = Qpush
    Qpush = Qpop
    Qpop = swap

def stack.pop():
    return Qpop.remove()

def stack.peek():
    return Qpop.peek()
1
dansalmo
Q1 = [10, 15, 20, 25, 30]
Q2 = []

exp:
{   
    dequeue n-1 element from Q1 and enqueue into Q2: Q2 == [10, 15, 20, 25]

    now Q1 dequeue gives "30" that inserted last and working as stack
}

swap Q1 and Q2 then GOTO exp
1
Ankur Lathiya
import Java.util.LinkedList;
import Java.util.Queue;

class MyStack {
    Queue<Integer> queue1 = new LinkedList<Integer>();
    Queue<Integer> queue2 = new LinkedList<Integer>();

    // Push element x onto stack.
    public void Push(int x) {
        if(isEmpty()){
            queue1.offer(x);
        }else{
            if(queue1.size()>0){
                queue2.offer(x);
                int size = queue1.size();
                while(size>0){
                    queue2.offer(queue1.poll());
                    size--;
                }
            }else if(queue2.size()>0){
                queue1.offer(x);
                int size = queue2.size();
                while(size>0){
                    queue1.offer(queue2.poll());
                    size--;
                }
            }
        }
    }

    // Removes the element on top of the stack.
    public void pop() {
        if(queue1.size()>0){
            queue1.poll();
        }else if(queue2.size()>0){
            queue2.poll();
        }
    }

    // Get the top element. You can make it more perfect just example
    public int top() {
       if(queue1.size()>0){
            return queue1.peek();
        }else if(queue2.size()>0){
            return queue2.peek();
        }
        return 0;
    }

    // Return whether the stack is empty.
    public boolean isEmpty() {
        return queue1.isEmpty() && queue2.isEmpty();
    }
}
1

Soit S1 et S2 les deux piles à utiliser pour la mise en oeuvre des files d'attente.

struct Stack 
{ struct Queue *Q1;
  struct Queue *Q2;
}

Nous veillons à ce qu'une file d'attente soit toujours vide.

Opération Push: Quelle que soit la file d'attente qui n'est pas vide, insérez l'élément dans celle-ci.

  • Vérifiez si la file d'attente Q1 est vide ou non. Si Q1 est vide, mettez ensuite l'élément en file d'attente.
  • Sinon, EnQueue l'élément en Q1.

Push (struct Stack *S, int data) { if(isEmptyQueue(S->Q1) EnQueue(S->Q2, data); else EnQueue(S->Q1, data); }

Complexité temporelle: O (1)

Opération Pop: Transférez n-1 éléments vers une autre file d'attente et supprimez-les en dernier pour effectuer une opération pop.

  • Si la file d'attente Q1 n'est pas vide, transférez n-1 éléments de Q1 à Q2 puis, DeQueue, retournez le dernier élément de Q1.
  • Si la file d'attente Q2 n'est pas vide, transférez n-1 éléments de Q2 à Q1 puis, DeQueue, le dernier élément de Q2 et retournez-le.

`

int Pop(struct Stack *S){
int i, size;
if(IsEmptyQueue(S->Q2)) 
{
size=size(S->Q1);
i=0;
while(i<size-1)
{ EnQueue(S->Q2, Dequeue(S->Q1)) ;
  i++;
}
return DeQueue(S->Q1);  
}
else{
size=size(S->Q2);
while(i<size-1)
EnQueue(S->Q1, Dequeue(S->Q2)) ;
i++;
}
return DeQueue(S->Q2);
} }

Complexité temporelle: la durée d'exécution de l'opération pop est O(n)) à chaque fois que pop est appelée, nous transférons tous les éléments d'une file d'attente à une autre.

1
Rahul Gandhi

Voici une autre solution:

pour Push: -Ajouter le premier élément de la file 1. -Lorsque vous ajoutez un deuxième élément, etc., commencez par mettre en file d'attente l'élément de la file 2, puis copiez tous les éléments de la file 1 dans la file2. -Pour POP simplement retirer l'élément de la file d'attente depuis que vous avez inséré le dernier élément.

Alors,

public void Push(int data){
if (queue1.isEmpty()){
    queue1.enqueue(data);
}  else {
queue2.enqueue(data);
while(!queue1.isEmpty())
Queue2.enqueue(queue1.dequeue());
//EXCHANGE THE NAMES OF QUEUE 1 and QUEUE2

}}

public int pop(){
int popItem=queue2.dequeue();
return popItem;
}'

Il y a un problème, je ne suis pas capable de comprendre, comment renommer les files d'attente ???

0
Vince

Voici une solution très simple qui utilise une file d’attente et offre des fonctionnalités telles que Stack.

public class CustomStack<T>
{
    Queue<T> que = new Queue<T>();

    public void Push(T t) // STACK = LIFO / QUEUE = FIFO
    {

        if( que.Count == 0)
        {
            que.Enqueue(t);
        }
        else
        {
            que.Enqueue(t);
            for (int i = 0; i < que.Count-1; i++)
            {
                var data = que.Dequeue();

                que.Enqueue(data);
            }
        }

    }

    public void pop()
    {

        Console.WriteLine("\nStack Implementation:");
        foreach (var item in que)
        {
            Console.Write("\n" + item.ToString() + "\t");
        }

        var data = que.Dequeue();
        Console.Write("\n Dequeing :" + data);
    }

    public void top()
    {

        Console.Write("\n Top :" + que.Peek());
    }


}

Donc, dans la classe ci-dessus nommée "CustomStack", je vérifie simplement si la file est vide, si elle est vide, insérez-en une, puis insérez-la et supprimez-la. Par cette logique, le premier viendra en dernier. Exemple: Dans la file d'attente, j'ai inséré 1 et j'essaie maintenant d'insérer 2. Une deuxième fois, supprimez 1 et réinsérez-la pour qu'elle devienne dans l'ordre inverse.

Je vous remercie.

0
Prityalok Raman

voici le code de travail complet en c #:

Il a été mis en œuvre avec Single Queue,

Pousser:

1. add new element.
2. Remove elements from Queue (totalsize-1) times and add back to the Queue

pop:

normal remove





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

    namespace StackImplimentationUsingQueue
    {
        class Program
        {
            public class Node
            {
                public int data;
                public Node link;
            }
            public class Queue
            {
                public Node rear;
                public Node front;
                public int size = 0;
                public void EnQueue(int data)
                {
                    Node n = new Node();
                    n.data = data;
                    n.link = null;
                    if (rear == null)
                        front = rear = n;
                    else
                    {
                        rear.link = n;
                        rear = n;
                    }
                    size++;
                    Display();
                }
                public Node DeQueue()
                {
                    Node temp = new Node();
                    if (front == null)
                        Console.WriteLine("Empty");
                    else
                    {
                        temp = front;
                        front = front.link;
                        size--;
                    }
                    Display();
                    return temp;
                }
                public void Display()
                {
                    if (size == 0)
                        Console.WriteLine("Empty");
                    else
                    {
                        Console.Clear();
                        Node n = front;
                        while (n != null)
                        {
                            Console.WriteLine(n.data);
                            n = n.link;
                        }
                    }
                }
            }
            public class Stack
            {
                public Queue q;
                public int size = 0;
                public Node top;
                public Stack()
                {
                    q = new Queue();
                }
                public void Push(int data)
                {
                    Node n = new Node();
                    n.data = data;
                    q.EnQueue(data);
                    size++;
                    int counter = size;
                    while (counter > 1)
                    {
                        q.EnQueue(q.DeQueue().data);
                        counter--;
                    }
                }
                public void Pop()
                {
                    q.DeQueue();
                    size--;
                }
            }
            static void Main(string[] args)
            {
                Stack s= new Stack();
                for (int i = 1; i <= 3; i++)
                    s.Push(i);
                for (int i = 1; i < 3; i++)
                    s.Pop();
                Console.ReadKey();
            }
        }
    }
0
Jaydeep Shil
#include <bits/stdc++.h>
using namespace std;
queue<int>Q;
stack<int>Stk;
void PRINT(stack<int>ss , queue<int>qq) {
    while( ss.size() ) {
        cout << ss.top() << " " ;
        ss.pop();
    }
    puts("");
    while( qq.size() ) {
        cout << qq.front() << " " ;
        qq.pop();
    }
    puts("\n----------------------------------");
}
void POP() {
    queue<int>Tmp ;
    while( Q.size() > 1 ) {
        Tmp.Push( Q.front()  );
        Q.pop();
    }
    cout << Q.front() << " " << Stk.top() << endl;
    Q.pop() , Stk.pop() ;
    Q = Tmp ;
}
void Push(int x ) {
    Q.Push(x);
    Stk.Push(x);
}
int main() {
    while( true ) {
        string typ ;
        cin >> typ ;
        if( typ == "Push" ) {
            int x ;
            cin >> x;
            Push(x);
        } else POP();
        PRINT(Stk,Q);
    }
}
0
Rezwan4029

Code Python utilisant une seule file d'attente

 class Queue(object):
    def __init__(self):
        self.items=[]
    def enqueue(self,item):
        self.items.insert(0,item)
    def dequeue(self):
        if(not self.isEmpty()):
            return  self.items.pop()
    def isEmpty(self):
        return  self.items==[]
    def size(self):
        return len(self.items)



class stack(object):
        def __init__(self):
            self.q1= Queue()


        def Push(self, item):
            self.q1.enqueue(item) 


        def pop(self):
            c=self.q1.size()
            while(c>1):
                self.q1.enqueue(self.q1.dequeue())
                c-=1
            return self.q1.dequeue()



        def size(self):
            return self.q1.size() 


        def isempty(self):
            if self.size > 0:
               return True
            else:
               return False
0
Amol Sinha