C - 如何实现Set数据结构?

时间:2010-04-13 15:15:04

标签: c algorithm math data-structures set

在C中实现set数据结构(一组唯一值)是否有任何棘手的方法?集合中的所有元素都是相同的类型,并且存在巨大的RAM内存。

据我所知,对于整数来说,使用值索引数组可以非常快速地完成它。但是我想要一个非常通用的Set数据类型。如果一个集合可以包含它本身就会很好。

4 个答案:

答案 0 :(得分:42)

实现设置(和地图)功能的多种方式,例如:

  • 基于树的方法(有序遍历)
  • 基于散列的方法(无序遍历)

由于你提到了价值索引数组,让我们尝试基于哈希的方法,自然地建立在价值索引数组技术之上

谨防advantages and disadvantages基于散列和基于树的方法。

您可以设计一个哈希集hash-tables的一个特例)指向 hashable POD s的指针,{{3内部表示为 hashables 的固定大小的数组,其中:

  • 存储桶中的所有 hashables 具有相同的哈希值
  • 一个存储桶可以实现为chaining
  • hashable 哈希值用于索引存储桶数组(哈希值索引数组)
  • 哈希集中包含的一个或多个 hashables 可能是(指向)另一个哈希集,甚至是哈希集本身(即自包含)是可能的

随着大量内存的使用,您可以慷慨地调整数据桶的大小,并结合良好的哈希方法,大幅降低dynamic array or linked list of hashables的概率,实现几乎恒定的时间性能。

您必须实施:

  • 正在散列的类型的collision
  • 用于测试两个哈哈狗是否相等的类型的相等函数
  • 哈希集contains / insert / remove功能。

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

答案 1 :(得分:5)

集合通常实现为binary tree的各种变体。 Red black trees表现最差。

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

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

如果您将集合成员资格限制为C中明确定义的类型,我不确定如何管理可能使用二叉树包含自身的集合...这些构造之间的比较可能会有问题。不过,你可以在C ++中轻松地完成它。

答案 2 :(得分:3)

如果集合中的最大元素数(基础数据类型的基数)足够小,您可能需要考虑使用一个普通的旧数组(或者用您喜欢的语言称之为它们)。< / p>

然后你有一个简单的集合成员资格检查:如果元素n在集合中,则位n为1。你甚至可以从1计算'普通'成员,只有当集合包含自己时才将0等于1。

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

答案 3 :(得分:2)

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

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

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

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

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