Triển khai Stack bằng cách sử dụng hai hàng đợi


142

Một câu hỏi tương tự đã được hỏi trước đó , nhưng câu hỏi ở đây là mặt trái của nó, sử dụng hai hàng đợi như một chồng. Câu hỏi...

Với hai hàng đợi với các hoạt động tiêu chuẩn ( enqueue, dequeue, isempty, size), thực hiện một chồng với các hoạt động tiêu chuẩn của nó ( pop, push, isempty, size).

Nên có hai phiên bản của giải pháp.

  • Phiên bản A : Ngăn xếp phải hiệu quả khi đẩy một vật phẩm; và
  • Phiên bản B : Ngăn xếp phải hiệu quả khi xuất hiện một mục.

Tôi quan tâm đến thuật toán hơn bất kỳ triển khai ngôn ngữ cụ thể nào. Tuy nhiên, tôi hoan nghênh các giải pháp được thể hiện bằng các ngôn ngữ mà tôi quen thuộc (,,,,,).


6
Chắc chắn là như vậy! CLRS - 10,1-6 ( tinyurl.com/clrs-ex-10-1-6 )
rampion

1
Một ngăn xếp, hai hàng đợi đưa ra một giải pháp tao nhã trong đó Pophoạt động trong $ O (1) $ và Pushhoạt động trong thời gian khấu hao $ O (\ sqrt {n}) $.
hengxin

1
@rampion Bây giờ CLRS của nó - 10.1-7. :)
nsane

Bài liên quan. Đây là một vấn đề thú vị khác để thực hiện ngăn xếp chỉ sử dụng một hàng đợi ở đây .
RBT

Câu trả lời:


194

Phiên bản A (đẩy hiệu quả):

  • đẩy:
    • enqueue trong queue1
  • bật:
    • trong khi kích thước của queue1 lớn hơn 1, các mục đã loại bỏ các ống từ queue1 vào queue2
    • dequeue và trả về mục cuối cùng của queue1, sau đó chuyển tên của queue1 và queue2

Phiên bản B (pop hiệu quả):

  • đẩy:
    • enqueue trong queue2
    • enqueue tất cả các mục của queue1 trong queue2, sau đó chuyển đổi tên của queue1 và queue2
  • bật:
    • deqeue từ queue1

4
Phiên bản B dường như có vấn đề: bạn có nghĩa là enqueue tất cả các mục của queue2 thành queue1 ngoại trừ phần tử cuối cùng (sau đó chuyển tên của q1 và q2)?
Icerman

Nhận xét của Icerman có ý nghĩa với tôi. Phiên bản B của câu trả lời cần chỉnh sửa. Tôi không có quyền chỉnh sửa. Ai đó có thể xin vui lòng chỉnh sửa câu trả lời này?
eeerahul

2
@eeerahul: Tôi đã kiểm tra lại và câu trả lời là đúng. Tại thời điểm Icerman dường như muốn thu hút tất cả các mục của queue2 vào queue1, queue2 chỉ bao gồm các mục mới, vì vậy nhận xét không có ý nghĩa.
Svante

Phiên bản A có đúng không? đẩy 1, đẩy 2, đẩy 3, đẩy 4. pop 4. đẩy 5, đẩy 6, đẩy 7, đẩy 8. pop 8. pop 7. Có vẻ như thuật toán đó sẽ xuất hiện 3 thay vì 7. Thuật toán của bạn có vẻ đúng cái nhìn đầu tiên bởi vì chúng ta có thể có thể lý do như: về cơ bản, bạn sẽ luôn xuất hiện phần tử bị mê hoặc cuối cùng trong Hàng đợi 1. Nhưng đó là phần tử được đẩy cuối cùng chỉ khi bạn đã xếp hàng trước đó. Nếu bạn xuất hiện nhiều lần liên tiếp, điều đó không cần phải đúng.
127.0.0.1

1
@ user127.0.0.1: Có vẻ như bạn đã quên chuyển đổi hàng đợi ở cuối mỗi cửa sổ bật lên. Có một bất biến là sau mỗi lần đẩy và mỗi lần bật, tất cả các mục đều nằm trong hàng1, trong khi queue2 trống.
Svante

68

Cách dễ nhất (và có thể duy nhất) để thực hiện việc này là bằng cách đẩy các phần tử mới vào hàng đợi trống, sau đó loại bỏ phần tử kia và đưa vào hàng đợi trống trước đó. Với cách này, mới nhất luôn luôn ở phía trước của hàng đợi. Đây sẽ là phiên bản B, đối với phiên bản A, bạn chỉ cần đảo ngược quá trình bằng cách sắp xếp các phần tử vào hàng đợi thứ hai ngoại trừ hàng cuối cùng.

Bước 0:

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

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

Bước 1:

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

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

