使用哈希表设置实现

Set implementation using hash table

本文关键字:实现 设置 哈希表      更新时间:2023-10-16

我必须在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];
}

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

让我们确保您首先了解 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->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++;
}

我并不是说这是最好的解决方案。其实不然。但是,在解决其余问题的同时,从不是最好的解决方案开始是可以的,最终事情会"点击",你会实现更好的解决方案。