【问题标题】:How to implement iterator for doubly linked list?如何实现双向链表的迭代器?
【发布时间】:2020-02-09 10:30:42
【问题描述】:

我有一个自定义的双向链表类,我想为它实现迭代器,这样我就可以使用像 std::sort 这样的函数和下面提供的函数。有什么办法呢?

例如,现在我有了实现,但它很糟糕。以下字符串

std::cout << list.end() - list.begin() << std::endl;

输出

-179191768

其中 list 是我的列表类,其中包含 10 个元素。

我要工作的功能:

template <typename I, typename C>
void quickSort(I begin, I end, C cmp) {
    if (begin >= end) throw new exception_incorrectSelection;
    I i = begin, j = end;
    T pivot = *(i + (j - i) / 2);
    while (i <= j) {
        while (cmp(*i, pivot)) ++i;
        while (cmp(pivot, *j)) --j;
        if (i <= j) {
            std::iter_swap(i, j);
            ++i;
            --j;
        }
    }
    if (j > begin) quickSort(begin, j, cmp);
    if (i < end) quickSort(i, end, cmp);
}

由于前面所述的原因,它在异常检查时中断。

【问题讨论】:

  • std::sort() 需要随机访问迭代器,这与链表不太一致。为什么标准的std::list 有自己的排序方法(可能使用归并排序)
  • 那么在列表排序算法中使用索引会更好吗?
  • 最好使用使用前向或双向元素访问的算法,如归并排序。
  • 由于同样的原因,在链表上建立索引效果不佳。

标签: c++ linked-list iterator


【解决方案1】:

迭代器有多种类别。对于双向链表,您通常会实现双向迭代器。双向迭代器不支持std::sort,但会支持许多(大多数?)其他算法,例如findfind_ifaccumulate 等。

可以为支持 RandomAccessIterator 概念(例如,支持 iterator + intiterator - int)的双向链表编写迭代器,但您是否真的想要这样做还有待商榷--您通常希望随机访问迭代器提供恒定的时间加法和减法,但是对于链表,它们将是线性时间。因此,即使您在它需要支持的操作方面支持该概念,您也违反了对复杂性的要求:

RandomAccessIterator 概念通过 +=、+、-= 和 - 增加了对 恒定时间 推进的支持,以及恒定时间 中的距离计算> 带 -。随机访问迭代器还支持通过下标的数组表示法。

[强调添加]

因此,尽管您可以根据需要使其与 std::sort 一起使用,但可能这样做不是一个好主意。

这留下了两个选择:继续生成相同的接口,并接受随机访问操作将具有线性复杂性的事实,或者重写您的算法以使用双向迭代器可以提供的功能。看起来像这样:

template <typename I, typename C>
void quickSort(I begin, I end, C cmp) {
    if (begin >= end) throw new exception_incorrectSelection;
    I i = begin, j = end;
    T pivot = *(i + std::distance(i, j) / 2); // <--
    while (i <= j) {
        while (cmp(*i, pivot)) ++i;
        while (cmp(pivot, *j)) --j;
        if (i <= j) {
            std::iter_swap(i, j);
            ++i;
            --j;
        }
    }
    if (j > begin) quickSort(begin, j, cmp);
    if (i < end) quickSort(i, end, cmp);
}

至少像通常实现的那样,std::distance 会做这样的事情:

template <class Iter>
size_t distance(Iter a, Iter b) { 
    size_t ret = 0;

    while (a != b) {
       ++a;
       ++ret;
    }
    return ret;
}

...所以只要您的迭代器支持++!=,通常就足以支持std::distance

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-14
    相关资源
    最近更新 更多