Blame programming-guidelines/cs/glist.page

Packit 1470ea
Packit 1470ea
<page xmlns="http://projectmallard.org/1.0/" xmlns:its="http://www.w3.org/2005/11/its" xmlns:xi="http://www.w3.org/2003/XInclude" type="topic" id="glist" xml:lang="cs">
Packit 1470ea
Packit 1470ea
  <info>
Packit 1470ea
    <link type="guide" xref="index#specific-how-tos"/>
Packit 1470ea
Packit 1470ea
    <credit type="author copyright">
Packit 1470ea
      <name>Philip Withnall</name>
Packit 1470ea
      <email its:translate="no">philip.withnall@collabora.co.uk</email>
Packit 1470ea
      <years>2015</years>
Packit 1470ea
    </credit>
Packit 1470ea
Packit 1470ea
    <include xmlns="http://www.w3.org/2001/XInclude" href="cc-by-sa-3-0.xml"/>
Packit 1470ea
Packit 1470ea
    <desc>Propojené seznamy a kontejnerové typy</desc>
Packit 1470ea
  </info>
Packit 1470ea
Packit 1470ea
  <title>GList</title>
Packit 1470ea
Packit 1470ea
  <section id="glist-usage">
Packit 1470ea
    <title>Použití GList</title>
Packit 1470ea
Packit 1470ea
    

GLib poskytuje někoklik kontejnerových typů pro množiny dat: <link href="https://developer.gnome.org/glib/stable/glib-Doubly-Linked-Lists.html">GList</link>, <link href="https://developer.gnome.org/glib/stable/glib-Singly-Linked-Lists.html">GSList</link>, <link href="https://developer.gnome.org/glib/stable/glib-Pointer-Arrays.html">GPtrArray</link> a <link href="https://developer.gnome.org/glib/stable/glib-Arrays.html">GArray</link>.

Packit 1470ea
Packit 1470ea
    

Dříve bylo běžnou praxí používat GList ve všech situacích, kdy bylo zapotřebí uchovat řadu nebo množinu dat. To ale není rozumné — ve většině situací by místo něj měl být použit GPtrArray. Má menší paměťové nároky (třetinové až poloviční oproti obdobnému seznamu), lepší dostupnost z mezipaměti a stejnou nebo menší algoritmickou složitost pro všechny běžné operace. Jedinou typickou situací, kdy může být GList vhodnější, je při práci se uspořádanými daty ve kterých je požadováno masivní vkládání na libovolné místo v poli.

Packit 1470ea
Packit 1470ea
    

Když jsou použité zřetězené seznamy, dávejte pozor, aby složitost operací zůstala na rozumné úrovni podle standardní analýzy složitosti v matematické informatice. Kterákoliv operace, která používá <link href="https://developer.gnome.org/glib/2.30/glib-Doubly-Linked-Lists.html#g-list-nth">g_list_nth()</link> nebo <link href="https://developer.gnome.org/glib/2.30/glib-Doubly-Linked-Lists.html#g-list-nth-data">g_list_nth_data()</link>, je povětšinou úplně špatně. Například iterace přes GList by měla být implementována pomocí zřetězujících ukazatelů a ne postupným zvyšováním indexu.

Packit 1470ea
    GList *some_list, *l;
Packit 1470ea
Packit 1470ea
for (l = some_list; l != NULL; l = l->next)
Packit 1470ea
  {
Packit 1470ea
    gpointer element_data = l->data;
Packit 1470ea
Packit 1470ea
    /* Provedení něčeho s @element_data. */
Packit 1470ea
  }
Packit 1470ea
Packit 1470ea
    

Když se místo toho použije postupné zvyšování indexu, je výsledkem kvadratické snížení výkonu (O(N^2) namísto O(N)):

Packit 1470ea
    GList *some_list;
Packit 1470ea
guint i;
Packit 1470ea
Packit 1470ea
/* Tento algoritmus je neefektivní a neměl by být použit v produkčním kódu. */
Packit 1470ea
for (i = 0; i < g_list_length (some_list); i++)
Packit 1470ea
  {
Packit 1470ea
    gpointer element_data = g_list_nth_data (some_list, i);
Packit 1470ea
Packit 1470ea
    /* Provedení něčeho s @element_data. */
Packit 1470ea
  }
Packit 1470ea
Packit 1470ea
    

Snížení výkonu nastává ve funkcích g_list_length() a g_list_nth_data(), které obě kvůli provedení své operace pole procházejí (O(N)).

Packit 1470ea
Packit 1470ea
    

Implementace kódu uvedeného výše pomocí GPtrArray má stejnou složitost pro první (správnou) implementaci GList, ale lepší dostupnost z mezipaměti a nižší spotřebu paměti, takže bude mít lepší výkon pro velké množství prvků:

Packit 1470ea
    GPtrArray *some_array;
Packit 1470ea
guint i;
Packit 1470ea
Packit 1470ea
for (i = 0; i < some_array->len; i++)
Packit 1470ea
  {
Packit 1470ea
    gpointer element_data = some_array->pdata[i];
Packit 1470ea
Packit 1470ea
    /* Provedení něčeho s @element_data. */
Packit 1470ea
  }
Packit 1470ea
  </section>
Packit 1470ea
</page>