[algorithm] 두 개의 대기열을 사용하여 스택 구현

비슷한 질문은 이전 질문을 받았다 , 그러나 여기에서 문제는 스택으로 두 개의 큐를 사용하여, 그것의 반대입니다. 질문…

자신의 표준 운영과 두 개의 큐를 감안할 때 ( enqueue, dequeue, isempty, size), 표준 운영과 스택을 구현 ( pop, push, isempty, size).

솔루션 에는 두 가지 버전 이 있어야합니다 .

  • 버전 A : 아이템을 밀 때 스택이 효율적이어야합니다. 과
  • 버전 B : 아이템을 쓸 때 스택이 효율적이어야합니다.

특정 언어 구현보다 알고리즘에 관심이 있습니다. 그러나 친숙한 언어로 표현 된 솔루션을 환영합니다.,,,,,).



답변

버전 A (효율적인 푸시) :

  • 푸시:
    • queue1에 넣다
  • 팝:
    • queue1의 크기가 1보다 큰 동안 큐에서 대기 한 항목을 queue1에서 queue2로 파이프
    • queue1의 마지막 항목을 대기열에서 빼고 반환 한 다음 queue1과 queue2의 이름을 전환하십시오.

버전 B (효율적인 팝) :

  • 푸시:
    • queue2에 넣다
    • queue2의 모든 queue1 항목을 대기열에 넣은 다음 queue1 및 queue2의 이름을 전환하십시오.
  • 팝:
    • queue1에서 deqeue

답변

이 작업을 수행하는 가장 쉬운 방법은 새 요소를 빈 대기열로 푸시 한 다음 다른 요소를 대기열에서 빼고 이전의 빈 대기열로 대기열에 넣는 것입니다. 이 방법으로 최신은 항상 대기열의 맨 앞에 있습니다. 이것은 버전 B입니다. 버전 A의 경우 마지막 큐를 제외하고 요소를 두 번째 큐로 큐에서 빼서 프로세스를 반대로합니다.

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


답변

하나의 대기열 로이 작업을 수행 할 수 있습니다.

푸시:

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


답변

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


답변

하나의 대기열을 사용하여 스택을 구현할 수 있습니까? 두 개의 대기열을 사용할 수 있지만 단일 대기열을 고려하는 것이 더 효율적입니다. 코드는 다음과 같습니다.

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

    }


답변

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


답변

내 대답은 ‘팝’이 비효율적 인 곳입니다. 즉시 생각 나는 모든 알고리즘에는 N 복잡성이 있습니다. 여기서 N은 목록의 크기입니다. ‘팝’에 대한 작업을 선택하든 ‘푸시’에 대한 작업을 선택하든

크기를 계산할 필요가 없기 때문에 목록을 다시 교환하고 네 번째로 교환하는 알고리즘이 더 나을 수 있습니다. 빈과 비교하고 반복해야합니다.

큐의 마지막 요소에 대한 정보는 큐의 크기를 알아야만 사용할 수 있으며 해당 요소에 도달하기 위해 데이터를 삭제해야하므로 두 번째 큐에이 알고리즘을 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