为什么我在 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();
}
我正在尝试从头开始在 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();
}