如何递归地反转队列
How to reverse a queue recursively?
我有下面的类模板,我希望在不使用任何外部/附加数据结构的情况下递归地实现reverse()函数。
template <class T> struct Node {
T value; Node<T> ∗next;
};
template <class T> class Dynque
{
protected :
Node<T> ∗front;
Node<T> ∗rear;
int numItems ; public :
Dynque();
Dynque ( Dynque & ) ;
virtual ̃Dynque ( ) ;
virtual void enqueue (T) ; // add an element
T dequeue();// remove an element from front
bool isEmpty ( ) ;
int getNumItems ( ) ;
void clear (); // remove all elements
void reverse(); // reverse order of elements
};
从概念上考虑如何递归地反转队列可能会很有用。
与所有好的递归函数一样,您需要一个基本情况,而且越简单越好!这里的一个合理选择是选择空队列。扭转空队列很容易——你可以完全恢复到原来的状态。所以我们可以开始这样写这个函数:
template <typename T> void Dynque<T>::reverse() {
if (!isEmpty()) {
/* ... handle the recursive case ... */
}
}
现在我们必须考虑递归的情况。假设我们有一个非空队列,为了简单起见,让我们假设元素编号为1、2、3。。。,n、 像这样:
1 2 3 4 5 6 ... n-2 n-1 n
在处理队列时,我们只能访问前面的元素。因此,让我们想象一下,我们将这个队列分为两组:第一个元素和其他所有元素:
|
1 | 2 3 4 5 6 ... n-2 n-1 n
|
现在,看看当我们反转队列时会得到什么:
|
n n-1 n-2 ... 6 5 4 3 2 | 1
|
请注意,这里的内容与队列中除第一个元素外的所有元素相反,后面是队列的第一个元素。
这引出了一个绝妙的小见解。如果我们从队列的前面出列,我们剩下的是"其他所有东西"。如果我们反转"其他所有的东西",我们就可以将删除的元素入队,这样我们就得到了原始队列的反转。这可能是什么样子:
template <typename T> void Dynque<T>::reverse() {
if (!isEmpty()) {
T first = dequeue(); // Store the first element...
reverse(); // ... reverse everything else ...
enqueue(first); // ... and enqueue the element we removed.
}
}
看到一个没有参数的递归函数是很奇怪的,因为递归操作是通过入队和出队操作对队列状态进行更改的结果。
如果您想知道为什么这样做,请想想如果您尝试反转队列[1, 2, 3]
会发生什么。逻辑如下:
To reverse `[1, 2, 3]`, we dequeue 1, then recursively reverse `[2, 3].
To reverse `[2, 3]`, we dequeue 2, then recursively reverse `[3]`.
To reverse `[3]`, we dequeue 3, then recursively `[]`.
To reverse `[]`, we don't need to do anything!
Now we enqueue the 3 we removed to get `[3]`.
Now we enqueue the 2 we removed to get `[3, 2]`.
Now we enqueue the 1 we removed to get `[3, 2, 1]`.
需要注意的是,这不是一种非常有效的反转队列的方法。它使用大量的堆栈空间来容纳每一步移除的所有元素。您最好使用显式std::stack
对象或类似的对象来执行反转(如果您将反转作为一个自由函数来实现),或者利用可以在内部手动重新布线指针以重新排列所有内容的事实。您可以尝试对这个解决方案进行一些优化,但这样做远不如选择一个根本不同的解决方案策略更有价值。
Node reverse(Node front)
{
if(front==NULL)
return NULL;
if(front->next==null)
return front;
Node rev=reverse(front->next);
front->next->next=front;
front->next=null;
return rev;
}
它应该像反转链表一样工作。希望这能有所帮助。
应该是这样的(未测试):
void reverse() {
// Base case
if (isEmpty()) return;
// Get head
T head = dequeue();
// Reverse everything else
reverse();
// Add head after reversion of everything else
enqueue(head);
}
由于入队()和出队()都对值进行操作,因此它们会创建副本。你真的不想使用这些方法。您没有添加或删除数据,它只是四处移动,所以让我们这样做吧。
void Dynque::reverse()
{
// No effect on 0 or 1 elements' count.
if (isEmpty() || !front->next)
return;
// Remember the element at the front by keeping a pointer to it.
Node<T>* move_me_to_back = front;
// "Erase" the first element.
front = front->next;
// Call again on now shortened queue.
// In the most nested call, the queue should have only one element, with front == back.
reverse();
// "Insert" the last remembered element.
back->next = move_me_to_back;
// Update the pointer to back.
back = back->next;
}
- 通过递归进行因子分解
- 递归函数计算序列中的平方和(并输出过程)
- 使用递归的数组的最小值.这是怎么回事
- 递归列出所有目录中的C++与Python与Ruby的性能
- 递归计数给定目录的文件和所有目录
- 如何在BST的这个简单递归实现中消除警告
- C++:正在检查LinkedList中的回文-递归方法-错误
- 递归模板化函数不能分配给具有常量限定类型"const tt &"的变量"state"
- 递归无序映射
- TSP递归解的迭代形式
- 如何在Elixir中调用递归函数并行
- 返回递归调用和仅递归调用的区别
- 数组元素打印的递归方法
- 使用递归时获取变量的奇怪值
- 如何在C++中递归地按相反顺序打印集合
- 了解使用堆栈实现队列的递归调用机制
- 如何递归地反转队列
- 使用队列的非递归回溯:内存不足
- C++-用递归打乱队列
- 如何在没有递归的情况下清除四叉树(也许使用队列?).