几天前,我问自己在 C 的函数中应该使用哪种数据结构。 我通常用 C ++ 编写,选择将落到std :: vector。
有一些可能的选择:
最后一个选项似乎不寻常。有没有更大的项目在哪里 有人使用自己的结构像列表? 数组或自己之间的决定是否有一般规则 数据结构?
当我需要树形结构时,我不会想到只写一棵树。 有没有广泛使用的具有这种结构的库(比如boost for C ++)? 或者这被认为是不好的风格,因为你必须存储一个空*而不是 实际类型?
非常感谢您的体验!
答案 0 :(得分:6)
不同的数据结构为插入,查找和其他操作提供了不同的计算复杂性。
以您的具体示例为例,数组和链表之间存在许多差异:
O(1)
,列表中为O(n)
; O(1)
或O(n)
(取决于它们是否需要遍历),如果做得好,则会在一个数组中分摊O(1)
; O(n)
,而某些类型的列表删除可以在O(1)
时间内完成; 您可能会发现以下页面非常有用:http://essays.hexapodia.net/datastructures/
作为一般规则,在选择数据结构时,我首先考虑是否有充分的理由相信相关代码的性能会变得很重要:
关于优秀C数据结构库的建议,请查看Are there any open source C libraries with common data structures?
答案 1 :(得分:1)
这完全取决于您要对数据结构执行哪些操作。如果您将通过索引检索数据(例如,数据[3]),那么列表是一个可怕的想法,因为每次读取都需要您遍历列表。如果你将大量插入第一个位置(例如,data [0] = x),那么数组将会非常糟糕,因为你将为每次插入移动所有数据。
如果你打算使用std :: vector,那么动态数组可能是最好的替代品。但也许std :: vector不是正确的选择。
答案 2 :(得分:0)
动态链接列表广泛用于C,其中要存储的项目数量未知。
答案 3 :(得分:0)
Vector是一个动态数组,在内部实现为动态数组。我建议您使用向量,因为机器已经过优化以检索连续的内存位置,而链接列表将不会存储在连续的位置。
话虽如此,如果你不需要在你的用例中快速检索索引元素,那么你也可以去链接列表。链接列表也有一个好处,就是不要浪费空间而不像动态数组(通过当它即将充满时加倍)并且与数组相比,在开始时或元素之间插入也更便宜。
答案 4 :(得分:0)
静态数组:非常适合在整个程序执行过程中不会改变其大小的查找表和数据。它们在程序启动时分配,因此您不必以任何方式管理此内存。缺点是您无法调整大小或释放静态数组 - 它会一直存在,直到程序终止。
动态增长的数组:易于管理的数据结构几乎可以替代C ++中的向量数组。缺点是在运行时分配内存的开销,但如果你一次分配更大的块,这可以减轻。
链接列表:如果要使用大量元素,请注意,因为在不使用内存池的情况下单独分配每个元素会导致内存浪费和碎片化。
答案 5 :(得分:0)
在纯C中我主要使用静态数组。它与嵌入式设备的编程有关,这些嵌入式设备在分配和释放内存方面存在问题 - 堆碎片。
但如果需要使用列表,我自己实现一个 - 有时它的实现基于静态数组(再次)。
我认为C语库可以提供更复杂的数据结构。 AFAIK glib被广泛使用,并至少提供链接列表。
答案 6 :(得分:0)
我记得我前段时间读过苹果公司的一份文件说这样的事情可以天真实施,其结构类似于:
struct {
void *data; //other type rather than void is easier
int length;
} MyArray;
MyArray *MyArrayCreate(){
//mallocate memory
return ...
}
void MyArrayRelease(){
free(...);
}
实现一个检查数组长度的函数,它不够长,然后分配另一个足够大的数组,以前的数据将被复制到它并添加新的数据。
MyArrayInsertAt(MyArray *array, index, void *object){
if (length < index){
//mallocate again, copy data
//update length
}
data[index] = object;
}
所以它可以这样使用:
MyArray *array = MyArrayCreate();
MyArrayInsertAt(array, 5, something);
MyArrayRelease(array);
MyArrayInsertAt()函数不会为其性能赢得代价,但它可以成为没有高要求程序/应用程序的解决方案
我找不到链接......也许有人也读过这个链接?
增加: 我发现GNU NSMutableArray(Objective-C)方法的实现是在C中完成的,它们的作用与上面相同。每次必须添加一个对象时,它们会使数组的大小加倍,并且不适合数组。见第131至145行