为什么我在 C++ 中使用链接程序进行散列会产生意外输出?

Why my hashing using chaining program in c++ gives unexpected output?

我正在尝试从头开始在 C++ 中实现散列。除了输出,一切似乎都很好。 我正在使用链接实现散列。这种散列方式使用链表来处理冲突。我使用了我在 HashTable class.

中定义的 HashNode 类型的链表数组
#include <bits/stdc++.h>
using namespace  std;

template<class K,class V>
class HashTable{
    class HashNode{
        friend class HashTable;
    public:
        K key;
        V val;
        HashNode(K key, V val){
            this->key = key;
            this->val = val;
        }
        K getKey(){
            return this->key;
        }
        V getVal(){
            return this->val;
        }
    };

    int cap;
    list<HashNode>* ptr = new list<HashNode>[cap];
public:
    //constructor
    HashTable(int x){
        cap = x;    
    }

    //hash function
    hash<K> hashIt;
    int getHash(K k){
        return hashIt(k)%cap;
    }

    //adding pair
    void addPair(K k, V v){
        int index = getHash(k);
        bool found = false;
        auto bucket = *(ptr + index);
        for(auto x = bucket.begin();x!=bucket.end();x++){
            if((*x).key == k){
                (*x).val = v;
                found = true;
                break;
            }
        }
        if(!found){
            bucket.push_back(HashNode(k,v));
        }
    }

    //display function
    void display(){
        for(int i=0;i<cap;i++){
            cout<<"\n Bucket " + i<<" =>"<<endl;
            auto bucket  = *(ptr + i);
            for(auto x = bucket.begin();x!=bucket.end();x++ ){
                cout<<(*x).getKey()<<" : "<<(*x).getVal()<<endl;
            }
        }
    }
};
int main(){
    HashTable<string,int> H(13);
    H.addPair("IND",20);
    H.addPair("PAK",10);
    H.display();
}

然而,当我运行这个程序时,我得到以下输出

 Bucket  =>
 Bucket  =>
Bucket  =>
ucket  =>
cket  =>
ket  =>
et  =>
t  =>
  =>
 =>
 => =>
=> =>
> =>

谁能指出错误会很有帮助。

一个错误是

cout<<"\n Bucket " + i<<" =>"<<endl;

应该是

cout << "\n Bucket " << i << " =>" << endl;

这里又犯了一个错误

    auto bucket = *(ptr + index);
    for(auto x = bucket.begin();x!=bucket.end();x++){
        if((*x).key == k){
            (*x).val = v;
            found = true;
            break;
        }
    }
    if(!found){
        bucket.push_back(HashNode(k,v));
    }

此代码复制 存储桶,然后将节点插入到存储桶副本中,而不是数组中的原始存储桶中。这就是为什么您的哈希 table 即使在您插入项目后仍保持为空的原因。

这里是为避免这种情况而重写的代码

    auto bucket = ptr + index;
    for (auto x = bucket->begin(); x!=bucket->end(); ++x) {
        if (x->key == k) {
            x->val = v;
            found = true;
            break;
        }
    }
    if (!found) {
        bucket->push_back(HashNode(k, v));
    }

在此代码中,bucket 是一个指针,因此没有创建存储桶的副本(您可以使用引用实现相同的效果)。

您在打印例程中遇到了同样的问题,您在打印之前复制了桶。这不会阻止它工作,但效率低下,您应该按照与上述相同的方式修复它。

请不要直接将 Java 转换为 C++。 C++ 是一种非常不同的语言。看看这个:

#include <vector>
#include <functional>
#include <algorithm>
#include <iostream>

template<class K, class V>
class HashTable {
    struct HashNode {
        K key;
        V val;
    };

    std::vector<std::vector<HashNode>> buckets;

    //hash function
    int getBucketIdx(K const& k) const {
        return std::hash<K>{}(k) % buckets.size();
    }
public:
    //constructor
    HashTable(int cap) : buckets(cap) {}

    //adding pair
    void addPair(K const& k, V const& v) {
        auto& bucket = buckets[getBucketIdx(k)];
        auto const loc = std::find_if(begin(bucket), end(bucket),
            [&](HashNode const& hn) { return hn.key == k; });
        if (loc != end(bucket)) {
            loc->val = v;
        } else {
            bucket.emplace_back(HashNode{k, v});
        }
    }

    //display function
    void display() const {
        for(int i = 0; i < buckets.size(); ++i){
            std::cout << "Bucket " << i << " =>\n";
            for(auto const& hn : buckets[i]){
                std::cout << hn.key
                 << " : " << hn.val << '\n';
            }
        }
    }
};
int main() {
    HashTable<std::string, int> H(13);
    H.addPair("IND", 20);
    H.addPair("PAK", 10);
    H.display();
}