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


143

Une question similaire a déjà été posée il , mais la question est ici l'inverse de celui - ci, en utilisant deux files d' attente comme une pile. La question...

Compte tenu de deux files d' attente avec leurs opérations standard ( enqueue, dequeue, isempty, size), mettre en œuvre 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 lors de la poussée d'un élément; et
  • Version B : La pile doit être efficace lors de l'éclatement d'un élément.

Je suis plus intéressé par l'algorithme que par toute implémentation de langage spécifique. Cependant, je salue les solutions exprimées dans des langues que je connais (,,,,,).


6
Bien sûr que ça l'est! CLRS - 10.1-6 ( tinyurl.com/clrs-ex-10-1-6 )
rampion

1
One Stack, Two Queues donne une solution élégante dans laquelle Popfonctionne en $ O (1) $ et Pushfonctionne en $ O (\ sqrt {n}) $ temps amorti.
hengxin

1
@rampion Maintenant son CLRS - 10.1-7. :)
nsane

Article similaire. C'est un autre problème intéressant pour implémenter la pile en utilisant une seule file d'attente ici .
RBT

Réponses:


194

Version A (push efficace):

  • pousser:
    • mettre en file d'attente dans la file d'attente1
  • pop:
    • alors que la taille de queue1 est supérieure à 1, redirige les éléments retirés de la file d'attente de queue1 vers queue2
    • retirer et renvoyer le dernier élément de queue1, puis changer les noms de queue1 et queue2

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 changer les noms de queue1 et queue2
  • pop:
    • deqeue de queue1

4
La version B semble avoir un problème: voulez-vous dire mettre en file d'attente tous les éléments de queue2 dans queue1 sauf le dernier élément (puis changer les noms de q1 et q2)?
Icerman

Le commentaire d'Icerman a du sens pour moi. La version B de la réponse doit être modifiée. Je n'ai pas les autorisations de modification. Quelqu'un pourrait-il modifier cette réponse?
eeerahul

2
@eeerahul: Je l'ai vérifié à nouveau et la réponse est correcte. Au moment où Icerman semble vouloir mettre en file d'attente tous les éléments de queue2 dans queue1, queue2 se compose uniquement du nouvel élément, donc le commentaire n'a pas de sens.
Svante

La version A est-elle correcte? push 1, push 2, push 3, push 4. pop 4. push 5, push 6, push 7, push 8. pop 8. pop 7. On dirait que l'algorithme va sauter 3 au lieu de 7. Votre algorithme semble juste premier coup d'œil parce que nous pouvons peut-être raisonner comme suit: en gros, vous allez toujours sauter le dernier élément mis en file d'attente dans la file d'attente 1. Mais c'est le dernier élément poussé uniquement si vous avez fait la file d'attente plus tôt. Si vous avez sauté plusieurs fois de suite, cela n'a pas besoin d'être vrai.
user127.0.0.1

1
@ user127.0.0.1: Il semble que vous ayez oublié de changer les files d'attente à la fin de chaque pop. Il y a un invariant qui, après chaque push et chaque pop, tous les éléments sont dans queue1, tandis que queue2 est vide.
Svante

68

Le moyen le plus simple (et peut-être le seul) de le faire est de pousser de nouveaux éléments dans la file d'attente vide, puis de retirer l'autre de la file d'attente et de mettre en file d'attente la file d'attente 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 vous 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 |   |   |  |   |   |   |   |   |
+---+---+---+---+---+  +---+---+---+---+---+

1
La logique de cela n'a aucun sens. Passez de l'étape 2 à l'étape 3. Quand je "pousse" 3, comment puis-je retirer des éléments de la file d'attente B de manière à obtenir 3 2 1 dans la file d'attente A? Si je retire B de la file d'attente A, je ne peux obtenir que les éléments dans l'ordre 2, 1. Si j'ajoute ensuite 3, j'obtiendrai l'ordre 3, 1, 2. Si je mets mon push en premier, puis dequeue / en file d'attente, j'obtiens 1, 2, 3.
tsurantino

pourquoi ne pas rendre l'opération de deque coûteuse plutôt que rendre l'opération de mise en file d'attente coûteuse?
Divij Sehgal

49

Nous pouvons le faire avec une seule file d'attente:

pousser:

  1. mettre en file d'attente un nouvel élément.
  2. Si nest le nombre d'éléments dans la file d'attente, supprimez et insérez les n-1temps d' élément .

pop:

  1. retirer la file d'attente

.

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 d'implémentation:

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));
  }
}

9
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());
    }
}

Quelqu'un pourrait-il expliquer la connexion derrière la méthode push dans le code ci-dessus? Autant que j'ai compris, la première boucle for supprime tous les éléments de q2 jusqu'à ce que q1 ait un élément restant. S'il vous plait corrigez moi si je me trompe.
John

