C++反向打印双链表-但我不希望它

C++ doubly linked list printing in reverse - but I don't want it to

本文关键字:希望 链表 打印 C++      更新时间:2023-10-16

我正在为一个双重链表创建一个类似STL的容器。我需要它像multiset一样,它只包含每个对象的单个实例,但保留一个计数,因此可以添加多个,但实际上只有一个被"存储"。

我目前遇到的问题是,当迭代对象的一个实例时,我得到它的元素颠倒顺序?

我一直在为这件事烦恼,似乎不知道发生了什么事…其他一切(到目前为止)都在按预期工作。

你的bug在insert:

    node *curr;
    curr = head->next; //point to first node since we're using dummy head node
    while (curr != tail && c(datum, curr->datum))
    {
        curr = curr->next;
    }

while条件应为curr != tail && c(curr->datum, datum)

这是因为插入排序应该考虑"当当前项小于我想插入的项之前的项时,跳到下一个"。键:电流,小于,插入。std::less::operator()(a,b)只做a < b。既然你想要curr->datum < datum,它应该是c(curr->datum, datum)


好了,这比预期的要长,因为你的代码:

cout << "ml Should be aceelppsu: ";

是错误的,应该是:

cout << "ml Should be aaceelppsu: ";

因为"applesauce"中有两个'a'

如何解决迭代器问题:首先认识到迭代器需要记住它当前所在的重复项中的哪一个。这意味着它需要是迭代器的成员:

class iterator
{
private:
    node *p;
    unsigned int count;
    friend class MutliLink;
    // NOT a copy ctor -- an initialize-from-ptr ctor.
    iterator(node *ptr) : p(ptr), count(0) { }
    // -- A copy ctor would be iterator(const iterator& iter);

第二,我删除了iterator默认构造函数,因为没有必要使用不指向任何对象的迭代器。在某些容器中,它们作为end迭代器可能是有意义的,但在这种情况下,end是指向虚拟tail的迭代器,因此不需要指向空值的迭代器。

这意味着唯一的公共构造函数是c++自动为您创建的默认复制构造函数。因此,新的迭代器只能从其他迭代器构造,而唯一可以自发创建迭代器的是MultiLink。这应该能捕捉到一些常见的用户错误。

接下来,我们需要修复自增和自减操作符(注意:"dec递减"中没有i)。这需要考虑count,更重要的是,自增和自减操作符需要相互兼容,因此:

iterator i = ml.begin(), j(i);
assert(--++i == j);

。这意味着我们需要解释count含义。在本例中,我将该含义定义为"count是当前元素的索引,从0开始,因此在任何时候都不应大于p->datumCount。"这会将自增前操作符更改为:

    iterator &operator++()      // preincrement
    {
        assert(p);
        if (count + 1 < p->datumCount)
        {
            // increment count and return *this
            count++;
        }
        else
        {
            // reset count and return next element
            count = 0;
            p = p->next;
        }
        return *this;
    }

可以更简洁地表示为:

    iterator &operator++()      // preincrement
    {
        assert(p);
        if (++count >= p->datumCount)
        {
            // reset count and return next element
            count = 0;
            p = p->next;
        }
        return *this;
    }

自增前操作符的变化类似:

    iterator &operator--()      // predecrement
    {
        assert(p);
        if (count-- == 0)
        {
            // reset count and return previous element
            p = p->prev;
            count = p->datumCount - 1;
        }
        return *this;
    }

后操作符不需要修改,因为它们只调用前操作符。