给定具有前后指针的队列类型的单链表实现,当您从一组1个元素中出列项时,是否需要将后指针设置为null?
我正在阅读Nell Dale的C ++ Plus数据结构,在第5.2章他用他的Dequeue方法写道:
if (front == NULL)
rear == NULL;
我想知道为什么这是必要的。我能想到的唯一原因是他在空集上实现Enqueue的方式:
if (rear == NULL)
front = newNode;
else
rear->next = newNode;
rear = newNode;
但是这个条件不能改为if (front == NULL)
答案 0 :(得分:0)
对于正确的代码,您需要为每个操作维护数据结构不变量。编写原始代码的方式,不变量看起来像这样:
front
指向第一个元素(如果存在); NULL
否则rear
指向最后一个元素(如果存在); NULL
否则你声称不变量可以是这些:
front
指向第一个元素(如果存在); NULL
否则rear
指向最后一个元素(如果存在)现在这些相似,但完全不相同。当列表为空时,B不变量不需要rear
的任何特定值。现在你可以使用B不变量来实现列表,当然,因为它允许在空状态和非空状态之间进行区分,这足以提供正确的实现。
但这并没有说明A或B在实践中是否更好。如果使用B不变量,则查看最后一个元素的函数不能简单地返回rear
的值,因为如果队列为空,它的值可以是任何值;你必须先测试front
值。
// for the A2 invariant
return rear ;
// for the B2 invariant
return ( front == NULL ) ? NULL : rear ;
这归结为当你出队时是否想要测试和分配,或者当你偷看最后一个元素时是否要测试。这是一个优化问题,而不是正确性问题。如果你永远不需要查看最后一个元素,你可以优化它。
所有这些都说,这是过早优化危害的主要案例。对NULL
的额外指针赋值几乎不会成为性能问题。当现有代码使用B代码时,当有人依赖A不变量时,更有可能出现问题的是在维护期间引入缺陷。 A不变量在认知上更简单,因为front
和rear
类似地设置,没有特殊行为。 B不变量可能表现更好,但代价是复杂性。根据您的情况,任何一种选择都可能更好。
这个故事的道德:始终记录您的不变量。