如何找到循环列表的开头?

How to find tha't circular list's begin?

本文关键字:开头 列表 循环 何找      更新时间:2023-10-16

我正在尝试实现像 STL C++列表和列表迭代器。

列表中的节点定义如下:

struct Node{
Node *prev,*next;
value_type data;
};

我想重载运算符>并<:

bool list_iterator::operator>(const iterator_impl_base &rhs) const
bool list_iterator::operator<(const iterator_impl_base &rhs) const

这意味着如果我需要调用下一个到达 rhs.node,它将在>中返回 0,在

如果我需要调用 prev 才能到达 rhs.node,它会在>中返回 1,在

我使用循环列表实现列表。以下是列表类的一部分:

class List : public ordered_container {
protected:
Node* begin_;
Node* end_;
size_type size_;
public:
List::List() : end_(new Node){
begin_ = end_->prev = end_->next = end_;
size_=0;
}
}

所以,我不知道如何区分我是否只是通过了列表的begin_。有人可以帮助我吗?谢谢。

首先,用operator<来表示"precedes"很奇怪。我知道这是一种练习,我只是不希望你认为这是正常的。

现在,循环列表将开始和结束存储在顶级容器对象中,因此节点本身无法判断它是头部还是尾迹,或者是否发生了反转。只有容器才能知道这一点。

循环列表的通常解决方案是在头部和尾部之间有一个哨兵节点。然后sentinel.next是头部,sentinel.prev是尾巴,你需要一些方法来标记哨兵本身(data的魔法值或额外的标志(。然后,此哨兵节点可以替换容器对象中的两个指针(因此不会浪费任何空间(。

当您遍历列表时,它仍然是圆形的,但您可以判断您是否传递了您包裹的哨兵。

哨兵还有一个额外的好处,即您永远不必担心空列表中的 nullptrs。


顺便说一句,我觉得很奇怪,教师一直使用双向链表而不显示哨兵排列。在我继承的埃尔森的数据结构书的副本中,它有几页的描述,该书于1975年出版。故意教一个糟糕的双向链表有什么意义?

如果他们想让你自己弄清楚这一点,他们应该让你完成基本的列表操作,而不是这些奇怪的先行/成功运算符,因为基本操作实际上可以在没有哨兵的情况下工作,但随着它的添加而明显改进。

一个元素a小于另一个元素b您可以通过以下nextend之前到达b

一个元素a大于另一个元素biffb小于a