嘿,我一直在阅读有关C的指针,结构和数据结构,过去几天。现在,我尝试通过沿本教程来实现C中的哈希表:https://www.tutorialspoint.com/data_sustructures_algorithms/hash_table_program_in_c.htm
但是,tutorialSpoint假设只有1个哈希表,并且它使其成为全局。此外,TutorialSpoint不考虑碰撞。
我想制作一个结构,不要将自己限制在单个哈希表上,我计划将链接(处理碰撞)与链接列表结合在一起。我有以下内容:
typedef struct node {
int key;
int data;
struct node* next;
} node;
typedef struct linkedList{
node* head;
node* tail;
size_t size;
} linkedList;
typedef struct hashTable{
//perhaps an array of linked list? This member is what I need help with
//And other potential members I am overlooking
size_t size
} hashTable;
我需要解释的一些事情:
节点struct用作一对密钥/数据,它具有指向具有相同哈希代码的下一个对的指针。所有具有相同哈希代码的节点都将在同一链接列表中。
linkedlist struct代表一个链接列表,最终将成为哈希表中的一行。所有链接列表将是哈希表中的一行。
Hashtable结构包含所有链接清单。
我如何在我的Hashtable结构中制作链接列表结构的数组?我在三个结构中还有其他成员吗?
任何帮助都将受到赞赏!
P.S。我计划使用我在链接列表程序中写的方法。这是它的早期版本的链接:https://codereview.stackexchange.com/questions/176904/my-linked-list-implementation-in-in-c
typedef struct linkedList{
node* head;
node* tail;
size_t size;
} linkedList;
我认为您在这里真的不需要size_t size
。实际的哈希表结构,您可以做什么:
typedef struct has_map {
linkedList** table; // stores the actual collision chains.
size_t table_capacity; // the current capacity of table.
size_t size; // number of mappings in this hash map.
} hash_map;
另外,我建议您将table
的长度保持在两个:2、4、8、16,...这样您可以使用位操作hash_code & (hash_map->table_capacity - 1)
。
hash_code % hash_map->table_capacity
。您可以使用节点和列表结构。然后,哈希表将只是一个带有一系列列表的结构。哈希表的大小可能是动态的,但让我们使用一个恒定的大小:
enum {
hashSize = 32
};
typedef struct hashTable {
linkedList list[hashSize];
size_t size; // How many elelents overall?
} hashTable;
您的哈希函数必须返回一个无符号哈希值小于 hashSize
。
但是您实际上不需要链接的列表结构。该结构可以在前面和末端轻松插入,并且还可以保持其元素的数量。列表的元素未排序,因此您可以随时在正面插入,并且您实际上不需要大小,因此您只需通过指示来定义链接列表,最初是所有NULL
:
typedef struct hashTable {
node *head[hashSize];
size_t size;
} hashTable;
(但是,如果您已经有链接列表的代码,则可能是链接列表的数组。)
您链接的教程码头代码上的注释:它确实可以满足碰撞,但它使用了另一种方法:每个哈希代码只有一个插槽。如果已经使用了哈希代码的插槽,则使用下一个免费的哈希代码。
该方法意味着您不能简单地删除元素。想象一下,您插入了带有哈希值5的项目,但是该插槽已经由另一个带有不同键但相同哈希代码的项目插入。也要采用6和7,因此您将项目插入插槽8。如果搜索该项目,则首先搜索搜索插槽5,但是那里的项目不匹配。HES代码增加了,最终,该项目在插槽8中找到。如果我们首先找到一个空的插槽,则搜索将不会成功。在插槽5中删除该项目使插槽8中的项目无法访问。因此,必须将假人元素放入该插槽中。您的链接列表方法不需要这样的虚拟元素。
(TutorialSpoint方法还意味着,如果Hash表已满,您将搜索所有元素,这并不比搜索未分类数组更好。链接的列表哈希表将永远不会满足,但是当表中的项目远大于哈希表尺寸,性能会降低。)