在C中,我需要存储一个相对较大的短字符串(char *)列表(数千个项目)。
字符串可以删除或插入但不能修改,顺序并不重要
我不知道什么是更有效的数据结构来做到这一点
我可以使用结构:
struct node_s {
char *str;
node_s *next;
}
或char *:
的数组char **strings;
我不需要直接访问 字符串,我只需要它们存在,因为旁边的另一个数据结构(基数trie)维护字符串某些部分的指针。
答案 0 :(得分:2)
如果您在初始化时不知道确切的条目数,使用链表通常比使用数组更好。
数组具有固定大小。如果您不知道有多少条目并且想要使用数组,则有两种选择。你要么分配一个比你需要的任何东西都大得多的数组,这是一个巨大的内存浪费(而且,事先很难知道合理的上限应该是多少)。或者你从一个小阵列开始,等到它满了。然后你分配一个新的,更大的数组,将所有条目复制到新数组并释放旧数组,这是一个巨大的CPU周期浪费。
但是对于链接列表,您没有那个问题,因为它们可以动态增长和缩小。
但要注意各种操作的运行时差异。
在数组中,通过索引获取元素非常快。但是删除具有特定索引的元素而不留空条目是非常昂贵的,因为后面的每个元素必须向后移动一个索引。在中间插入一个条目而不覆盖现有的条目同样昂贵,因为你必须将所有后面的条目移动一个。
使用链接列表,在中间删除或插入节点很快(当您已经拥有其前端节点时),因为除了插入的节点及其前置节点之外,不需要触摸任何节点。但是找到必须进行此操作的节点可能很昂贵,因为您必须遵循之前所有节点的链接。
当您需要快速查找和快速插入/删除时,使用binary tree是一个很好的折衷方案。
答案 1 :(得分:1)
这取决于你的程序。
如果你知道字符串的数量。我建议你使用数组
如果您不知道字符串的数量,我建议您使用链表
如果字符串将在C中定义为常量。你可以这样使用:
char *strings[1000] = {
"string 0",
"string 1",
"string 2",
"string 3",
.
.
.
"string 999"
}
答案 2 :(得分:1)
实际上,char **strings
只是一个字符串数组。 array≠链表。那么node_s
绝对是解决方案。
答案 3 :(得分:1)
这取决于你想用它们做什么。
如果订单不重要,我认为大多数操作都是添加\删除.. 如果确实如此,则需要选择列表数据结构(第一个变体)。
如果你需要对元素进行恒定时间访问,那么数组是好的,但是在无序数组中,这是行不通的。搜索一些字符串将花费O(n)时间,就像列表一样。
答案 4 :(得分:1)
因此,如果我理解正确,字符串列表不是访问数据的主要方式,它只是一个"清理列表"必须释放的指针,而不必浏览所有其他的,现在过时的数据。
在这种情况下,我会使用链表,但不是正常的方式。上面的node_s
要求,对于每个字符串,您为结构执行一个malloc
,为字符串本身执行一个。{/ p>
相反,我会定义一个这样的结构:
struct string_list {
struct string_list *next;
char data[0];
};
零长度数组在结构中不占用空间,但为您提供了一个可以输入的类型地址。然后,您可以将malloc内存用于struct 和实际字符串:
struct string_list *newstr = malloc (sizeof(struct string_list) + my_desired_size);
然后,您将数据放在newstr->data
,并链接next
指针:
newstr->next = list_head;
strcpy (newstr->data, my_data, my_desired_size);
list_head = newstr;
现在是时候释放字符串了,只需free
一个{{1}}。哦,当然还要修理链接。
答案 5 :(得分:0)
如果您有大量商品并且想要经常添加/删除商品,而访问时间接近随机访问O(日志n),则应考虑hash table。
如果在节点上添加数千个,并且某个数组不适合频繁添加/删除,链接列表的访问时间将会非常慢。