4

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();

    }

Je suppose que dans la méthode pop, la condition de la boucle for devrait être i <queLower.Count - 2 lorsque vous initialisez la variable i avec 0.
vignesh

3
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();
   }
}

2

Voici ma réponse - là où le «pop» est inefficace. Il semble que tous les algorithmes qui viennent immédiatement à l'esprit ont N complexité, 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 en arrière et en quatrième 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 vide.

vous pouvez prouver que cet algorithme ne peut pas être écrit plus rapidement que N en notant que les informations sur le dernier élément d'une file d'attente ne sont disponibles qu'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 2ème 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

Voici ma solution qui fonctionne pour O (1) dans le cas moyen. Il y a deux files d'attente: inet out. Voir le pseudocode 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
Là, vous utilisez 2 files d'attente et 1 pile pour simuler 1 pile!
BeniBela

Voulez-vous dire pile de récursivité implicite?
Vladimir Kostyukov

1

Comme cela a été mentionné, une seule file d'attente ne ferait-elle pas l'affaire? C'est probablement moins pratique mais un peu plus astucieux.

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

pop(x):
dequeue()

1

Voici un pseudo-code simple, push est O (n), pop / peek est 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

Soit S1 et S2 les deux piles à utiliser dans l'implémentation des files d'attente.

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

Nous nous assurons qu'une file d'attente est toujours vide.

Opération push: quelle que soit la file d'attente non vide, insérez-y l'élément.

  • Vérifiez si la file d'attente Q1 est vide ou non. Si Q1 est vide, mettez l'élément en file d'attente.
  • Sinon, EnQueue l'élément dans 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 le dernier de la file d'attente 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 le dernier élément de Q1 et retournez-le.
  • Si la file d'attente Q2 n'est pas vide, transférez n-1 éléments de Q2 à Q1 et ensuite, 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: le temps d'exécution de l'opération pop est O (n) car chaque fois que pop est appelé, nous transférons tous les éléments d'une file d'attente à l'autre.


1
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
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();
    }
}

0

Voici une autre solution:

pour PUSH: -Ajoutez le premier élément dans la file d'attente 1. -Lors de l'ajout du deuxième élément et ainsi de suite, mettez d'abord l'élément en file d'attente dans la file d'attente 2, puis copiez tout l'élément de la file d'attente 1 dans la file d'attente2. -Pour POP, retirez simplement l'élément de la file d'attente de l'insertion du 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 en mesure de comprendre, comment renommer les files d'attente ???


0
#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);
    }
}

1
Veuillez quelques mots, expliquant en quoi consiste ce code, et comment ce truc est capable d'aider l'OP à résoudre son problème, seront très appréciés, ainsi que l'exemple de code :-)
nIcE cOw

0

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

1
Essayez d'éviter de simplement jeter un code comme réponse et essayez d'expliquer ce qu'il fait et pourquoi. Votre code peut ne pas être évident pour les personnes qui n'ont pas l'expérience de codage appropriée.
Frits

0

voici le code de travail complet en c #:

Il a été implémenté 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();
            }
        }
    }

Vous souhaitez commenter le temps (attendu / amorti) requis par votre implémentation en fonction des éléments actuellement conservés / somme des push & pops?
greybeard

0

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", ce que je fais est juste de vérifier que la file d'attente est vide, si elle est vide, insérez-en une et à partir de là, insérez puis supprimez l'insertion. 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. Deuxième fois, retirez 1 et insérez à nouveau pour qu'il devienne dans l'ordre inverse.

Je vous remercie.


0

Voici une solution Java très simple qui prend en charge l'opération push de manière efficace.

Algorithme -

  1. Déclarez deux files d'attente q1 et q2.

  2. Opération push - Mettre l'élément en file d'attente dans la file d'attente q1.

  3. Opération Pop - Assurez-vous que la file d'attente q2 n'est pas vide. S'il est vide, retirez tous les éléments de q1 à l'exception du dernier élément et placez-le dans q2 un par un. Retirez le dernier élément de q1 et stockez-le comme élément popped. Permutez les files d'attente q1 et q2. Renvoie l'élément popped stocké.

  4. Opération Peek - Assurez-vous que la file d'attente q2 n'est pas vide. S'il est vide, retirez tous les éléments de q1 à l'exception du dernier élément et placez-le dans q2 un par un. Retirez le dernier élément de q1 et stockez-le comme élément examiné. Remettez-le en file d'attente dans la file d'attente q2 et échangez les files d'attente q1 et q2. Renvoie l'élément consulté stocké.

Ci-dessous le code de l'algorithme ci-dessus -

class MyStack {

    java.util.Queue<Integer> q1;
    java.util.Queue<Integer> q2;
    int SIZE = 0;

