从一组1个元素中取出项目

时间:2016-06-08 07:33:23

标签: linked-list queue

给定具有前后指针的队列类型的单链表实现,当您从一组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)

1 个答案:

答案 0 :(得分:0)

对于正确的代码,您需要为每个操作维护数据结构不变量。编写原始代码的方式,不变量看起来像这样:

  • A1:front指向第一个元素(如果存在); NULL否则
  • A2:rear指向最后一个元素(如果存在); NULL否则

你声称不变量可以是这些:

  • B1:front指向第一个元素(如果存在); NULL否则
  • B2: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不变量在认知上更简单,因为frontrear类似地设置,没有特殊行为。 B不变量可能表现更好,但代价是复杂性。根据您的情况,任何一种选择都可能更好。

这个故事的道德:始终记录您的不变量。