对于我的算法,我需要另一个名为h(k, i)
的函数我认为它会搜索哈希以查看它是否为空,然后将该元素插入i
位置,但我不确定。有人能解释一下这个功能吗?谢谢。到目前为止,这是我的代码。
#include <iostream>
using namespace std;
#define hashSize 1000
typedef struct hashElem{
char* date;
char* holiday;
}hashElem;
typedef struct hash{
struct hashElem element;
struct hash* next;
}hash;
void h(hash* hashTable[hashTable],int index)
{
}
int hashInsert (hash* hashTable[hashSize],int k)
{
int index=0,index2;
do
{
index2=h(k,index);
if (hashTable[index2]== NULL) {
hashTable[index2] = k;
return index2;
}
else
index=index+1;
}
while (index == hashSize);
printf ("Hash Table Overflow");
}
int hashSearch (hash* hashTable[hashSize],int k){
int index=0,index2;
do
{
index2=h(k,index);
if (hash* hashTable[index2]==k)
return index2;
index=index+1;
}
while (hash* hashTable[index2]==NULL || index=hashSize);
return NULL;
}
int main() {
cout << "Hello, World!" << endl;
return 0;
}
答案 0 :(得分:1)
你的“h function”是一个哈希函数,它接受一个键作为输入,并在哈希表中返回键的位置。
简单的哈希函数可以是return key % tablesize
。
显然,这种简单的散列函数可能导致具有相同位置的不同键,称为“冲突”。选择合适的哈希函数并选择解决冲突的方法是一个广泛的主题。
在某些情况下,我们可以找到一个完美的哈希函数来避免冲突,这是一个更难的主题。
通常在散列函数中,我们不搜索整个散列表并找到要返回的空位置,因为我们期望散列函数需要O(1)时间。
答案 1 :(得分:0)
以下是用于一般演示目的的哈希表示例。
<强> HashMap.h 强>
#ifndef HASH_MAP_H
#define HASH_MAP_H
// ============ Hash Entry ======================
class HashEntry {
private:
int m_key;
int m_value;
public:
HashEntry( int key, int value );
int getKey() const;
int getValue() const;
}; // HashEntry
// ========== Hash Map ==========================
class HashMap {
public:
static const int TABLE_SIZE;
private:
HashEntry** m_pTable;
public:
HashMap();
~HashMap();
int get( int key ) const;
void insert( int key, int value );
}; // HashMap
#endif // HASH_MAP_H
<强> HashMap.cpp 强>
// ================ Hash Entry ==================
HashEntry::HashEntry( int key, int value ) :
m_key( key ),
m_value( value ) {
} // HashKey
int HashEntry::getKey() const {
return m_key;
} // getKey
int HashEntry::getValue() const {
return m_value;
} // getValue
// ================ Hash Map ====================
const int HashMap::TABLE_SIZE = 128;
HashMap::HashMap() {
m_pTable = new HashEntry*[TABLE_SIZE];
for ( unsigned u = 0; u < TABLE_SIZE; u++ ) {
m_pTable[u] = nullptr;
}
} // HashMap
HashMap::~HashMap() {
for ( unsigned u = 0; u < TABLE_SIZE; u++ ) {
if ( m_pTable[u] != nullptr ) {
delete m_pTable[u];
}
}
delete[] m_pTable;
} // ~HashMap
int HashMap::get( int key ) const {
int hash = ( key % TABLE_SIZE );
while ( m_pTable[hash] != nullptr && m_pTable[hash]->getKey() != key ) {
hash = (hash + 1) % TABLE_SIZE;
}
if ( m_pTable[hash] == nullptr ) {
return -1;
} else {
return m_pTable[hash]->getValue();
}
} // get
void HashMap::insert( int key, int value ) {
int hash = ( key % TABLE_SIZE );
while ( m_pTable[hash] != nullptr && m_pTable[hash]->getKey() != key ) {
hash = (hash + 1) % TABLE_SIZE;
}
if ( m_pTable[hash] != nullptr ) {
delete m_pTable[hash];
}
m_pTable[hash] = new HashEntry( key, value );
} // insert
这里正在使用:
<强>的main.cpp 强>
#include <iostream>
#include "HashMap.h"
int main() {
HashMap myHash;
myHash.insert( 1, 22 );
myHash.insert( 2, 445 );
myHash.insert( 3, 12 );
myHash.insert( 6, 24 );
myHash.insert( 4, 9 );
std::cout << "My Hash Table: " << std::endl;
std::cout << "Key: 1 - Value: " << myHash.get( 1 ) << std::endl;
std::cout << "Key: 6 - Value: " << myHash.get( 6 ) << std::endl;
std::cout << "Key: 4 - Value: " << myHash.get( 4 ) << std::endl;
return RETURN_OK;
} // main
现在你可以使用这个类并将键和值更改为适合的任何类型,但更重要的是使其可重用和通用;你可以轻松地模拟这个课程。此外,如果您使用的是现代编译器,而不是使用原始指针,则可以将它们交换为智能指针,例如std::shared_ptr<>
或std::unique_ptr<>
,这样您就不必担心内存泄漏。但是,为了更进一步,您可以在代码中执行此操作:
#include <iostream>
#include <string>
#include <unordered_map>
int main() {
// Normally all of this code within this main function would be
// a part of a class, I'm just showing a demonstration of how
// one can use std::unordered_map<> for a Hash Map.
std::string date;
std::string holiday;
typedef std::unordered_map<std::string, std::string> HashTable;
HashTable myTable;
myTable.insert( HashTable::value_type( "January 1st", "New Years Day" ) );
myTable.insert( HashTable::value_type( "July 4th", "Fourth of July" ) );
myTable.insert( HashTable::value_type( "December 25th, "Christmas" ) );
// Then To Search The Hash Table:
// Usually This would be in a class's function that returns the value
// when a specified key was passed in as a parameter.
HashTable::const_iterator it = myTable.find( "Feburary 14th" );
if ( it == myTable.cend() ) {
std::cout << "Date & Holiday not found!";
} else {
std::cout << myTable->second;
}
// As you can see this is repeat code!
// A class that would search a hash table would have
// something like this as a member function.
HashTable::const_iterator it = myTable.find( "January 1st" );
if ( it == myTable.cend() ) {
std::cout << "Date & Holiday not found!";
} else {
std::cout << myTable->second;
}
// Except for printing out the element they would return the value and
// in most cases they would return a pointer to an object, this
// way if it is not found, a nullptr is returned.
return 0;
}