Data structures 您能否仅通过反转队列的头指针和尾指针来反转队列?

Data structures 您能否仅通过反转队列的头指针和尾指针来反转队列?,data-structures,queue,big-o,theory,Data Structures,Queue,Big O,Theory,在尝试反转队列时,我发现了一种普遍认可的方法: 您可以通过队列出列,获取出列值并将每个值推送到堆栈中。然后可以遍历该堆栈,弹出每个值并将其排入队列 我所说的“一致同意”,是指我在谷歌上搜索的大多数关于排队的内容最终都会把我带到那个解决方案 尽管这种方法是正确的,并且在线性时间内相对有效,但我相信有一种更好的方法更简单,在恒定时间内更有效 假设一个队列是用一个双链表实现的,难道你不能通过反转头指针和尾指针来在O(1)时间内反转它吗?如果你想把一个双链表当作一个队列来处理,那么你只需要按照惯例,用什

在尝试反转队列时,我发现了一种普遍认可的方法:

您可以通过队列出列,获取出列值并将每个值推送到堆栈中。然后可以遍历该堆栈,弹出每个值并将其排入队列

我所说的“一致同意”,是指我在谷歌上搜索的大多数关于排队的内容最终都会把我带到那个解决方案

尽管这种方法是正确的,并且在线性时间内相对有效,但我相信有一种更好的方法更简单,在恒定时间内更有效


假设一个队列是用一个双链表实现的,难道你不能通过反转头指针和尾指针来在O(1)时间内反转它吗?

如果你想把一个双链表当作一个队列来处理,那么你只需要按照惯例,用什么样的方式来迭代它,哪个是头,哪个是尾。但队列的关键是它的接口。。。。因此,对于任何以未知方式实现的任意队列(有许多东西可以实现队列,包括分布在多台计算机上的队列),问题是,如何逆转它,这意味着您不能依赖底层实现


特定的实现可能会对某些操作实施优化。

如果您想将双链接列表视为队列,那么只有按照约定,您才需要迭代它,即头和尾。但队列的关键是它的接口。。。。因此,对于任何以未知方式实现的任意队列(有许多东西可以实现队列,包括分布在多台计算机上的队列),问题是,如何逆转它,这意味着您不能依赖底层实现


特定的实现可能会对某些操作实施优化。

简短回答:

冗长的答案/理由

队列是一种抽象数据类型。这意味着这种数据结构在物理上不存在。队列可以通过多种方式实现。最基本的实现是使用数组的实现

struct Queue{
 int elements[50];//The actual/physical (array)data structure which houses the data
 int max=50;//The maximum no of elements that can be stored in this queue.
 int front,rear;//pointers to the front and rear.
};
现在,我确信您知道如何定义这种队列上的操作

void enQ(Queue &Q,int new_element);
int deQ(Queue &Q);
int getFront(Queue Q);
这意味着如果我必须将元素
7
添加到
Q
标识的队列中,我需要执行
enQ(Q,7)
。假设我通过调用
enQ
10次添加了10项类似的内容。然后我向队列中添加一个编号
89
。现在,如果我必须获得这个数字89(假设所有数字都是唯一的),我将首先必须
deQ
前10项,然后再次调用
deQ
函数以获得89。我相信你会同意的,这是排队的原则

现在是施展魔法的时候了。如果我知道89是我添加的第11个数字,我可以通过
Q.elements[(Q.front+11)%Q.max]
直接获得它。另外,如果我知道89是我刚才添加的数字,我也可以使用
Q.elements[Q.rear]
获得它

哇!这是否意味着违反了队列的原则?不,这只是意味着我不再使用队列了。我实际上是在使用一个数组,但我试图欺骗自己,用一种复杂的方式(把它放在一个结构中等等)

如果您使用的是队列,则只能使用上面提到的三种方法。您不允许干预队列的内部工作。您可能会认为您的情况有所不同,因为您只是想更改前后值,而不是实际数据。但不是。在真正的队列中,你甚至不允许进入前面和后面。您可以访问的只有我上面定义的三种方法

这就是为什么队列的实际实现应该是

class Queue{
   int elements[50];//The actual/physical (array)data structure which houses the data
   int max=50;//The maximum no of elements that can be stored in this queue.
   int front,rear;//pointers to the front and rear.

   public:

   void enQ(int new_element);
   int deQ();
   int getFront();
};
现在,我们正在维护队列的真正本质。如果使用双链接列表实现队列,则应使用类似的布局。前后指针应该是私有的,用户无法访问

因此,逆转队列的速度不可能快于O(n)

因此,底线是:如果您想通过使用双链接列表来更改队列指针,那么您可以通过各种方式进行更改。但你不能称之为倒队。因为,那么您将不会使用队列。事实上,这将是一个全新的数据结构,称为。如果您真的想以O(1)的时间复杂度实现队列反转,我建议您继续使用您的方法。但是您必须停止将其称为队列,因为这是一个DEQ(顺便说一句,使用DEQ没有什么错,无论如何,使用它)。或者,如果您不喜欢DEQ的声音,您可以定义自己的数据结构,称为可逆队列

您可以像这样定义数据结构

class ReversibleQueue{
   DLL front,rear; //pointers to a DOUBLY-LINKED-LIST

   public:

   void enQ(int new_element);
   int deQ();
   int getFront();
   void reverse();
};

简短回答:

冗长的答案/理由

队列是一种抽象数据类型。这意味着这种数据结构在物理上不存在。队列可以通过多种方式实现。最基本的实现是使用数组的实现

struct Queue{
 int elements[50];//The actual/physical (array)data structure which houses the data
 int max=50;//The maximum no of elements that can be stored in this queue.
 int front,rear;//pointers to the front and rear.
};
现在,我确信您知道如何定义这种队列上的操作

void enQ(Queue &Q,int new_element);
int deQ(Queue &Q);
int getFront(Queue Q);
这意味着如果我必须将元素
7
添加到
Q
标识的队列中,我需要执行
enQ(Q,7)
。假设我通过调用
enQ
10次添加了10项类似的内容。然后我向队列中添加一个编号
89
。现在,如果我必须获得这个数字89(假设所有数字都是唯一的),我将首先必须
deQ
前10项,然后再次调用
deQ
函数以获得89。我相信你会同意的,这是排队的原则

现在是施展魔法的时候了。如果我知道89是我添加的第11个数字,我可以通过
Q.elements[(Q.front+11)%Q.max]
直接获得它。如果我知道89是我刚才加的数字,我也可以得到