【问题标题】:Can I reverse a queue without using stack?我可以在不使用堆栈的情况下反转队列吗?
【发布时间】:2017-12-14 23:42:39
【问题描述】:

我有一个带有一些数字的队列,例如 5,6,7,8 在队列中,5 是 q->front,8 是 q->rear.. 我可以在队列中反转它们但不使用堆栈吗?

【问题讨论】:

  • 使用临时变量很容易反转这些。
  • 你能稍微描述一下吗?是更好的方法还是使用堆栈更好?
  • 假设队列接口是 FIFO,您需要将队列中的元素弹出到数组、链表或堆栈中,然后以相反的顺序重新创建队列。
  • 你应该在这里放一些代码来展示你正在使用的队列类型以及它可能有什么限制。
  • 我投票结束这个,因为没有上下文它太宽泛了。这一切都取决于队列的实现方式以及一般环境的样子。

标签: algorithm stack queue reverse


【解决方案1】:

当然!但它不会那么有效。

Using a stack:              O(N) time.   O(1) memory.
Using an associative array: O(N) time.   O(1) memory.
Using a fixed-size array:   O(N) time.   O(N) memory.
Using an extendable array:  O(N) time.   O(N) memory.
Using a queue:              O(N^2) time. O(1) memory.

使用关联数组将比使用堆栈花费更多时间,但两者的性能和内存使用量将相同。

以下 sn-ps 显示了如何使用这些数据结构。

堆栈:

# O(N) time. O(1) memory.
sub reverse_queue_using_stack {
   my ($in_q) = @_;

   my $stack = Stack->new();
   while ( my ($item) = $in_q->dequeue() ) {
      $stack->push($item);
   }

   my $out_q = Queue->new();
   while ( my ($item) = $stack->pop() ) {
      $out_q->enqueue($item);
   }

   return $out_q;
}

关联数组:

# O(N) time. O(1) memory.
sub reverse_queue_using_dict {
   my ($in_q) = @_;

   my $dict = Dictionary->new();
   my $i = 0;
   while ( my ($item) = $in_q->dequeue() ) {
      $dict->set($i++, $item);
   }

   my $out_q = Queue->new();
   while ($i--) {
      $out_q->enqueue($dict->delete($i));
   }

   return $out_q;
}

固定大小的数组(如果无法获取队列的大小,则为队列):

# O(N) time. O(N) memory.
sub reverse_queue_using_array {
   my ($in_q) = @_;

   my $count = 0;
   my $queue = Queue->new();
   while ( my ($item) = $in_q->dequeue() ) {
      ++$count;
      $queue->enqueue($item);
   }

   my $array = Array->new($count);
   for my $i (0..$count-1) {
      $array->set($i, $queue->dequeue());
   }

   my $out_q = Queue->new();
   for (1..$count) {
      my $i = $count - $_;
      $out_q->enqueue($array->get($i));
   }

   return $out_q;
}

可扩展数组:

# O(N) time. O(N) memory.
sub reverse_queue_using_list {
   my ($in_q) = @_;

   my $list = List->new();
   while ( my ($item) = $in_q->dequeue() ) {
      $list->append($item);
   }

   my $count = $list->size();

   my $out_q = Queue->new();
   for (1..$count) {
      my $i = $count - $_;
      $out_q->enqueue($list->get($i));
   }

   return $out_q;
}

队列:

# O(N^2) time. O(1) memory.
sub reverse_queue_using_queue {
   my ($in_q) = @_;

   my $queue = Queue->new();
   my $out_q = Queue->new();
   while (1) {
      my ($tail) = $in_q->dequeue()
         or last;

      while ( my ($item) = $in_q->dequeue() ) {
         $queue->enqueue($tail);
         $tail = $item;
      }

      $out_q->enqueue($tail);
      ($in_q, $queue) = ($queue, $in_q);
   }

   return $out_q;
}

使用以下工具进行测试:

#!/usr/bin/perl
use strict;
use warnings;
use feature qw( say );

# The implementation of these don't matter;
# if the problem can be solved using only the methods provided by these classes,
# the problem can be solved using any implementation of these classes.

