【问题标题】:C - How to implement Set data structure?C - 如何实现 Set 数据结构?
【发布时间】:2011-02-07 12:19:32
【问题描述】:

在 C 中实现集合数据结构(唯一值的集合)有什么棘手的方法吗?一个集合中的所有元素都将属于同一类型,并且有一个巨大的 RAM 内存。

据我所知,对于整数,使用值索引数组可以非常快速地完成。但我想要一个非常通用的 Set 数据类型。如果一个集合可以包含它自己,那就太好了。

【问题讨论】:

标签: c algorithm math data-structures set


【解决方案1】:

多种实现方式设置(和映射)功能,例如:

  • 基于树的方法(有序遍历)
  • 基于哈希的方法(无序遍历)

既然您提到了值索引数组,让我们尝试一下基于散列的方法,它自然地构建在值索引数组技术之上

当心advantages and disadvantages 基于散列与基于树的方法。

您可以设计一个 hash-sethash-tables 的特例)指向 hashable PODs 的指针,chaining,内部表示为一个固定大小的 hashables 桶数组,其中:

  • 桶中的所有hashables都有相同的hash值
  • 桶可以实现为dynamic array or linked list of hashables
  • 一个hashable哈希值用于索引桶数组(哈希值索引数组)
  • 散列集中包含的一个或多个 hashables 可以是(指向)另一个散列集,甚至是散列集本身(即 自包含是可能的

有了可供您支配的大量内存,您可以充分调整存储桶数组的大小,并结合良好的哈希方法,大大降低collision 的概率,实现几乎恒定的时间性能。

你必须实现:

  • 被散列的类型的hash function
  • 用于测试两个哈希值是否相等的类型的相等函数
  • 哈希集contains/insert/remove 功能。

您还可以使用open addressing 作为维护和管理存储桶的替代方法。

【讨论】:

    【解决方案2】:

    集合通常以某种binary tree 的形式实现。 Red black trees 具有良好的最坏情况性能。

    这些也可用于构建map 以允许键/值查找。

    这种方法需要对集合的元素和映射中的键值进行某种排序。

    如果您将集合成员限制为 C 中明确定义的类型,我不确定您将如何使用二叉树来管理可能包含自身的集合......此类构造之间的比较可能会出现问题。不过,您可以在 C++ 中轻松做到这一点。

    【讨论】:

      【解决方案3】:

      如果集合中元素的最大数量(基础数据类型的基数)足够小,您可能需要考虑使用普通的旧位数组(或您喜欢的语言中的任何名称)。

      然后你有一个简单的集合成员检查:如果元素 n 在集合中,位 n 为 1。您甚至可以从 1 开始计算“普通”成员,并且只有在集合包含自身时才使位 0 等于 1。

      这种方法可能需要某种其他数据结构(或函数)来从成员数据类型转换到位数组中的位置(并返回),但它会进行基本的集合操作(​​联合、交集、成员资格测试,差异,插入,删除,强制)非常非常容易。而且它只适用于相对较小的集合,你不会想将它用于我不认为的 32 位整数集合。

      【讨论】:

        【解决方案4】:

        在 C 中获得泛型的方法是通过void *,所以无论如何你都将使用指针,并且指向不同对象的指针是唯一的。这意味着您需要一个包含指针的哈希映射或二叉树,这适用于所有数据对象。

        这样做的缺点是您不能独立输入右值。你不能有一个包含值 5 的集合;您必须将 5 分配给一个变量,这意味着它不会匹配随机 5。您可以将其输入为 (void *) 5,出于实际目的,这可能适用于小整数,但如果您的整数可以变大足够的大小来与指针竞争,这有非常小的失败概率。

        这也不适用于字符串值。给定char a[] = "Hello, World!"; char b[] = "Hello, World!";,一组指针会发现ab 不同。您可能希望对这些值进行哈希处理,但如果您担心哈希冲突,您应该将字符串保存在集合中并执行strncmp() 以将存储的字符串与探测字符串进行比较。

        (浮点数也有类似的问题,但首先尝试在集合中表示浮点数是个坏主意。)

        因此,您可能需要一个标记值,一个标记用于任何类型的对象,一个标记用于整数值,一个标记用于字符串值,并且可能更多用于不同类型的值。这很复杂,但可行。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-09-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多