我正在为基于 Linear Hashing Algorithm 的数据结构实现Iterator。由于此数据结构使用存储桶(数组),每个存储桶可以进一步拥有自己的存储桶(也是数组),并且所有存储桶都通过动态增长的表进行结构化。
要实现begin()
方法,我只需将迭代器设置为表中的第一个元素。代码是:
const_iterator begin() const {
if(this->empty()) { return end(); } //if container is empty return end iterator
//else return the iterator to first taken element
//try only passing to the first element regardless if its full or not cause it shouldnt make a difference
bucket* next{table[0]};
element* ptr{next->Bucket};
return const_iterator{ptr, table};
}
要实现end()
方法,我的想法是在表的底部创建一个额外的数组,该数组在插入或结构中的任何操作时都不会使用,其唯一目的是充当结尾。该数组的第一个元素具有值(状态)end
,一旦达到该值,end
就会被设置为该数组的最后一个元素之后的位置。代码是:
const_iterator end() const { //should point to position behind the last element?
//find the last taken element in the table
bucket* next{table[tableSize]};
element* ptr{next->Bucket}; //cause that one is marked with end and will trigger returning the end
return const_iterator{ptr, table};
}
负责处理这些请求的迭代器类是:
template <typename Key, size_t N>
class ADS_set<Key, N>::Iterator {
private:
element* elem{nullptr}; //pointer to element for which the iterator is called
bucket** tab{nullptr}; //pointer to table
//find the bucket in which the element for which the constructor was called is in
bucket* current_bucket{nullptr};
size_type current_idx{0};
bool endFound{false};
void find_current_bucket() {
bucket* next{tab[current_idx]};
while(next != nullptr) {
for(unsigned i=0; i<N; ++i) { //loop through the bucket and its overflows
if(&(next->Bucket[i]) == elem) {
current_bucket = tab[current_idx];
return;
}
}
if(next->overflowBucket != nullptr) {
next = next->overflowBucket;
} else {
++current_idx;
if(tab[current_idx]->Bucket[0].state == State::end) {
endFound = true;
elem = &(tab[current_idx]->Bucket[N]);
return;
}
next = tab[current_idx];
}
}
}
void skip() {
//set the current bucket
find_current_bucket();
if(endFound == true) { return; }
bucket* next{current_bucket};
while(next != nullptr) {
for(unsigned i=0; i<N; ++i) {
if(&(next->Bucket[i]) == elem) {
if(elem->state == State::free) {
++elem;
} else {
return; //you found the element
//and its not a free place so nothing to skip--> return
}
} //goes through each element of bucket
} //needs to go through overflows as well
if(next->overflowBucket != nullptr) {
next = next->overflowBucket;
} else { //if there is no more overflows and element still not found it has to move to the next index in the table
++current_idx;
if(tab[current_idx]->Bucket[0].state == State::end) {
elem = &(tab[current_idx]->Bucket[N]);
//++elem;
return; //if end return
}
next = tab[current_idx];
}
}
}
public:
using value_type = Key;
using difference_type = std::ptrdiff_t;
using reference = const value_type&;
using pointer = const value_type*;
using iterator_category = std::forward_iterator_tag;
explicit Iterator(element* elem = nullptr, bucket** tab = nullptr): elem{elem}, tab{tab} {
if(elem && tab) {
skip();
}
}
reference operator*() const {
return elem->key;
}
pointer operator->() const {
return &(elem->key);
}
Iterator& operator++() {
++elem;
skip();
return *this;
}
Iterator operator++(int) { //increments the pointer but returns the old value
Iterator copy = *this;
++(*this);
return copy;
}
friend bool operator==(const Iterator &lhs, const Iterator &rhs) { return lhs.elem == rhs.elem; }
friend bool operator!=(const Iterator &lhs, const Iterator &rhs) { return lhs.elem != rhs.elem; }
};
当我使用 Valgrind 测试程序并使用指定的测试程序时,执行以下代码(从测试程序)会出现错误:
void test_iter(ads::set<val_t> const& a, std::set<val_t> const& r) {
std::cerr << "\n=== test_iter ===\n";
size_t dist = std::distance(a.begin(), a.end());
**if(dist != r.size()) {
std::cerr << RED("[iter] err: range size (distance between begin and end) is wrong.\n"
<< "expected: " << r.size() << ", but got: " << dist << "and begin is: " << *(a.begin()) << '\n');
dump_compare(a, r);
std::abort();
}**
std::vector<val_t> dump; dump.reserve(a.size());
for(auto const& v: a) {
if(!r.count(v)) {
std::cerr << RED("[iter] err: encountered unexpected value while iterating: " << v << " should not be part of container!\n");
dump_compare(a, r);
std::abort();
}
dump.push_back(v);
}
std::vector<val_t> dump_copy = dump;
std::sort(dump.begin(), dump.end(), std::less<val_t>{});
auto last = std::unique(dump.begin(), dump.end(), std::equal_to<val_t>{});
dump.erase(last, dump.end());
if(dump.size() != r.size()) {
std::cerr << RED("[iter] err: had duplicate encounters while iterating. found following elements (in this order):\n\n");
for(auto const& v: dump_copy) { std::cerr << v << ' '; }
std::cerr << '\n';
dump_compare(a, r);
std::abort();
}
ads::set<val_t>::iterator i;
for(i = a.begin(); i != a.end(); ++i) {
if(!r.count(*i)) {
std::cerr << RED("[iter] err: encountered unexpected value while iterating (default iterator constructor): "
<< *i << " should not be part of container!\n");
dump_compare(a, r);
std::abort();
}
}
}
更具体地说,当执行代码的合并部分时发生错误,并且错误消息如下(图片如下):
我真的不明白为什么会这样,因为我在我的代码或方法中没有发现逻辑上的错误,因此,我很乐意提供有关纠正错误或实现这两种方法的任何建议。