Cormen预订后的HashSearch和HashInsert函数实现

时间:2016-03-30 06:02:10

标签: c++ algorithm sorting

对于我的算法,我需要另一个名为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;
  }

2 个答案:

答案 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;        
}