我有以下类模板,我希望在不使用任何外部/附加数据结构的情况下递归地实现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
};
答案 0 :(得分:1)
从概念上考虑如何以递归方式反转队列可能会很有用。
与所有良好的递归函数一样,您需要一个基本案例,而且越简单越好!这里合理的选择是选择空队列。反转空队列很容易 - 你准确地回到了你的开始。所以我们可以开始编写这样的函数:
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
|
请注意,我们这里的内容是队列中除第一个元素之外的所有元素的反向,后跟队列的第一个元素。
这导致了一个非常小的洞察力。如果我们从队列的前面出队,我们就会留下&#34;其他所有内容。&#34;如果我们然后反转其他一切,&#34;然后我们可以将我们删除的元素排入队列,并且我们与原始队列相反。这可能是这样的:
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.
}
}
看到一个没有参数的递归函数很奇怪,因为递归操作是由于通过enqueue和dequeue操作发生的队列状态的改变而发生的。
如果您很好奇为什么会这样,请考虑一下如果您尝试撤消队列[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
对象或类似的东西进行反转(如果你将反转实现为自由函数)或者利用你可以在内部手动重新连接指针的事实重新安排一切。您可以尝试稍微优化此解决方案,但这样做比仅选择一种根本不同的解决方案策略更不值得。
答案 1 :(得分:0)
boolean
它应该像撤消链接列表一样工作。希望这会有所帮助。
答案 2 :(得分:0)
它应该是这样的(未经测试):
{{1}}
答案 3 :(得分:0)
由于enqueue()和dequeue()都对值进行操作,因此它们会创建副本。你真的不想使用这些方法。你没有添加或删除数据,它只是四处移动,所以让我们这样做。
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;
}