简体   繁体   English

为什么我在 c++ 中使用链接程序的散列给出了意外的 output?

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

I am trying to implement hashing in C++ from scratch.我正在尝试从头开始在 C++ 中实现散列。 Everything seems to be fine except the output.除了 output 之外,一切似乎都很好。 I am implementing hashing using chaining.我正在使用链接实现散列。 This style of hashing uses a linked list for handling collisions.这种散列风格使用链表来处理冲突。 I used an array of linked lists of the type HashNode which I defined inside the HashTable class.我使用了我在 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();
}

However, when I run the program, I get the following output但是,当我运行程序时,我得到以下 output

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

It would be helpful if anyone could point out the mistake.如果有人能指出错误,那将很有帮助。

One mistake is that一个错误是

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

should be应该

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

Another mistake is here另一个错误在这里

    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));
    }

This code copies the bucket and then inserts the node in the bucket copy, not in the original bucket in the array.此代码复制存储桶,然后将节点插入到存储桶副本中,而不是在数组中的原始存储桶中。 This is why your hash table stays empty even after you insert items.这就是为什么您的 hash 表即使在您插入项目后仍为空的原因。

Here's the code rewritten to avoid this这是重写的代码以避免这种情况

    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));
    }

In this code bucket is a pointer so there is no copy of the bucket made (you could acheive the same effect using a reference).在此代码中, bucket是一个指针,因此没有创建 bucket 的副本(您可以使用引用实现相同的效果)。

You have the same issue in your printing routine, you copy the buckets before printing them.您在打印程序中遇到了同样的问题,您在打印之前复制了存储桶。 This doesn't stop it working but it is inefficient and you should fix it in the same manner as above.这不会停止它的工作,但它效率低下,您应该以与上述相同的方式修复它。

Please don't literally convert Java to C++.请不要将 Java 直接转换为 C++。 C++ is a very different language. C++ 是一种非常不同的语言。 Look at this:看这个:

#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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM