在C中实现set数据结构(一组唯一值)是否有任何棘手的方法?集合中的所有元素都是相同的类型,并且存在巨大的RAM内存。
据我所知,对于整数来说,使用值索引数组可以非常快速地完成它。但是我想要一个非常通用的Set数据类型。如果一个集合可以包含它本身就会很好。
答案 0 :(得分:42)
实现设置(和地图)功能的多种方式,例如:
由于你提到了价值索引数组,让我们尝试基于哈希的方法,自然地建立在价值索引数组技术之上。
谨防advantages and disadvantages基于散列和基于树的方法。
您可以设计一个哈希集(hash-tables的一个特例)指向 hashable POD s的指针,{{3内部表示为 hashables 的固定大小的数组,其中:
随着大量内存的使用,您可以慷慨地调整数据桶的大小,并结合良好的哈希方法,大幅降低dynamic array or linked list of hashables的概率,实现几乎恒定的时间性能。
您必须实施:
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!";
,一组指针会发现a
和b
不同。您可能希望对值进行哈希处理,但如果您担心哈希冲突,则应将字符串保存在集合中并执行strncmp()
以将存储的字符串与探测字符串进行比较。
(浮点数存在类似问题,但尝试在集合中表示浮点数首先是一个坏主意。)
因此,您可能需要一个标记值,一个标记用于任何类型的对象,一个用于整数值,一个用于字符串值,对于不同类型的值可能更多。这很复杂,但可行。