【问题标题】:create a Set template class using the Standard C++ Library vector as an underlying implementation使用标准 C++ 库向量作为底层实现创建一个 Set 模板类
【发布时间】:2015-09-01 05:50:17
【问题描述】:

我刚刚阅读了有关模板和迭代器的一章,但这仍然很难理解。基本上我想创建一个 Set 模板类,它只接受你放入其中的每种类型的对象中的一种,使用向量实现。

问题是,我不知道Set类中的insert函数怎么写,嵌套迭代器类中的构造函数怎么写。另外,我提供的大部分功能都是文中章节中的示例,我什至不知道它们是否必要或者我做得对。注释?因为这是一个非常混乱的问题。这是我的代码:

//testSetClass.cpp

#include <iostream>
#include <vector>
using namespace std;

/****************************CLASS DEFINITION*********************************/

// -----------------------------------------
 //         SET
 // -----------------------------------------
template <class T>
class Set
{
    vector<T> theSet;
public:
    Set() {}
    Set(const Set& s): theSet(s.theSet){} //copy constructor
    ~Set(){ theSet.clear(); }

    void insert(T t) 
    {
        //insert in orderly fashion? as set class does too
        //also, how do i check for duplicates?
        theSet.push_back(t);
    }

    //nested iterator class: that supports the begin() and end() sentinel
    class iterator; //declaration
    friend class iterator;
    class iterator //definition
    {
        Set<T>& s;
        int index;
    public:
        iterator(const Set<T>& ss): s(ss), index(0){}
        //to create the "end sentinel" operator:
        iterator(Set<T>& ss,bool):s(ss){} //???

        T operator*() {return s.theSet.at(index);} //is this right?

        T operator++() //prefix form
        {
            return ++s.theSet.at(index);
        }
        T operator++(int) //postfix form
        {
            return s.theSet.at(index)++;
        }
        bool operator!=(const iterator& ri)const {return index!=ri.index;}
    };

    //iterators begin() and end()
    iterator begin()const { return iterator (*this); }
    //create the end sentinel:
    iterator end() { return iterator (*this,true); } //why?
};


/*************************************END OF CLASS DEFINITIONS*********************************/


/* *****************************************************************************
 *  MAIN 
 * *****************************************************************************
 *  
 *  REMARKS:
 *     to test that the class works correctly.
 * *****************************************************************************/

int main (int argv, char const *argc[])
{
    Set<int> other;


    for(int i = 0; i<10; ++i)
        other.insert(i);

    for(Set<int>::iterator start = other.begin(); start != other.end(); start++)
        cout<<*start<<endl;

    cout << "\n\nProgram ends successfully!" <<endl;
}

【问题讨论】:

  • 您是否尝试使用 std::vector 来实现 std::set 规范作为教育练习?
  • 一旦你完成它,你可以从代码审查codereview.stackexchange.com的人们那里得到很好的反馈

标签: c++ templates generics iterator set


【解决方案1】:

使用std::vector&lt;T&gt;::iterator 作为您的迭代器。与您的const_iterator 类似。

要查找,请使用std::equal_range。如果first==second,则返回end()。

插入,查找。如果它已经存在,请停止。如果它不存在,请插入它。插入它的懒惰方法是推回,然后排序。先偷懒。

完成上述操作后,您就有了一个有效的Set&lt;T&gt;。使用一堆数据针对std::set&lt;T&gt; 进行测试。编写一堆单元测试以确保 Set&lt;T&gt; 在重复、排序、查找等方面与 std::set&lt;T&gt; 一样工作。


现在让您的Set&lt;T&gt; 更有效率。将Find 替换为对lower_bound 和&lt; 的调用,并将元素插入它应该在的位置,而不是插入然后排序。 (没关系,这对您来说毫无意义;在阅读本文之前先获得一个有效的Set,然后花一些时间打开它。

或者,创建一个惰性排序Set&lt;T&gt;,它会盲目追加,并且在插入时很少以指数方式排序。在读取时,它要么进行排序,要么使用二分搜索检查已排序的部分,并使用线性搜索检查剩余的(小)部分。或者类似的。

另一个改进是像上面一样写一个手册iterator;不像std::vector 迭代器那样容易失效。这......很难做到正确。

但是在你有正确性之后再提高效率。

【讨论】:

    【解决方案2】:

    //还有,我如何检查重复项?

    theSet.find()....

    iterator(Set& ss,bool):s(ss){} //???

    那是行不通的。许多选项,最简单的方法是将index 设置为s.theSet.size(),这样现有的!= 就可以工作了。

    T operator*() {return s.theSet.at(index);} //这样对吗?

    不...您需要将 T&amp; 返回到 - 而不是 vector 元素的副本。

    运算符++ / 运算符++(int)

    您需要增加迭代器(即index),而不是增加迭代器地址,并且应该返回*this(返回类型为iterator&amp;)。研究一些迭代器的实现......

    迭代器 end() { 返回迭代器 (*this,true); } //为什么?

    为什么?无论如何,您最好提供begin() 和end() 的const 版本,它们返回const_iterators(这很像iterator,但只公开const T&amp;),以及非@987654336 @ 返回iterators 的版本:您将这两个想法与iterator begin() const 混合在一起。

    【讨论】:

      猜你喜欢
      • 2011-07-08
      • 1970-01-01
      • 2015-11-13
      • 2015-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多