首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将静态哈希表转换为动态哈希表

将静态哈希表转换为动态哈希表
EN

Stack Overflow用户
提问于 2013-06-04 07:23:36
回答 2查看 489关注 0票数 0

我被指派将一个带有静态内存分配的给定哈希表更改为动态,以便在程序运行时可以分配超过限制的更多内存。我并不是要求一个问题的解决方案,我只是问是否有人知道一个好的起点,或者我需要注意代码的哪些方面,因为我对哈希表有点迷茫和困惑。我知道枚举和构造函数需要更改,但我不太确定其他方面。以下是给出的代码,并提前感谢您的建议:

代码语言:javascript
复制
#ifndef TABLE1_H
#define TABLE1_H
#include <cstdlib>    // Provides size_t
#include <cassert>  // Provides assert

namespace main_savitch_12A
{
template <class RecordType>
class table
{
public:

enum { CAPACITY = 30 }; 
    // CONSTRUCTOR
    table( );
    // MODIFICATION MEMBER FUNCTIONS
    void insert(const RecordType& entry);
    void remove(int key);
    // CONSTANT MEMBER FUNCTIONS
    bool is_present(int key) const;
    void find(int key, bool& found, RecordType& result) const;
    size_t size( ) const { return used; }
private:
    // MEMBER CONSTANTS -- These are used in the key field of special records.
    enum { NEVER_USED = -1 };
    enum { PREVIOUSLY_USED = -2 };
    // MEMBER VARIABLES
    RecordType data[CAPACITY];
    size_t used;
    // HELPER FUNCTIONS
    size_t hash(int key) const;
    size_t next_index(size_t index) const;
    void find_index(int key, bool& found, size_t& index) const;
    bool never_used(size_t index) const;
    bool is_vacant(size_t index) const;
};

    template <class RecordType>
table<RecordType>::table( )
{
    size_t i;

    used = 0;
    for (i = 0; i < CAPACITY; ++i)
        data[i].key = NEVER_USED;  // Indicates a spot that's never been used.
}

template <class RecordType>
void table<RecordType>::insert(const RecordType& entry)
// Library facilities used: cassert
{
    bool already_present;   // True if entry.key is already in the table
    size_t index;        // data[index] is location for the new entry

    assert(entry.key >= 0);

    // Set index so that data[index] is the spot to place the new entry.
    find_index(entry.key, already_present, index);

    // If the key wasn't already there, then find the location for the new entry.
    if (!already_present)
    {
        assert(size( ) < CAPACITY);
        index = hash(entry.key);
        while (!is_vacant(index))
            index = next_index(index);
        ++used;
    }

    data[index] = entry;
    size_t i;
    for (i=0; i<CAPACITY; i++) cout << data[i].key << ' ';
    cout << endl;
}

template <class RecordType>
void table<RecordType>::remove(int key)
// Library facilities used: cassert
{
    bool found;        // True if key occurs somewhere in the table
    size_t index;   // Spot where data[index].key == key

    assert(key >= 0);

    find_index(key, found, index);
    if (found)
    {   // The key was found, so remove this record and reduce used by 1.
        data[index].key = PREVIOUSLY_USED; // Indicates a spot that's no longer in use.
        --used;
    }
}

template <class RecordType>
bool table<RecordType>::is_present(int key) const
// Library facilities used: assert.h
{
    bool found;
    size_t index;

    assert(key >= 0);

    find_index(key, found, index);
    return found;
}

template <class RecordType>
void table<RecordType>::find(int key, bool& found, RecordType& result) const
// Library facilities used: cassert.h
{
    size_t index;

    assert(key >= 0);

    find_index(key, found, index);
    if (found)
        result = data[index];
}

template <class RecordType>
inline size_t table<RecordType>::hash(int key) const
{
    return (key % CAPACITY);
}

template <class RecordType>
inline size_t table<RecordType>::next_index(size_t index) const
// Library facilities used: cstdlib
{
    return ((index+1) % CAPACITY);
}

template <class RecordType>
void table<RecordType>::find_index(int key, bool& found, size_t& i) const
// Library facilities used: cstdlib
{
size_t count; // Number of entries that have been examined

count = 0;
i = hash(key);
while((count < CAPACITY) && (data[i].key != NEVER_USED) && (data[i].key != key))
{
    ++count;
    i = next_index(i);
}
found = (data[i].key == key);
}

template <class RecordType>
inline bool table<RecordType>::never_used(size_t index) const
{
return (data[index].key == NEVER_USED);
}

template <class RecordType>
inline bool table<RecordType>::is_vacant(size_t index) const
{
return (data[index].key == NEVER_USED);// || (data[index].key == PREVIOUSLY_USED);
}
}

#endif
EN

回答 2

Stack Overflow用户

发布于 2013-06-04 07:31:17

需要考虑的几点:

  • 您可以使用vector而不是C样式的数组来保存元素,因为它允许动态调整大小。
  • 当您需要增大表时,您必须对所有现有元素进行重新散列,以便将它们放在新容器中的新位置(当重新散列时,您可以与现有容器交换)。

希望能够指定决定何时增长的加载因子。

  • 您需要决定是否允许容器再次以某个阈值收缩分配的空间。
票数 1
EN

Stack Overflow用户

发布于 2013-06-04 10:20:06

@Mark B想法就是答案。

我想补充一下:

建议您的表大小CAPACITY是一个质数。用质数修改弱哈希函数hash(key)有助于分散。(一个好的散列函数不需要帮助。)

您的增长步数通常是指数级的,并且可以构建到一个查找表中。不同的作者建议的比率在1.5和4之间。例如,Grow2 x[]={ 0,1,3,7,13,31,61,...(素数正好在2的幂之下);

假设你每次增长2倍,你的增长负载是100%。那么你的收缩负载应该是70%左右( 100%/2x和100%的几何平均值)。如果插入/删除操作在临界值附近徘徊,您希望避免增长/收缩。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16907423

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档