{
   package Queue;
   sub new     { my $class = shift; bless([], $class) }
   sub enqueue { my $self = shift; push @$self, @_; }
   sub dequeue { my $self = shift; @$self ? shift(@$self) : () }
}

{
   package Stack;
   sub new  { my $class = shift; bless([], $class) }
   sub push { my $self = shift; push @$self, @_; }
   sub pop  { my $self = shift; @$self ? pop(@$self) : () }
}

{
   package Array;  # Fixed-size array.
   use Carp qw( croak );
   sub new  { my ($class, $size) = @_; bless([ (undef) x $size ], $class) }
   sub size { my $self = shift; 0+@$self }
   sub get  { my ($self, $i) = @_; croak "!" if $i<0 || $i>=@$self; $self->[$i] }
   sub set  { my ($self, $i, $item) = @_; croak "!" if $i<0 || $i>=@$self; $self->[$i] = $item; }
}

{
   package List;  # Extendable array.
   use Carp qw( croak );
   sub new    { my $class = shift; bless([], $class) }
   sub size   { my $self = shift; 0+@$self }
   sub get    { my ($self, $i) = @_; croak "!" if $i<0; $self->[$i] }
   sub set    { my ($self, $i, $item) = @_; croak "!" if $i<0; $self->[$i] = $item; }
   sub append { my ($self, $item) = @_; push @$self, $item; }
}

{
   package Dictionary;
   use Carp qw( croak );
   sub new    { my $class = shift; bless({}, $class) }
   sub get    { my ($self, $k) = @_; croak "!" if !exists($self->{$k}); $self->{$k} }
   sub set    { my ($self, $k, $item) = @_; $self->{$k} = $item; }
   sub exists { my ($self, $k) = @_; exists($self->{$k}) }
   sub delete { my ($self, $k) = @_; croak "!" if !exists($self->{$k}); delete($self->{$k}) }
}


sub purge_queue {
   my ($q) = @_;

   my @vals;
   while ( my ($item) = $q->dequeue() ) {
      push @vals, $item;
   }

   return @vals;
}

# ...

for my $reverse_func_name (qw(
   reverse_queue_using_stack
   reverse_queue_using_dict
   reverse_queue_using_array
   reverse_queue_using_list
   reverse_queue_using_queue
)) {
   my $reverse_func = \&$reverse_func_name;

   my $in_q = Queue->new();
   $in_q->enqueue($_) for 'a'..'j';

   my $out_q = $reverse_func->($in_q);
   say sprintf "%-26s %s", "$reverse_func_name:", join ' ', purge_queue($out_q);
}

【讨论】:

  • 使用栈和关联数组不是 O(1) 空间复杂度
  • @csguy reverse_queue_using_stackreverse_queue_using_dict 不使用额外的内存——新结构使用的任何内存首先从队列中释放——所以它们是 O(1)。
  • (取决于QueueStackDict的实际实现,他们可以使用更多。但O(1)实现是可能的。)
【解决方案2】:

Example of How it works

你可以像这样使用三系统队列(但效率很低):

void Start()
{

    queueB.Enqueue(1);
    queueB.Enqueue(2);
    queueB.Enqueue(3);
    queueB.Enqueue(4);

    count = queueB.Count;

    for (int i = 0; i < queueB.Count; i++)
    {

        while (queueB.Count > 1)
        {
            queueC.Enqueue(queueB.Dequeue());
        }

        queueA.Enqueue(queueB.Dequeue());



        while (queueC.Count > 1)
        {
            queueB.Enqueue(queueC.Dequeue());
        }

        queueA.Enqueue(queueC.Dequeue());

    }

queueA -> 4, 3, 2, 1.

【讨论】:

    【解决方案3】:

    您可以使用递归堆栈在内部反转队列:

    #include <queue>
    
    void reverseQueue(queue<int> &q) {
        if (!q.empty()) {
            int front = q.front();
            q.pop();
            reverseQueue(q);
            q.push(front);
        }
    }
    

    source

    【讨论】:

      猜你喜欢
      • 2021-09-03
      • 1970-01-01
      • 2021-04-08
      • 1970-01-01
      • 1970-01-01
      • 2015-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多