    /** Initialize your data structure here. */
    public MyStack() {
        q1 = new LinkedList<Integer>();
        q2 = new LinkedList<Integer>();

    }

    /** Push element x onto stack. */
    public void push(int x) {
        q1.add(x);
        SIZE ++;

    }

    /** Removes the element on top of the stack and returns that element. */
    public int pop() {
        ensureQ2IsNotEmpty();
        int poppedEle = q1.remove();
        SIZE--;
        swapQueues();
        return poppedEle;
    }

    /** Get the top element. */
    public int top() {
        ensureQ2IsNotEmpty();
        int peekedEle = q1.remove();
        q2.add(peekedEle);
        swapQueues();
        return peekedEle;
    }

    /** Returns whether the stack is empty. */
    public boolean empty() {
        return q1.isEmpty() && q2.isEmpty();

    }

    /** move all elements from q1 to q2 except last element */
    public void ensureQ2IsNotEmpty() {
        for(int i=0; i<SIZE-1; i++) {
            q2.add(q1.remove());
        }
    }

    /** Swap queues q1 and q2 */
    public void swapQueues() {
        Queue<Integer> temp = q1;
        q1 = q2;
        q2 = temp;
    }
}

-1

Voici ma solution ...

Concept_Behind :: push(struct Stack* S,int data):: Cette fonction met en file d'attente le premier élément de Q1 et reste dans Q2 pop(struct Stack* S):: si Q2 n'est pas vide, transfère tous les éléments dans Q1 et retourne le dernier élément de Q2 sinon (ce qui signifie que Q2 est vide) transfère tous les éléments dans Q2 et renvoie le dernier élément de Q1

Efficiency_Behind :: push(struct Stack*S,int data):: O (1) // depuis une seule mise en file d'attente par données pop(struct Stack* S):: O (n) // car transfère les pires n-1 données par pop.

#include<stdio.h>
#include<stdlib.h>
struct Queue{
    int front;
    int rear;
    int *arr;
    int size;
    };
struct Stack {
    struct Queue *Q1;
    struct Queue *Q2;
    };
struct Queue* Qconstructor(int capacity)
{
    struct Queue *Q=malloc(sizeof(struct Queue));
    Q->front=Q->rear=-1;
    Q->size=capacity;
    Q->arr=malloc(Q->size*sizeof(int));
    return Q;
    }
int isEmptyQueue(struct Queue *Q)
{
    return (Q->front==-1);
    }
int isFullQueue(struct Queue *Q)
{
    return ((Q->rear+1) % Q->size ==Q->front);
    }
void enqueue(struct Queue *Q,int data)
{
    if(isFullQueue(Q))
        {
            printf("Queue overflow\n");
            return;}
    Q->rear=Q->rear+1 % Q->size;
    Q->arr[Q->rear]=data;
    if(Q->front==-1)
        Q->front=Q->rear;
        }
int dequeue(struct Queue *Q)
{
    if(isEmptyQueue(Q)){
        printf("Queue underflow\n");
        return;
        }
    int data=Q->arr[Q->front];
    if(Q->front==Q->rear)
        Q->front=-1;
    else
    Q->front=Q->front+1 % Q->size;
    return data;
    }
///////////////////////*************main algo****************////////////////////////
struct Stack* Sconstructor(int capacity)
{
    struct Stack *S=malloc(sizeof(struct Stack));
    S->Q1=Qconstructor(capacity);
    S->Q2=Qconstructor(capacity);
    return S;
}
void push(struct Stack *S,int data)
{
    if(isEmptyQueue(S->Q1))
        enqueue(S->Q1,data);
    else
        enqueue(S->Q2,data);
    }
int pop(struct Stack *S)
{
    int i,tmp;
    if(!isEmptyQueue(S->Q2)){
        for(i=S->Q2->front;i<=S->Q2->rear;i++){
            tmp=dequeue(S->Q2);
            if(isEmptyQueue(S->Q2))
                return tmp;
            else
                enqueue(S->Q1,tmp);
                }
            }
    else{
        for(i=S->Q1->front;i<=S->Q1->rear;i++){
            tmp=dequeue(S->Q1);
            if(isEmptyQueue(S->Q1))
                return tmp;
            else
                enqueue(S->Q2,tmp);
                }
            }
        }
////////////////*************end of main algo my algo************
///////////////*************push() O(1);;;;pop() O(n);;;;*******/////
main()
{
    int size;
    printf("Enter the number of elements in the Stack(made of 2 queue's)::\n");
    scanf("%d",&size);
    struct Stack *S=Sconstructor(size);
    push(S,1);
    push(S,2);
    push(S,3);
    push(S,4);
    printf("%d\n",pop(S));
    push(S,5);
    printf("%d\n",pop(S));
    printf("%d\n",pop(S));
    printf("%d\n",pop(S));
    printf("%d\n",pop(S));
    }