Bước 2:

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

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

Bước 3:

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

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

1
Logic cho điều này không có ý nghĩa gì. Chuyển từ Bước 2 sang Bước 3. Khi tôi "đẩy" 3, làm cách nào tôi có thể loại bỏ các yếu tố trong Hàng đợi B theo cách mà tôi nhận được 3 2 1 trong Hàng đợi A? Nếu tôi dequeue B để enqueue A, tôi chỉ có thể nhận các phần tử theo thứ tự 2, 1. Nếu sau đó tôi thêm 3, tôi sẽ nhận được thứ tự 3, 1, 2. Nếu đặt lực đẩy của mình lên trước, và sau đó là dequeue / enqueue, tôi nhận được 1, 2, 3.
tsurantino

Tại sao không làm cho hoạt động deque đắt hơn làm cho hoạt động enqueue đắt tiền?
Divij Sehgal

49

Chúng tôi có thể làm điều này với một hàng đợi:

đẩy:

  1. enqueue yếu tố mới.
  2. Nếu nlà số phần tử trong hàng đợi, sau đó loại bỏ và chèn n-1thời gian phần tử .

bật:

  1. dequeue

.

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

Mẫu thực hiện:

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

Bất cứ ai có thể giải thích đăng nhập đằng sau phương pháp đẩy trong mã ở trên? Theo như tôi hiểu, vòng lặp for đầu tiên sẽ loại bỏ tất cả các phần tử vào q2 cho đến khi q1 còn một phần tử. Xin hãy sửa tôi nếu tôi sai.
John

4

Chúng ta có thể chỉ sử dụng một hàng đợi để thực hiện một ngăn xếp không? Tôi có thể sử dụng hai hàng đợi, nhưng xem xét hàng đợi đơn sẽ hiệu quả hơn. Đây là mã:

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

    }

Tôi đoán trong phương thức pop, điều kiện vòng lặp for phải là i <queLower.Count - 2 khi bạn khởi tạo biến i bằng 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

Đây là câu trả lời của tôi - nơi 'pop' không hiệu quả. Có vẻ như tất cả các thuật toán xuất hiện ngay lập tức đều có độ phức tạp N, trong đó N là kích thước của danh sách: cho dù bạn chọn thực hiện công việc trên 'pop' hay thực hiện công việc trên 'đẩy'

Thuật toán nơi danh sách được giao dịch trở lại và thứ tư có thể tốt hơn, vì không cần tính toán kích thước, mặc dù bạn vẫn cần lặp và so sánh với sản phẩm nào.

bạn có thể chứng minh thuật toán này không thể được viết nhanh hơn N bằng cách lưu ý rằng thông tin về phần tử cuối cùng trong hàng đợi chỉ có sẵn thông qua việc biết kích thước của hàng đợi và bạn phải hủy dữ liệu để đến phần tử đó, do đó hàng đợi thứ 2 .

Cách duy nhất để làm điều này nhanh hơn là không sử dụng hàng đợi ở nơi đầu tiên.

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

Đây là giải pháp của tôi hoạt động cho O (1) trong trường hợp trung bình. Có hai hàng đợi: inout. Xem mã giả dưới đây:

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
Ở đó bạn đang sử dụng 2 hàng đợi và 1 ngăn xếp để mô phỏng 1 ngăn xếp!
BeniBela

Bạn có nghĩa là ngăn chặn đệ quy?
Vladimir Kostyukov

1

Như đã được đề cập, sẽ không một hàng đợi thực hiện các mẹo? Nó có thể ít thực tế hơn nhưng là một chút lấp lánh.

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

pop(x):
dequeue()

1

Đây là một số mã giả đơn giản, đẩy là O (n), pop / peek là 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

Đặt S1 và S2 là hai Ngăn xếp được sử dụng để triển khai hàng đợi.

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

Chúng tôi đảm bảo rằng một hàng đợi luôn trống.

Thao tác đẩy: Bất kỳ hàng đợi nào không trống, hãy chèn phần tử vào đó.

  • Kiểm tra xem hàng đợi Q1 có trống hay không. Nếu Q1 trống thì Enqueue phần tử trong đó.
  • Mặt khác, EnQueue phần tử vào Q1.

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

Độ phức tạp thời gian: O (1)

Hoạt động pop: Chuyển các phần tử n-1 sang hàng đợi khác và xóa lần cuối khỏi hàng đợi để thực hiện thao tác pop.

  • Nếu hàng đợi Q1 không trống thì chuyển các phần tử n-1 từ Q1 sang Q2 và sau đó, DeQueue phần tử cuối cùng của Q1 và trả về nó.
  • Nếu hàng đợi Q2 không trống thì chuyển các phần tử n-1 từ Q2 sang Q1 và sau đó, DeQueue phần tử cuối cùng của Q2 và trả về nó.

