c_cpp 哈希表实现

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c_cpp 哈希表实现相关的知识,希望对你有一定的参考价值。

#include <cassert>
#include <iostream>
#include <string>

#include "HashTable.h"

void test1()
{
  struct Book {
    std::string name;
    double price;
  };

  struct Book books[] = {
    { "Data Structure", 21.45 },
    { "Introduction to Algorithm", 34.76 },
    { "Introduction to Operating System", 30.77 },
    { "Introduction to Embedded System", 25.32 },
    { "Machine Learning", 25.89 },
    { "Deep Learning", 27.99 },
    { "Introduction to Cryptography", 24.23 },
    { "Computer Architecture", 29.45 },
    { "Design Pattern", 27.88 },
    { "Introduction to Programming in C++", 28.27 },
    { "Data Science in Python", 22.76 },
    { "Software Debugging", 26.25 }
  };

  HashMap<std::string, double> prices;
  for (unsigned int i = 0 ; i < sizeof(books)/sizeof(books[0]) ; ++i) {
    assert(prices.Put(books[i].name, books[i].price));
  }

  assert(!prices.Put(books[0].name, books[0].price + 3));

  for (unsigned int i = 0 ; i < sizeof(books)/sizeof(books[0]) ; ++i) {
    double p;
    assert(prices.Get(books[i].name, p));
    std::cout << books[i].name << " : " << p << std::endl;
  }

#if DEBUG
  prices.Print();
#endif

  assert(!prices.Remove("Machine Leaning"));

  double p;
  assert(!prices.Get("Machine Leaning", p));

  unsigned int solds[] = { 4, 5, 6 };
  for (unsigned int i = 0 ; i < sizeof(solds)/sizeof(solds[0]) ; ++i) {
    unsigned int index = solds[i];
    assert(index < sizeof(books)/sizeof(books[0]));
    std::string name = books[index].name;
    std::cout << "Remove " << name << std::endl;
    assert(prices.Remove(name));
    assert(!prices.Get(name, p));
  }

#if DEBUG
  prices.Print();
#endif
}

int main()
{
  test1();
  return 0;
}
#include <cassert>    // for assert.
#include <cstdlib>    // for calloc, free.
#include <functional> // for std::hash.
#include <memory>     // for std::unique_ptr.

#define DEBUG 1 // Set 1 to log the debugging messages.
#define LOG(...) DEBUG && fprintf(stderr, __VA_ARGS__)

#if DEBUG
#include <iostream>   // for std::cout, std::endl.
#endif

const unsigned long TABLE_SIZE = 5;

template<class K, class V>
class HashMap
{
public:
  HashMap()
    : mTable(static_cast<Data**>(calloc(1, sizeof(Data*) * TABLE_SIZE)))
  {
  }

  ~HashMap()
  {
    Clear();
  }

  bool Put(const K& aKey, const V& aValue)
  {
    unsigned int index = Hash(aKey);
    assert(index < TABLE_SIZE);

    // Check the key is unique and find the position to insert.
    Data** p = &mTable[index];
    while (*p) {
      if ((*p)->mKey == aKey) {
        LOG("The key has been used!\n");
        return false; // The key is not unique!
      }
      p = &(*p)->mNext;
    }

    // Create a Data chunk and insert it into the table.
    *p = new Data(aKey, aValue);

    return true;
  }

  bool Get(const K& aKey, V& aValue)
  {
    unsigned int index = Hash(aKey);
    assert(index < TABLE_SIZE);

    Data* p = mTable[index];
    while (p) {
      if (p->mKey == aKey) {
        aValue = p->mValue;
        return true;
      }
      p = p->mNext;
    }

    LOG("The key is not in the map!\n");
    return false;
  }

  bool Remove(const K& aKey)
  {
    unsigned int index = Hash(aKey);
    assert(index < TABLE_SIZE);

    // Applying the Linus Torvalds “Good Taste” style.
    Data** p = &mTable[index];
    while (*p) {
      if ((*p)->mKey == aKey) {
        // Data* del = *p;
        // *p = (*p)->mNext;
        // delete del;
        std::unique_ptr<Data> autoRelease(*p);
        *p = (*p)->mNext;
        return true;
      }
      p = &(*p)->mNext;
    }

    LOG("The key is not in the map!\n");
    return false;
  }

#if DEBUG
  // Debugging Helper.
  void Print()
  {
    for (unsigned int i = 0 ; i < TABLE_SIZE ; ++i) {
      std::cout << i << ": ";
      Data* p = mTable[i];
      while(p) {
        std::cout << p->mKey << ", " << p->mValue << " -> ";
        p = p->mNext;
      }
      std::cout << "*" << std::endl;
      continue;
    }
  }
#endif

private:
  unsigned long Hash(const K& aKey)
  {
    // unsigned long hash = 0;
    // for (size_t i = 0 ; i < sizeof(aKey) ; ++i) {
    //   unsigned char byte = *((unsigned char *)&aKey + i);
    //   hash += byte;
    // }
    // hash %= TABLE_SIZE;
    // return hash;
    std::hash<K> hasher;
    return static_cast<unsigned long>(hasher(aKey) % TABLE_SIZE);
  }

  void Clear()
  {
    for (unsigned int i = 0 ; i < TABLE_SIZE ; ++i) {
      Data* p = mTable[i];
      while (p) {
        // Data* del = p;
        // p = p->mNext;
        // delete del;
        std::unique_ptr<Data> autoRelease(p);
        p = p->mNext;
      }
    }
  }

  typedef struct HashNode
  {
    K mKey;
    V mValue;
    struct HashNode* mNext;

    HashNode(const K aKey, const V aValue)
      : mKey(aKey)
      , mValue(aValue)
      , mNext(nullptr)
    {
    }

    ~HashNode()
    {
    }
  } Data;

  Data** mTable;
};

以上是关于c_cpp 哈希表实现的主要内容,如果未能解决你的问题,请参考以下文章

c_cpp 为字符串实现哈希表和哈希函数

c_cpp c中的快速哈希表实现。

c_cpp c的哈希表

c_cpp c中非常简单的哈希表

c_cpp C中的哈希表环境类

c_cpp 在C中的哈希表,它可以解决重复问题。