我正在学习一个C++数据结构类,我正在处理的问题是编写一个客户端函数,该函数可以在不使用函数原型改变队列的情况下获得队列的长度:
int GetLength(QueType queue);
在我看来,这很简单,因为当你将队列对象传递给一个函数时,它正在使用一个副本,所以如果我迭代并出列,直到它为空,我就知道队列中有多少项。
QueType是由文本提供的简单队列类型,ItemType定义为
typedef char ItemType;
我的简单驱动程序代码如下:
#include "QueType.h"
using namespace std;
int GetLength(QueType queue);
int main()
{
ItemType item; //typedef char
//initialize and fill the queue
QueType que(5);
que.Enqueue('A');
que.Enqueue('B');
que.Enqueue('C');
que.Enqueue('D');
que.Enqueue('E');
cout << "The length of the queue is " << GetLength(que) << endl;
while (!que.IsEmpty())
{
que.Dequeue(item);
cout << "Dequeue item of queue: " << item << endl;
}
system("PAUSE");
return EXIT_SUCCESS;
}
int GetLength(QueType queue)
{
int cnt = 0;
ItemType item;
while (!queue.IsEmpty())
{
queue.Dequeue(item);
cout << "Dequeue item of local copy of queue: " << item << endl;
cnt++;
}
return cnt;
}
我的预期输出是:
Dequeue item of local copy of queue: A
Dequeue item of local copy of queue: B
Dequeue item of local copy of queue: C
Dequeue item of local copy of queue: D
Dequeue item of local copy of queue: E
The length of the queue is 5
Dequeue item of queue: A
Dequeue item of queue: B
Dequeue item of queue: C
Dequeue item of queue: D
Dequeue item of queue: E
Press any key to continue . . .
但我得到了这个:
Dequeue item of local copy of queue: A
Dequeue item of local copy of queue: B
Dequeue item of local copy of queue: C
Dequeue item of local copy of queue: D
Dequeue item of local copy of queue: E
The length of the queue is 5
Dequeue item of queue: p
Dequeue item of queue: ↨
Dequeue item of queue: 7
Dequeue item of queue:
Dequeue item of queue: ─
Press any key to continue . . .
QueType.h:类FullQueue{};
class EmptyQueue
{};
typedef char ItemType;
class QueType
{
public:
QueType();
QueType(int max);
~QueType();
void MakeEmpty();
bool IsEmpty() const;
bool IsFull() const;
void Enqueue(ItemType newItem);
void Dequeue(ItemType& item);
private:
int front;
int rear;
ItemType* items;
int maxQue;
};
QueType.cpp:
#include "QueType.h"
QueType::QueType(int max)
{
maxQue = max + 1;
front = maxQue - 1;
rear = maxQue - 1;
items = new ItemType[maxQue];
}
QueType::QueType() // Default class constructor
{
maxQue = 501;
front = maxQue - 1;
rear = maxQue - 1;
items = new ItemType[maxQue];
}
QueType::~QueType() // Class destructor
{
delete [] items;
}
void QueType::MakeEmpty()
{
front = maxQue - 1;
rear = maxQue - 1;
}
bool QueType::IsEmpty() const
{
return (rear == front);
}
bool QueType::IsFull() const
{
return ((rear + 1) % maxQue == front);
}
void QueType::Enqueue(ItemType newItem)
{
if (IsFull())
throw FullQueue();
else
{
rear = (rear +1) % maxQue;
items[rear] = newItem;
}
}
void QueType::Dequeue(ItemType& item)
{
if (IsEmpty())
throw EmptyQueue();
else
{
front = (front + 1) % maxQue;
item = items[front];
}
}
代码得到了长度,但很明显队列已经被修改了。如果对象是通过引用传递的,那么队列将是空的,但事实并非如此,它只是在每个队列位置都有垃圾。有些概念我不理解。如有任何帮助,我们将不胜感激!
如何覆盖Enqueue和Dequeue函数来递增和递减计数器。。。然后你就会知道队列中有多少项目。
更好的方法是在QueType
类中实现length
或size
函数,该函数返回队列中的项数。
否则,您将需要为队列迭代器提供支持或foreach
函数。这是被动访问功能。GetLength
函数从队列中删除项目,这可能不是一件好事。换句话说,要获得队列中的项目数,需要删除队列中的项。
由于您无法更改基类,而且从其他答案和注释来看,如果不实现自己的复制构造函数,您实际上就无法进行深度复制,因此我现在能想到的客户端功能的唯一解决方法是制作另一个临时队列,当您将项目从原始队列中出列时,将其排入tmp队列,完成后,将它们再次移回原始队列。
一些伪代码:
while(!Q.empty())
tmp.enqueue(Q.dequeue())
counter++
while(!tmp.empty())
Q.enqueue(tmp.dequeue())
此解决方案将花费θ(2n*copy_cost)
,任何在不使用内部计数器的情况下实现的解决方案都将花费O(n)
,并且由于您没有任何选项可以在不删除队列元素的情况下对队列进行迭代,因此唯一的选项是将元素排入队列并对原始队列进行更改。
这里的问题是,当队列参数超出GetLength()客户端函数的范围时,会调用QueType类析构函数。
QueType::~QueType() // Class destructor
{
delete [] items;
}
这将释放包含队列内部数据的动态分配数组(项)。
您是正确的,因为GetLength()函数的队列参数是通过值传递的,所以您不需要复制队列值,因为原始变量中不会修改内部状态。
您会发现,如果您注释掉析构函数中的delete[],您的GetLength()函数将按预期工作。