Мне нужно реализовать HashTable в C++. Я думал об использовании Array. Но я точно не знаю, как создать массив фиксированного размера. Допустим, что мой класс называется HT. В конструкторе я хочу указать размер массива, но я не знаю, как это сделать. У меня размер size_type членов; и string [] t; в заголовке HT. Как я могу определить размер t от конструктора?
HT(size_type s):size(s) {
}
Если невозможно, какую структуру данных я должен использовать для реализации хеш-таблицы?
Вы можете сделать как std :: array и сделать размер параметром времени компиляции.
Если нет, то нет смысла пытаться избежать std :: vector, так как вы будете делать динамическое размещение независимо от того, что.
Итак, пока вы могли
struct HT
{
HT(size_t size) : _size(size), _data(new std::string[size]) {}
private:
size_t const _size;
std::unique_ptr<std::string[]> _data;
};
Это только делает ваш класс более сложным, менее гибким и, как правило, менее элегантным, поэтому я бы пошел с вектором:
#include <memory>
using namespace std;
struct HT
{
HT(size_t size) : _size(size), _data(new std::string[size]) {}
private:
size_t const _size;
std::unique_ptr<std::string[]> _data;
};
#include <vector>
struct HT2
{
HT2(size_t size) : _data(size) {}
private:
std::vector<std::string> _data;
};
int main()
{
HT table1(31);
HT2 table2(31);
}
В конструкторе для HT
класса передайте (или по умолчанию 0) переменную (s
) размера, чтобы указать размер массива. Затем установите t
в новый массив строк размера s
Итак, что-то вроде:
HT::HT(size_type s)
{
t = new string[s];
}
Большинство предложений, похоже, предполагают, что он реализует ваш контейнерный класс хеш-таблицы с точки зрения стандартной библиотеки. Интересно, какова ваша ситуация; как это получилось, эта "необходимость" для реализации примитивного класса контейнера? Это действительно здорово, если вы зависите от другой библиотеки?
Однако все остальные думают так. Я думаю, std действительно является фундаментальным компонентом языка C++, теперь...
Глядя на другие ответы, я вижу std :: vector, std :: string, std :: unique_pointer...
Но дорога не заканчивается. Даже не близко.
#include <unordered_map>
#include <string>
#include <iostream>
template <typename T>
class CHashTable {
typedef std::string KEYTYPE;
struct HASH_FUNCTOR {
size_t operator ()(const KEYTYPE& key) const {
return CHashTable::MyAmazingHashFunc(key);
} };
typename std::unordered_map<KEYTYPE, T, HASH_FUNCTOR> m_um;
public:
static size_t MyAmazingHashFunc(const KEYTYPE& key) {
size_t h = key.length();
for(auto c : key) {
h = h*143401 + static_cast<size_t>(c)*214517 + 13;
}
h = (~h << (sizeof(h)*4)) + (h >> (sizeof(h)*4));
return h;
}
template <typename KT>
T& operator [] (const KT& key) {
return m_um[KEYTYPE(key)];
}
template <typename KT>
const T& operator [] (const KT& key) const {
return m_um.at(KEYTYPE(key));
}
void DeleteAll() {
m_um.clear();
}
template <typename KT>
void Delete(const KT& key) {
m_um.erase(KEYTYPE(key));
}
template <typename KT>
bool Exists(const KT& key) const {
const auto fit = m_um.find(KEYTYPE(key));
return fit != m_um.end();
}
};
int main() {
CHashTable<int> ht;
// my Universal Translator, a "WIP"
ht["uno"] = 1;
ht["un"] = 1;
ht["one"] = 1;
ht["dos"] = 2;
ht["deux"] = 2;
ht["two"] = 2;
const char* key = "deux";
int value = ht[key];
std::cout << '[' << key << "] => " << value << std::endl;
key = "un";
bool exists = ht.Exists(key);
std::cout << '[' << key << "] "
<< (exists ? "exists" : "does not exist") << std::endl;
key = "trois";
exists = ht.Exists(key);
std::cout << '[' << key << "] "
<< (exists ? "exists" : "does not exist") << std::endl;
return 0;
}
main():
[deux] => 2
[un] exists
[trois] does not exist
И это даже не конец Hash Table std :: Highway! Конец является резким, в классе, который просто наследуется от std :: unordered_map. Но я бы никогда не предложил ЭТО в ответе, потому что я не хочу встречаться с саркастическим смартфоном.
std::array
. Если размер не известен до времени выполнения, вы можете использоватьstd::vector
.