【问题标题】:Set implementation using hash table使用哈希表设置实现
【发布时间】:2020-08-30 09:10:08
【问题描述】:

我必须在 C++ 中使用散列表(开放寻址和双散列)来实现 ADT 集。 我的迭代器有问题,它没有通过下一个测试:

void testIterator() {
    cout << "Test iterator" << endl;
    Set s;
    SetIterator it = s.iterator(); //iterator on an empty set
    assert(it.valid() == false);
    try {
        it.next();
        //assert(false);
    }
    catch (exception& e) {
        assert(true);
    }
    try {
        it.getCurrent();
        //assert(false);
    }
    catch (exception& ex) {
        assert(true);
    }
    for (int i = 0; i < 100; i++) {
        s.add(33);
    }
    //printM(m);
    SetIterator it2 = s.iterator();
    assert(it2.valid() == true);
    TElem elem = it2.getCurrent();
    assert(elem == 33);
    it2.next();
    assert(it2.valid() == false);

    it2.first();
    assert(it2.valid() == true);

    Set s2;
    for (int i = -100; i < 100; i++) {
        s2.add(i);
        s2.add(i);
        s2.add(i);
    }
    //printM(m2);
    SetIterator it3 = s2.iterator();
    assert(it3.valid() == true);
    for (int i = 0; i < 200; i++) {
        //TElem e1 = im3.element();
        it3.next();
    }
    assert(it3.valid() == false);
    it3.first();
    assert(it3.valid() == true);


    Set s3;
    for (int i = 0; i < 200; i = i + 4) {
        s3.add(i);
    }
    //printM(m3);

    SetIterator it4 = s3.iterator();
    assert(it4.valid() == true);
    int count = 0;
    while (it4.valid()) {
        TElem e = it4.getCurrent();
        assert(e % 4 == 0);
        it4.next();
        count++;
    }
    try {
        it4.getCurrent();
        //assert(false);
    }
    catch (exception& ex) {
        assert(true);
    }
    try {
        it4.next();
        //assert(false);
    }
    catch (exception& ex) {
        assert(true);
    }
    assert(count == 50);
}

它不会传递评论的资产。这就是我实现这些方法的方式:

SetIterator::SetIterator(const Set& _set) : set{ _set }
{
    this->pos = 0;
    while (this->set.elems[this->pos] == INT_MIN && this->pos < this->set.m)
        this->pos++;
    this->first_pos = pos;
}

void SetIterator::first()
{
    this->pos = this->first_pos;
}

void SetIterator::next()
{
    this->pos++;

    while (this->set.elems[this->pos] == INT_MIN && this->pos < this->set.m)
        this->pos++;
}

bool SetIterator::valid() const
{
    if (this->pos < this->set.m)
        return true;

    return false;
}

TElem SetIterator::getCurrent() const
{
    return this->set.elems[this->pos];
}

有人可以帮帮我吗?我不知道为什么会这样。

【问题讨论】:

  • 与其捕捉和断言,不如不捕捉。程序将中止,您可能会收到一条很好的错误消息,告诉您抛出了什么。
  • 如果你确切地知道哪些断言失败了,你难道不知道你必须做什么吗?例如,测试期望it.next() 为空集的迭代器抛出异常。为什么你的::next() 没有?以此类推。
  • 您的代码中没有一条throw 语句,所以我不知道您为什么希望抛出任何异常。
  • 我明白了。所以我必须检查它是否有效,如果不抛出异常
  • @AndreiGabor - 没错。你在我回答之前几秒钟,你明白了:-)

标签: c++ algorithm data-structures iterator set


【解决方案1】:

让我们确保您首先了解 try-catch。

try {
    // some code
    assert(false);
}
catch (exception& e) {
    assert(true);
}

这是一种说法,“我预计某些代码会因抛出异常而失败。”因此,如果它没有抛出异常,我们通过断言 false 来标记它。如果它确实抛出异常,我们会捕获它,这样我们的程序就不会崩溃,然后断言 true 并继续。

我们以第一个测试为例。

给定一个空集的迭代器 it,测试期望 it.next() 抛出异常。但是,正如您发现的那样,它没有。

首先,让我们弄清楚您的代码应该在哪里引发异常。嗯,很明显,这里:

void SetIterator::next()
{
    this->pos++;

    while (this->set.elems[this->pos] == INT_MIN && this->pos < this->set.m)
        this->pos++;
}

但是我们怎么知道迭代器是为空集构建的呢? 会怎么做呢?我不知道this-&gt;set.m 指的是什么,因为我没有您的其余代码,但假设它表示您的集合中的项目数。那么这个为零就意味着它是一个空集,对吧?那么这个怎么样:

void SetIterator::next()
{
    if (this->s.m == 0) throw std::runtime_err;

    this->pos++;

    while (this->set.elems[this->pos] == INT_MIN && this->pos < this->set.m)
        this->pos++;
}

我并不是说这是最好的解决方案。事实上,它不是。但是,在解决其余问题时,可以从不是最好的解决方案开始,最终事情会“点击”,您会发现更好的解决方案。

【讨论】:

    猜你喜欢
    • 2014-10-18
    • 2012-10-30
    • 2020-12-30
    • 1970-01-01
    • 2016-03-25
    • 2011-10-14
    • 2011-09-15
    • 2014-02-13
    相关资源
    最近更新 更多