如何正确使用哨兵节点?

How to properly use sentinel nodes?

会有多个(密切)相关的问题,而不是一个。为了我们的舒适,我会相应地给它们编号。

基于this Wikipedia article, this question和讲座,我想我已经理解了哨兵节点背后的思想及其在链表中的用法。但是,看了这些资料,还是有一些不明白的地方。

我得到了双向链表的基本实现(它只存储 int 值),任务是更改实现,以便它使用这样的哨兵节点:

Illustrative image(还不允许嵌入图片,抱歉)

问题 1

我假设列表的 head 变量将指向第一个真实节点(哨兵节点之后的节点),而 tail 变量将简单地指向最后一个节点。我是正确的还是 head 应该指向哨兵节点?我在这里要求最佳实践或最标准的方法。

问题 2

我知道在列表中搜索值时,我不再需要检查 nullptr,因为我使用的是哨兵节点。由于哨兵节点,列表基本上形成了一个圆圈,我必须在遍历整个列表并到达它后终止它。我可以通过将我要查找的值放在哨兵节点中并将其用作排序的哨兵值,然后在循环结束时检查是否从哨兵节点返回结果来做到这一点吗?一些消息来源声称哨兵节点根本不应该存储任何值。我的方法 correct/reasonably 有效吗?

问题 3

当只是简单地迭代而不是搜索特定值时(例如,计算节点数,将整个列表输出到控制台),我是否必须像检查 nullptr 一样检查哨兵节点(以终止迭代循环)或者是否有不同或更聪明的方法来做到这一点?

答案 1

是的,这是哨兵节点可以采取的有效立场。 headtail可以指向数据的实际开始和结束。但是您的 adddelete 函数将需要知道由于哨兵节点

在列表边界处引起的偏差

答案 2

是的,这是一种有效的搜索策略,实际上称为 Elephant in Cairo 技术

答案 3

是的,哨兵节点的作用就是让你知道它是哨兵节点。你可以只维护一个指向这个哨兵节点的常量指针(或者你选择的任何语言支持)来检查你是否在哨兵节点或者只是在节点中粘贴一个标志。