-1
import java.util.LinkedList;
import java.util.Queue;


public class StackQueue {

    static Queue<Integer> Q1 = new LinkedList<Integer>();
    static Queue<Integer> Q2 = new LinkedList<Integer>();
    public static void main(String args[]) {



        push(24);
        push(34);
        push(4);
        push(10);
        push(1);
        push(43);
        push(21);
        System.out.println("Popped element is  "+pop());
        System.out.println("Popped element is  "+pop());
        System.out.println("Popped element is  "+pop());


    }

    public static void push(int data) {

        Q1.add(data);

    }

    public static int pop() {

        if(Q1.isEmpty()) {
        System.out.println("Cannot pop elements ,  Stack is Empty !!"); 
        return -1;
        }
        else
        {
        while(Q1.size() > 1) {
            Q2.add(Q1.remove());
        }
        int element = Q1.remove();
        Queue<Integer> temp = new LinkedList<Integer>();
        temp = Q1;
        Q1 = Q2;
        Q2 = temp;
        return element;
        }
    }
}

Une liste chaînée Java fonctionne comme un deque très bien. Cette réponse n'a pas de sens.
dfeuer

-1
#include "stdio.h"
#include "stdlib.h"

typedef struct {
    int *q;
    int size;
    int front;
    int rear;
} Queue;
typedef struct {
    Queue *q1;
    Queue *q2;
} Stack;

int queueIsEmpty(Queue *q) {
    if (q->front == -1 && q->rear == -1) {
        printf("\nQUEUE is EMPTY\n");
        return 1;
    }
    return 0;
}
int queueIsFull(Queue *q) {
    if (q->rear == q->size-1) {
        return 1;
    }
    return 0;
}
int queueTop(Queue *q) {
    if (queueIsEmpty(q)) {
        return -1;
    }
    return q->q[q->front];
}
int queuePop(Queue *q) {
    if (queueIsEmpty(q)) {
        return -1;
    }
    int item = q->q[q->front];
    if (q->front == q->rear) {
        q->front = q->rear = -1;
    }
    else {
        q->front++;
    }
    return item;
}
void queuePush(Queue *q, int val) {
    if (queueIsFull(q)) {
        printf("\nQUEUE is FULL\n");
        return;
    }
    if (queueIsEmpty(q)) {
        q->front++;
        q->rear++;
    } else {
        q->rear++;
    }
    q->q[q->rear] = val;
}
Queue *queueCreate(int maxSize) {
    Queue *q = (Queue*)malloc(sizeof(Queue));
    q->front = q->rear = -1;
    q->size = maxSize;
    q->q = (int*)malloc(sizeof(int)*maxSize);
    return q;
}
/* Create a stack */
void stackCreate(Stack *stack, int maxSize) {
    Stack **s = (Stack**) stack;
    *s = (Stack*)malloc(sizeof(Stack));
    (*s)->q1 = queueCreate(maxSize);
    (*s)->q2 = queueCreate(maxSize);
}

/* Push element x onto stack */
void stackPush(Stack *stack, int element) {
    Stack **s = (Stack**) stack;
    queuePush((*s)->q2, element);
    while (!queueIsEmpty((*s)->q1)) {
        int item = queuePop((*s)->q1);
        queuePush((*s)->q2, item);
    }
    Queue *tmp = (*s)->q1;
    (*s)->q1 = (*s)->q2;
    (*s)->q2 = tmp;
}

/* Removes the element on top of the stack */
void stackPop(Stack *stack) {
    Stack **s = (Stack**) stack;
    queuePop((*s)->q1);
}

/* Get the top element */
int stackTop(Stack *stack) {
    Stack **s = (Stack**) stack;
    if (!queueIsEmpty((*s)->q1)) {
      return queueTop((*s)->q1);
    }
    return -1;
}

/* Return whether the stack is empty */
bool stackEmpty(Stack *stack) {
    Stack **s = (Stack**) stack;
    if (queueIsEmpty((*s)->q1)) {
        return true;
    }
    return false;
}

/* Destroy the stack */
void stackDestroy(Stack *stack) {
    Stack **s = (Stack**) stack;
    free((*s)->q1);
    free((*s)->q2);
    free((*s));
}

int main()
{
  Stack *s = NULL;
  stackCreate((Stack*)&s, 10);
  stackPush((Stack*)&s, 44);
  //stackPop((Stack*)&s);
  printf("\n%d", stackTop((Stack*)&s));
  stackDestroy((Stack*)&s);
  return 0;
}

Un mur de code sans commentaires ni explications est une mauvaise réponse.
Richard
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.