【问题标题】:separate chaining in hashing散列中的单独链接
【发布时间】:2014-06-11 03:22:53
【问题描述】:

我正在阅读 Robert Sedwick 关于 C++ 算法的书中关于散列的内容

我们可能会使用标头节点来简化插入代码 进入有序列表,但我们可能不想使用 M 头节点 单独链接中的单独列表。事实上,我们甚至可以消除 M 通过列表中的第一个节点链接到列表 组成表格

.

class ST
{
    struct node
    {
        Item item;
        node* next;

        node(Item x, node* t)
            { item = x; next = t; }
     };

     typedef node *link;

  private:
     link* heads;
     int N, M;

     Item searchR(link t, Key v)
     {
          if (t == 0) return nullItem;
          if (t->item.key() == v) return t->item;
          return searchR(t->next, v);
     }

   public:
     ST(int maxN)
     {
          N = 0; M = maxN/5;
          heads = new link[M];
          for (int i = 0; i < M; i++) heads[i] = 0;
     }

     Item search(Key v)
         { return searchR(heads[hash(v, M)], v); }

     void insert(Item item)
         { int i = hash(item.key(), M);
           heads[i] = new node(item, heads[i]); N++; }
};

我对上述文字的两个问题是什么作者的意思

  1. “我们甚至可以通过让列表中的第一个节点组成表来消除指向列表的 M 个链接。”我们如何修改上面的代码?

  2. “我们可能不想将 M 头节点用于单独链接中的单个列表。”这句话是什么意思。

【问题讨论】:

    标签: c++ algorithm hash


    【解决方案1】:

    “我们甚至可以通过让列表中的第一个节点组成表来消除指向列表的 M 个链接。”

    考虑Node* x[n]Node x[n]:前者需要为每个非空元素的头部Node 分配一个额外的指针和插入内存,并为每个哈希表操作提供额外的间接寻址,而后者消除了n 指针,但要求任何未使用的元素都能够置于一些可辨别的未使用状态(跟踪可能需要也可能不需要额外内存),并且如果sizeof(Node) 大小大于@ 987654326@,反正可能比较浪费内存。内存使用的差异也会影响缓存使用的效率:如果表的元素与桶的比率很高,那么Node[] 会将节点数据放入更少的连续内存页面中,如果您正在迭代(以未排序的顺序)然后它的缓存效率很高,而Node*[] 将跳转到可能遍布各处的单独内存分配(或者另一方面,在某些实际有用的情况下实际上可能非常接近:例如,如果访问模式和动态内存分配地址与对象创建的时间顺序相关。

    我们如何修改上面的代码?

    首先,您现有的代码有一个问题:heads[i] = new node(item, heads[i]); 覆盖哈希表中的一个条目,而没有先检查它是否为空...如果那里有任何内容,那么您应该添加到列表中,而不是覆盖数组。

    讨论的设计变更需要:

    link* heads;
    

    ...改为...

    node* head;
    

    你可以这样初始化它:

    head = new node[M];
    

    这需要一个额外的node 构造函数(如果item 有一个等效的默认构造函数,你可以在下面省略它的初始化)

    node() : item(nullItem), next(nullptr) { }
    

    然后对您的其余代码进行一些很容易完成的更改。基本上,你摆脱了一层指针。

    “我们可能不想在单独的链接中为单个列表使用 M 个标头节点。”这句话是什么意思。

    不是我写的,所以不能说权威,但似乎是说在设计列表代码时,可能已经决定即使在空列表中也有一个初始节点,因为这简化了代码对于几个列表操作。虽然在考虑“通常”使用列表时,额外的无数据节点似乎是一个合理的价格,但哈希表是不寻常的,因为您希望桶链中的大多数列表具有 0 或 1 个元素,并且应该呈指数级减少越来越长。因此,这样的列表实现不太适合在哈希表中使用。

    【讨论】:

      猜你喜欢
      • 2017-08-01
      • 2018-10-29
      • 2012-10-06
      • 2021-03-11
      • 2021-07-08
      • 1970-01-01
      • 1970-01-01
      • 2016-11-27
      • 1970-01-01
      相关资源
      最近更新 更多