C中链接列表的链接列表

时间:2015-04-16 19:09:19

标签: c linked-list hashtable

我在C中有一个项目,我需要创建一个带链表的链式哈希表。 实际上,因为我看到它是一个链表,链表作为节点。 因此,哈希表中每个条目中每个节点的数据结构应为:

typedef struct node {
    int value;
    int counter;
    struct node *next;
} t_listnode;

然后应该包含上述节点的哈希表如下所示:

typedef struct {
    t_listnode *head;
    t_listnode *tail;
} t_htentry;

我已经耗尽了我的小脑(第一次触摸链接列表),无法想象如何创建哈希表以及如何在每个条目中输入数据。 任何帮助都将受到高度赞赏。

谢谢!

1 个答案:

答案 0 :(得分:5)

此答案假设您使用外部链接列表和内部链接列表:

首先,为了让您的生活更轻松,您应该为内部链接列表node制作一些方法:

  • insert():迭代到链接列表的末尾并添加新节点
  • find():遍历列表,查看您的价值是否符合您的要求

接下来,您将要实现哈希表的相关方法:

  • get()find():哈希您正在寻找的元素以获取外部链接列表中的索引,然后遍历该索引处的内部链接列表以查找您的元素寻找
  • put()insert():哈希您正在寻找的元素以获取外部链接列表中的索引,您将在该链接列表中附加到内部链接列表的末尾< / LI>

最重要的是,对于哈希表,您需要创建hash()函数。在这种情况下,由于您的数据看起来是int,因此您的散列函数应该接受一个int,然后将该int散列到外部链接列表中的给定位置。

由于您使用链接列表来表示哈希表的外部结构,因此您肯定希望创建一个迭代外部链表(at())的t_htentry方法,返回指向内部链表的索引的指针(在您的情况下,是t_listnode节点)。

示例

我们想在我们的哈希表中添加10,201,302。

第一步是将t_htentry* hashtable[PRIME_NUMBER]预分配到素数大小 - 即,假设我们从大小为5的数组开始(数组中的每个索引都用[ ]表示)。 t_listnode* head已经在每个t_htentry*中,每个t_htentry*( )表示,头节点由*表示,尾节点由t)表示。

  0      1      2      3      4  -- indexes
[(*)]  [(*)]  [(*)]  [(*)]  [(*)] -- t_htentry*[] with t_listnode* head in each index
  |      |      |      |      |
  v      v      v      v      v  -- pointer
 (t)    (t)    (t)    (t)    (t) -- t_listnode* tail

第二步是哈希我们的第一个数据点 - 10.

int idx = hash(10); //-> 2

第三步是在我们的外部列表中找到idx(2)。 hashtable[idx]会给我们一个恒定的时间查找!

现在第四步是将一个带有数据点5的节点附加到该列表中。

// append value to hashtable[idx] (where "next" points to TAIL)
insert(hashtable[idx], 5);

[(*)]  [(*)]  [(*)]  [(*)]  [(*)]
  |      |      |      |      |
  |      |      v      |      |
  |      |     (5)     |      |
  |      |      |      |      |
  v      v      v      v      v
 (t)    (t)    (t)    (t)    (t)

第五步,我们现在进入下一个数据点201.假设201哈希值也是idx = 2。 (从现在开始,我不想为所有没有任何数据的索引绘制[(t)],但请注意它们仍在那里。)

idx = hash(201); //-> 2
t_listnode * spot = positionAt(hashtable, idx);
insert(spot, 201);

[(*)]  [(*)]  [(*)]  [(*)]  [(*)]
                |
                v
               (5)
                |
                v
               (2)
                |
                v
               (t)

下一步,我们将转到我们的最后一个数据点302.假设有302个哈希值到idx = 0

 idx = hash(302); //-> 0
 t_listnode * spot = positionAt(hashtable, idx);
 insert(spot, 302);

 [(*)]  [(*)]  [(*)]  [(*)]  [(*)]
   |             |
   v             v
 (302)          (5)
   |             |
   v             v
  (t)           (2)
                 |
                 v
                (t)

其中,

hash看起来像these examples

之一

insert看起来像

void insert(t_htentry * bucket, int value) {
  // copy spot to a new t_listnode* and iterate until spot->next is NULL
  // (i.e., t_htentry* tmp = bucket; tmp = bucket->head->next)
  // create a new node with t_listnode->value set to value
  // set the current spot's next to the new node
  // set the new node's next to the TAIL node
}

find看起来像

bool find(hashtable, int value) {
  // hash "value" and go to hashtable[idx] as before
  // iterate through hashtable[idx]'s linked list as before using a copy
  // of that t_htentry*.
  // if the node that you're on has ->value == value, return true
  // else continue until you're at the end of the list, and return false
}

此实施的效果将针对findinsert进行O(1)摊销。了解原因非常重要。