代码之家  ›  专栏  ›  技术社区  ›  Greedy Pointer

我可以在不使用堆栈的情况下反转队列吗?

  •  3
  • Greedy Pointer  · 技术社区  · 7 年前

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

    3 回复  |  直到 7 年前
        1
  •  5
  •   ikegami Gilles Quénot    7 年前

    当然但效率不会那么高。

    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.
    

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

    下面的代码片段展示了如何使用这些数据结构中的每一个。

    堆栈:

    # 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);
    }
    
        2
  •  0
  •   Prabhsimran Singh    6 年前

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

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

    source

        3
  •  0
  •   Halbchatten    4 年前

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

    队列A->4, 3, 2, 1.