簡體   English   中英

鏈表或數組以在C中存儲字符串

[英]linked list or array to store strings in C

在C語言中,我需要存儲一個可能比較大(數千個項目)的短字符串(char *)列表。
可以刪除或插入字符串,但不能修改它們,順序並不重要。
我不知道什么是更有效的數據結構來做到這一點。
我可以使用一個結構:

struct node_s {
  char *str;
  node_s *next;
}

或char *數組:

char **strings;

我不需要直接訪問字符串,我只需要它們存在,因為旁邊的另一個數據結構(基數trie)可以在字符串的某些部分維護指針。

當您不知道初始化時的確切條目數時,使用鏈表通常比使用數組更好。

數組的大小固定。 當您不知道將要有多少個條目並且想使用數組時,有兩個選擇。 要么分配一個比您將需要的任何東西都大得多的數組,這將浪費大量的內存(而且,通常很難事先知道一個合理的上限應該是多少)。 或者,您從一個小型陣列開始,然后等待其裝滿。 然后,分配一個更大的新數組,將所有條目復制到新數組中,然后重新分配舊數組,這是CPU周期的巨大浪費。

但是,有了鏈接列表,您就不會遇到問題,因為它們可以動態增長和收縮。

但是請注意各種操作在運行時的差異。

在數組中,通過其索引獲取元素非常快。 但是刪除具有特定索引的元素而不留下空條目非常昂貴,因為后面的每個單個元素都必須向后移動一個索引。 在不覆蓋現有條目的情況下在中間插入條目也同樣昂貴,因為您必須將后面的所有內容向前移動一個。

使用鏈表時,在中間位置刪除或插入節點很快(當您已有其先行節點時),因為除了插入的節點及其先行節點外,無需觸摸任何節點。 但是,找到必須在其后進行此操作的節點可能會很昂貴,因為您必須遵循之前所有節點之間的鏈接。

當您既需要快速查找又需要快速插入/刪除時,使用二進制樹是一個不錯的選擇。

這取決於您的程序。

如果知道字符串的數量。 我建議你使用陣列

如果您不知道字符串的數量,我建議您使用鏈表

如果字符串將在C中定義為常量。 您可以使用這種方式:

char *strings[1000] = {
  "string 0",
  "string 1",
  "string 2",
  "string 3",
   .
   .
   .
  "string 999"
}

實際上, char **strings只是一個字符串數組。 數組≠鏈表。 那么node_s絕對是解決方案。

這取決於您要如何處理它們。

如果順序不重要,則我認為大多數操作將被添加\\刪除。如果確實如此,則需要選擇列表數據結構(第一個變體)。

如果需要恆定時間訪問元素,則數組是個好方法,但是在無序數組中則不起作用。搜索某些字符串將花費O(n)時間,如列表中所示。

因此,如果我理解正確,字符串列表並不是訪問數據的主要方式,它只是指針的“清除列表”,必須釋放這些指針,而不必遍歷現在已經過時的所有其他數據。

在這種情況下,我將使用鏈表,但不采用通常的方式。 上面的node_s要求,對於每個字符串,您node_s對結構進行一個malloc分配,而對字符串本身進行一個malloc分配。

相反,我將定義一個這樣的結構:

struct string_list {
  struct string_list *next;
  char data[0];
};

零長度數組不占用結構中的任何空間,但會為您提供一個可以鍵入的地址。 然后,您可以為結構實際字符串分配內存:

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的字符串即可。 哦,當然,並修復鏈接。

如果您有大量項目,並且想要頻繁添加/刪除項目,但訪問時間接近隨機訪問O(log n),則應考慮使用哈希表

如果在節點上添加數千個鏈接列表,訪問時間將非常緩慢,並且數組不適合頻繁添加/刪除。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM