【问题标题】:C - How to implement Set data structure?C - 如何实现 Set 数据结构?
【发布时间】:2011-02-07 12:19:32
【问题描述】:
在 C 中实现集合数据结构(唯一值的集合)有什么棘手的方法吗?一个集合中的所有元素都将属于同一类型,并且有一个巨大的 RAM 内存。
据我所知,对于整数,使用值索引数组可以非常快速地完成。但我想要一个非常通用的 Set 数据类型。如果一个集合可以包含它自己,那就太好了。
【问题讨论】:
标签:
c
algorithm
math
data-structures
set
【解决方案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!";,一组指针会发现a 和b 不同。您可能希望对这些值进行哈希处理,但如果您担心哈希冲突,您应该将字符串保存在集合中并执行strncmp() 以将存储的字符串与探测字符串进行比较。
(浮点数也有类似的问题,但首先尝试在集合中表示浮点数是个坏主意。)
因此,您可能需要一个标记值,一个标记用于任何类型的对象,一个标记用于整数值,一个标记用于字符串值,并且可能更多用于不同类型的值。这很复杂,但可行。