web-dev-qa-db-ja.com

2つのキューを使用してスタックを実装する

同様の質問が以前に尋ねられました there ですが、ここでの質問はその逆で、2つのキューをスタックとして使用しています。質問...

標準操作(enqueuedequeueisemptysize)の2つのキューが与えられた場合、標準操作(popPushisemptysize)。

ソリューションのtwoバージョンがあるはずです。

  • バージョンA:スタックは、アイテムをプッシュするときに効率的でなければなりません。そして
  • バージョンB:アイテムをポップするとき、スタックは効率的でなければなりません。

特定の言語実装よりもアルゴリズムに興味があります。ただし、私がよく知っている言語で表現されたソリューションを歓迎します( Javac#pythonvb 、- javascriptphp )。

134
TechTravelThink

バージョンA(効率的なプッシュ):

  • 押す:
    • queue1のエンキュー
  • ポップ:
    • queue1のサイズが1より大きい間、キューから取り出されたアイテムをqueue1からqueue2にパイプします。
    • キューから取り出してqueue1の最後のアイテムを返し、queue1とqueue2の名前を切り替えます

バージョンB(効率的なポップ):

  • 押す:
    • queue2のエンキュー
    • queue1のすべてのアイテムをqueue2にエンキューし、queue1とqueue2の名前を切り替えます
  • ポップ:
    • queue1からの要求
190
Svante

これを行う最も簡単な(そしておそらく唯一の)方法は、新しい要素を空のキューにプッシュし、次に他の要素をデキューし、以前に空のキューに入れることです。この方法では、最新のものが常にキューの先頭にあります。これはバージョンBになります。バージョンAの場合は、最後のキューを除く2番目のキューに要素をデキューすることでプロセスを逆にできます。

ステップ0:

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

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

ステップ1:

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

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

ステップ2:

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

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

ステップ3:

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

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

1つのキューでこれを行うことができます。

押す:

  1. 新しい要素をキューに入れます。
  2. nがキュー内の要素の数である場合、要素をn-1回削除して挿入します。

ポップ:

  1. デキュー

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
+----+----+----+----+----+----+

サンプル実装:

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

1つのキューを使用してスタックを実装できますか? 2つのキューを使用できますが、単一のキューを検討する方が効率的です。コードは次のとおりです。

    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

これは、平均的なケースでO(1)に対して機能する私のソリューションです。 inoutの2つのキューがあります。以下の擬似コードを参照してください。

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

ここに私の答えがあります-「ポップ」は非効率的です。すぐに思い浮かぶすべてのアルゴリズムはNの複雑さを持っているようです。Nはリストのサイズです。「ポップ」で作業するか、「プッシュ」で作業するかを選択します。

リストをトレードバックして4番目のアルゴリズムを使用すると、サイズを計算する必要がなくなるため、ループを作成して空と比較する必要があります。

キューの最後の要素に関する情報はキューのサイズを知ることによってのみ利用可能であり、その要素に到達するためにデータを破棄する必要があるため、2番目のキュー。

これを速くする唯一の方法は、そもそもキューを使用しないことです。

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

既に述べたように、1つのキューでこのトリックを行うことはないでしょうか?おそらく実用的ではありませんが、少しスリッカーです。

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

pop(x):
dequeue()
1
dhackner

以下は、PushがO(n)、pop/peekが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

S1とS2を、キューの実装で使用される2つのスタックとします。

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

1つのキューが常に空であることを確認します。

プッシュ操作:空でないキューに要素を挿入します。

  • キューQ1が空かどうかを確認します。 Q1が空の場合、その要素をキューに入れます。
  • それ以外の場合は、要素をQ1にエンキューします。

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

時間の複雑さ:O(1)

ポップ操作: n-1要素を他のキューに転送し、ポップ操作を実行するためにキューから最後に削除します。

  • キューQ1が空でない場合は、n-1個の要素をQ1からQ2に転送してから、Q1の最後の要素をデキューして返します。
  • キューQ2が空でない場合は、n-1個の要素をQ2からQ1に転送してから、Q2の最後の要素をデキューして返します。

`

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

時間の複雑さ:ポップ操作の実行時間はO(n)です。ポップが呼び出されるたびに、1つのキューから他のすべての要素を転送します。

1
Rahul Gandhi

もう1つのソリューションを次に示します。

プッシュの場合:-キュー1に最初の要素を追加します。-2番目の要素を追加する場合など、キュー2の要素を最初にキューに入れ、キュー1からキュー2にすべての要素をコピーします。 -POPの場合、最後の要素を挿入したキューから要素をデキューするだけです。

そう、

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

1つの問題があります。キューの名前を変更する方法がわかりません。

0
Vince

これは、1つのキューを使用し、スタックのような機能を提供する非常にシンプルなソリューションです。

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


}

したがって、上記の「CustomStack」というクラスでは、空のキューをチェックするだけで、空の場合は1つを挿入し、それから病棟に挿入してから挿入を削除します。この論理により、最初に最後に来ます。例:キューに1を挿入し、2を挿入しようとしています。2回目に1を削除し、再度挿入して、逆の順序になるようにします。

ありがとうございました。

0
Prityalok Raman

これはc#の完全な作業コードです:

シングルキューで実装されており、

押す:

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

ポップ:

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

1つのキューのみを使用するPythonコード

 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