2017-10-28 102 views
6

好的,所以这是我得到的一个面试问题,并且只在当时表现平平。我想知道最佳解决方案是什么以及如何最好地实施。如何在几个已排序的列表上创建一个迭代器?

给你多个排序列表,构造东西,它允许我们遍历从最小元素到最大元素的所有这些列表。

例子:

{ -2, 5, 10} 
{ 2, 9, 11} 
{ -5, 9} 


-> -5, -2, 2, 5, 9, 9, 10, 11 

更新:

随着从SO聊天#C-问题 - 和 - 答案和@Nican特别是一些帮助,我收到了此船以某种方式飞行。我已经发布了我的工作代码作为允许其他解决方案的答案。

我在下面发布的答案仍然很混乱,尤其是我没有正确实现==和!=。我仍然需要帮助。

理由为这个问题

寻找干净,简约定制迭代器实现在线是并不常见。我相信这个问题可能成为其他人加强对迭代器和最佳实践的理解的良好起点。

+0

不太确定你的意思是*“执行end()来检查底层的哪一端是最大的。”*我看不出这对你有什么帮助。只要'end()'返回一个带有标识符的迭代器对象,该标识符告诉你你在序列的末尾。然后确保你的'=='运算符处理它。对于前向迭代器编写'++',赋值运算符等等,然后重构一个'const_iterator'。 – MFisherKDX

回答

0

这不是一个完整的答案

我已经实现了一个部分的解决方案,它的作品的地步。这与input_iterator的要求并不完全一致,也不正确。这说明了这一点,剩下的工作由谁来决定。

-

我只是从我的笔记和努力昨天就捡起一次。我从Nican得到了一些很好的帮助。

我正在使用堆来保存我的结构中的列表。 (其中有对我重新创建priority_queue的有效批评)。有几件事情仍然缺少在这里,除其他事项外:

  • 复制构造
  • 后修复++运算符
  • 正确的==和=的实现,我只是比较大小!
  • 这可能很容易成为forward_iterator。

我已经到了建立我对迭代器的理解的地步。这就是我将要采取这一次。

#include <algorithm> 
#include <forward_list> 
#include <iostream> 
#include <iterator> 
#include <string> 
#include <vector> 

template <typename Iter> 
struct SortedListIterItem { 
    Iter it_beg; 
    Iter it_end; 
    /* Used by the heap to sort ascending */ 
    bool operator<(const SortedListIterItem<Iter>& other) { 
    return *it_beg > *other.it_beg; 
    } 
    bool operator==(const SortedListIterItem<Iter>& other) { 
    return it_beg == other.it_begin && it_end == *other.it_beg; 
    } 
    SortedListIterItem<Iter>(Iter _begin, Iter _end) 
     : it_beg(_begin), it_end(_end){}; 
}; 

template <typename Iter> 
class SortedListsIter { 
    // member typedefs provided through inheriting from std::iterator 
    class iterator { 
    std::vector<SortedListIterItem<Iter> > m_items; 

    public: 
    iterator(std::vector<SortedListIterItem<Iter> > _items = {}) 
     : m_items(_items){}; 
    iterator& operator++() { 
     std::pop_heap(m_items.begin(), m_items.end()); 
     SortedListIterItem<Iter>& largest = m_items.back(); 

     if (++largest.it_beg == largest.it_end) { 
     m_items.pop_back(); 
     } else { 
     std::push_heap(m_items.begin(), m_items.end()); 
     } 
     return *this; 
    } 
    // iterator traits 
    using value_type = typename Iter::value_type; 
    using pointer = typename Iter::pointer; 
    using reference = typename Iter::reference; 
    using iterator_category = std::input_iterator_tag; 
    /** A simplified comparator, which is not a correct implementation. 
    * While it does work for regular for loops. */ 
    bool operator!=(iterator other) { 
     return (m_items.size() != other.m_items.size()); 
    } 
    value_type operator*() const { 
     return *(m_items.front().it_beg); 
    }; 
    }; 
    std::vector<SortedListIterItem<Iter> > m_items; 

public: 
    void add_list(Iter it_begin, Iter it_end) { 
    if (it_begin != it_end) { 
     m_items.push_back(SortedListIterItem<Iter>(it_begin, it_end)); 
     std::push_heap(m_items.begin(), m_items.end()); 
    } 
    // Ignore empty lists. 
    } 
    iterator begin() { return iterator(m_items); }; 
    iterator end() { 
    std::vector<SortedListIterItem<Iter> > _items; 
    return iterator(_items); 
    }; 
}; 

int main(int argc, char** argv) { 
    std::forward_list<std::string> animals = {"Cat", "Dog", "Horse"}; 
    std::forward_list<std::string> fish = {"Dolphin", "Mermaid", "Shark"}; 
    std::forward_list<std::string> birds = {"Crow", "Duck", "Eagle"}; 
    SortedListsIter<std::forward_list<std::string>::iterator> my_string_iter; 
    my_string_iter.add_list(fish.begin(), fish.end()); 
    my_string_iter.add_list(animals.begin(), animals.end()); 
    my_string_iter.add_list(birds.begin(), birds.end()); 

    for (auto i : my_string_iter) { 
    std::cout << " " << i << ","; 
    } 
    std::cout << std::endl; 
    for (auto i : my_string_iter) { 
    std::cout << " " << i << ","; 
    } 
    std::cout << std::endl; 

    std::vector<int> l4 = {1, 2, 99}; 
    std::vector<int> l5 = {-11, -4, 3}; 
    std::vector<int> l6 = {-5, 1}; 

    SortedListsIter<std::vector<int>::iterator> my_iter2; 
    my_iter2.add_list(l4.begin(), l4.end()); 
    my_iter2.add_list(l5.begin(), l5.end()); 
    my_iter2.add_list(l6.begin(), l6.end()); 

    for (auto i : my_iter2) { 
    std::cout << " " << i << ","; 
    } 
    std::cout << std::endl; 

    return 0; 
} 
+1

C++已经有了std :: priority_queue,为什么要重新创建它? –

1

我认为SortedListsIter::iterator应包含所有项目的副本,而不是引用,这样就可以ForwardIterator而不是InputIterator。你也避免在结束迭代的悬空参考(其可以是默认构造迭代器,如iterator::iterator(std::vector<SortedListIterItem<Iter> > _items = {}) : m_items(_items){};

两个堆可以在元件的顺序不同,所以我们使用std::is_permutation确定平等

bool SortedListsIter::iterator::operator==(iterator other) 
{ return std::is_permutation(m_items.begin(), m_items.end(), other.m_items.begin(), other.m_items.end()); } 

Ç ++ 11替代(即检查距离4的迭代版本是不可用的):

bool SortedListsIter::iterator::operator==(iterator other) 
{ return (std::distance(m_items.begin(), m_items.end()) == std::distance(other.m_items.begin(), other.m_items.end())) 
     && std::is_permutation(m_items.begin(), m_items.end(), other.m_items.begin()); } 

项目平等很简单:

bool SortedListIterItem::operator==(SortedListIterItem other) 
{ return (it_beg == other.it_beg) && (it_end == other.it_end); } 
相关问题