4

あるタイプの要素で満たされたキューがあり、指定された比較子によって2つの要素が同じであると評価された場合、それらは互いに隣接するように埋められているとします。

ここで、次の方法でキューを逆にしたいと考えています。キュー内のすべての要素が一意である場合は、通常の逆の定義として逆にします。

同じ要素がいくつかある場合 (そして、それらがどのように埋められるかを考えると、それらは互いに隣接することになります)、キューを逆にしますが、一意でない要素の相対位置はそのままにします。

問題が何であるかを理解するのは、図の方が簡単かもしれません。

キューが次のような場合:

[11 22 33 44 55]

私の比較子は最初の数字を見て 2 つの整数を比較すると、上記のキューの逆は次のようになります。

[55 44 33 22 11]

ただし、入力キューが次の場合:

[11 22 23 44 55]

逆は次のようになります。

[55 44 22 23 11]

与えられた比較子。

追加の補助ストレージとしてスタックを 1 つだけ使用して、これを再帰的に実行しようとしています。しかし、正しく効果的な方法を見つけるのに苦労しています。助けていただけますか?どうもありがとうございました!

PS: 追加のストレージとしてスタックを使用する理由は、従来の方法でキューを逆にすることがスタックで最も簡単に実行できるためです (デキューしてすべてをスタックにプッシュし、次にポップしてキューにエンキューします)。

4

4 に答える 4

2

アプローチ 1)

最初にキュー全体を反転し (21、22 などの等価性を考慮せずに)、次にスタックを使用して個々のブロック (つまり 21、22 など) を反転します。これは繰り返し行うことができます。

これは、文の問題(有名なインタビューの質問)の逆の単語に似ています。

(以下の例と疑似コードを参照してください)

アプローチ 2)

絶対に再帰を行いたい場合は、スタックではなくキューを補助ストレージとして使用することをお勧めします。

ブロックを補助キューにエンキューし、リストの残りを再帰的に反転してから、要素をメイン キューにエンキューします。

コードはこのようなものになります(handwavy疑似)

StrangeReverse(Queue <T> q) {
    Queue<T> aux;
    // this removes first block from q, and places them in aux
    while (elem_of_first_block(q)) {
        aux.Enque(elem);
    }
    // Recursively reverse the rest of the q.
    StrangeReverse(q);

    // place the first block back in q, at the end.
    // in the order they appeared originally.
    while (aux.HasElements()) {
        q.Enque(aux.Deque());
    }
}

再帰的なバージョンは、キューのスタックを持つことで反復的に変換できます! 各ブロックからキューを作成し、それらを積み重ねます。次に、スタックをポップし、キューを使用します。

アプローチ 1 の具体例

[11, 12, 21, 22, 43, 44]

これを逆にします(スタックを使用するか、再帰的な方法で)

[44, 43, 22, 21, 12, 11]

次に、各ブロックを逆にします。

push 44, the 43.

Stack = [44, 43]. Queue = [22, 21, 12, 11]

スタックからポップしてエンキューする

Stack = [], Queue = [22, 21, 12, 11, 43, 44]

push 22, 21

Stack = [22, 21], Queue = [12, 11, 43, 44]

スタックをポップしてエンキューします。

Stack = [], Queue = [12, 11, 43, 44, 21, 22]

最後に、

[43, 44, 21, 22, 11, 12]

注: ブロックを特定するには、Queue の peek メソッドが必要になる場合があります。

アプローチ1の疑似コード

void StrangeReverse(Queue<T> q) {
    Stack<T> s;
    int count = q.Count();
    if (count < 2) return;
    for (i = 0; i < count; i++) {
        T elem = q.Deque();
        s.Push(elem);
    }    
    while (s.HasElements()) {
        T elem = s.Pop();
        q.Enque(elem);
    }
    // Now the queue has been reversed,
    // in the normal fashion.
    ReverseBlocks(q);
}

void ReverseBlocks(Queue<T> q) {
    int reversed = 0;
    int count = q.Count();
    while (reversed < count) {
        reversed += ReverseSingleBlock(q);
    }
}

int ReverseSingleBlock(Queue <T> q) {
    Stack <T> s;
    T prevElem = q.Deque();
    s.Push(prevElem);
    T curElem = q.Peek();
    while(curElem == prevElem) {
        s.Push(curElem);
        q.Deque();
        prevElem = curElem;
        curElem = q.Peek();
    }
    int count = 0;
    while(s.HasElements()) {
        T elem = s.Pop();
        q.Enque(elem);
        count++;
    }
    return count;
}
于 2013-03-22T08:29:01.553 に答える
0

まだ仮定:enque-> [11,21,22,23,30]-> deque / peek
は今より良くなるはずです:

first = queue.peek();
start = true;
while (queue.peek() != first || start) {
  start = false;
  el = queue.deque();
  if (el.compare(queue.peek())) {
    stack.push(el);
    while (el.compare(queue.peek())) {
      el1 = queue.dequeue();
      if (first.compare(el1)) {
        first = el1;
      }
      stack.push(el1);
    }
    while (!stack.isEmpty()) {
      queue.enque(stack.pop());       
    }
  } else {
    queue.enque(el);
  }
}
while (!queue.isEmpty()) {
  stack.push(queue.deque());
}
while (!stack.isEmpty()) {
  queue.enque(stack.pop());
}

したがって、最初にキューをローテーションし、「同等の」要素の順序を変更し、最後に通常のキューを逆にします

于 2013-03-22T04:36:09.683 に答える
0
 class ReverseQueue(object):
    def __init__(self, limit=5):
        self.rear = None
        self.front = None
        self.que = []
        self.size = 0
        self.limit = limit

   def enQueue(self, item):
        if self.size >= self.limit:
            print "Queue Overflow"
            return
        else:
            self.que.append(item)

        # two case
        # 1. if front is None then the queue is empty.
        #    so if item is added both front
        #    end point to the same position i.e 0
        # 2. if front is not None then item is added to the end of the
        #    list(append does that). we then increase the size of rear

        # note: rear is 0 indexed but size is not
        # that's why there's a diff of 1 always b/w these rear and size
        if self.front is None:
            self.rear = self.front = 0
            self.size = 1
        else:
            self.rear = self.size
            self.size += 1

        return

    def deQueue(self):
          if self.size <= 0:
              print "Queue Underflow"
              return
          else:
              temp = self.que.pop(0)

          # change the size
          self.size -= 1

          # if list is empty set both front and rear = None
          # This is in sync with the queue method
          #  where we check if front = none when adding item
          # change front and rear
          if self.size is 0:
             # if only one element
             self.rear = self.front = None
          else:
             # more then one element
             self.rear -= 1

          return temp

      def isEmpty(self):
          return self.size <= 0

      def reverse(self):
          if not self.isEmpty():
              temp = self.deQueue()
              self.reverse()
              self.enQueue(temp)

myQueue = ReverseQueue()

myQueue.enQueue("最初")

myQueue.enQueue("秒")

myQueue.enQueue("Third")

myQueue.enQueue("4番目")

myQueue.enQueue("5番目")

myQueue.que を印刷する

myQueue.reverse()

myQueue.que を印刷する

于 2016-12-13T15:56:39.333 に答える