`

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

Độ phức tạp thời gian: Thời gian chạy của hoạt động pop là O (n) vì mỗi lần pop được gọi, chúng tôi sẽ chuyển tất cả các yếu tố từ một hàng đợi sang oter.


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

Đây là một giải pháp nữa:

cho PUSH: -Thêm phần tử đầu tiên vào hàng đợi 1. -Khi thêm phần tử thứ hai, v.v., Enqueue phần tử trong hàng đợi 2 trước rồi sao chép tất cả phần tử từ hàng đợi 1 sang hàng đợi2. -cho POP chỉ xử lý phần tử từ hàng đợi từ bạn đã chèn phần tử cuối cùng.

Vì thế,

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

Có một vấn đề, tôi không thể tìm ra, làm thế nào để đổi tên hàng đợi ???


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
Xin vui lòng một số từ, giải thích mã này nói về cái gì và làm thế nào điều này có thể giúp OP giải quyết vấn đề của anh ấy / cô ấy, sẽ được đánh giá cao, cùng với ví dụ về mã :-)
nIcE cOw 12/07/14

0

Mã Python chỉ sử dụng một hàng đợi

 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
Hãy cố gắng tránh chỉ bỏ một mã như một câu trả lời và cố gắng giải thích nó làm gì và tại sao. Mã của bạn có thể không rõ ràng đối với những người không có kinh nghiệm mã hóa có liên quan.
Frits

0

đây là mã làm việc hoàn chỉnh trong c #:

Nó đã được thực hiện với Hàng đợi đơn,

đẩy:

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

bật:

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

Bạn có muốn nhận xét về thời gian (dự kiến ​​/ khấu hao) mà việc triển khai của bạn yêu cầu như là một chức năng của các yếu tố hiện được giữ / tổng số lần đẩy & bật không?
greybeard

0

Đây là giải pháp rất đơn giản sử dụng một Hàng đợi và cung cấp chức năng như 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());
    }


}

Vì vậy, trong lớp trên có tên "CustomStack", những gì tôi đang làm chỉ là kiểm tra hàng đợi cho trống, nếu trống thì chèn một và sau đó vào phường chèn rồi xóa chèn. Theo logic này đầu tiên sẽ đến cuối cùng. Ví dụ: Trong hàng đợi tôi đã chèn 1 và hiện đang cố gắng chèn 2. Lần thứ hai xóa 1 và một lần nữa chèn để nó trở thành thứ tự ngược lại.

Cảm ơn bạn.


0

Dưới đây là một giải pháp Java rất đơn giản hỗ trợ hoạt động đẩy hiệu quả.

Thuật toán -

  1. Khai báo hai hàng đợi q1 và q2.

  2. Thao tác đẩy - Phần tử Enqueue để xếp hàng q1.

  3. Hoạt động pop - Đảm bảo rằng hàng đợi q2 không trống. Nếu nó trống, thì dequeue tất cả các phần tử từ q1 ngoại trừ phần tử cuối cùng và liệt kê nó thành q2 từng cái một. Dequeue phần tử cuối cùng từ q1 và lưu nó dưới dạng phần tử popped. Hoán đổi hàng đợi q1 và q2. Trả về phần tử popped được lưu trữ.

  4. Thao tác Peek - Đảm bảo rằng hàng đợi q2 không trống. Nếu nó trống, thì dequeue tất cả các phần tử từ q1 ngoại trừ phần tử cuối cùng và liệt kê nó thành q2 từng cái một. Dequeue phần tử cuối cùng từ q1 và lưu nó dưới dạng phần tử nhìn trộm. Enqueue nó trở lại hàng đợi q2 và trao đổi hàng đợi q1 và q2. Trả về phần tử nhìn trộm được lưu trữ.

Dưới đây là mã cho thuật toán trên -

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

Đây là giải pháp của tôi ..

Concept_Behind :: push(struct Stack* S,int data):: Hàm này liệt kê phần tử đầu tiên trong Q1 và phần còn lại trong Q2 pop(struct Stack* S) :: nếu Q2 không trống, chuyển tất cả elem vào Q1 và trả lại elem cuối cùng trong Q2 khác (có nghĩa là Q2 trống) chuyển tất cả elem vào Q2 và trả lại elem cuối cùng trong Q1

Effic_Behind :: push(struct Stack*S,int data):: O (1) // kể từ khi enqueue cho mỗi dữ liệu pop(struct Stack* S):: O (n) // kể từ khi chuyển dữ liệu n-1 tệ nhất trên mỗi 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;
        }
    }
}

Một danh sách liên kết Java có chức năng như một deque tốt. Câu trả lời này không có ý nghĩa.
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;
}

Một bức tường mã mà không có ý kiến ​​hoặc giải thích là một câu trả lời kém.
Richard
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.