Kiedy używać listy połączonej nad tablicą / listą tablic?

Używam wielu list i tablic, ale jeszcze nie spotkałem się ze scenariuszem, w którym lista tablic nie mogłaby być używana tak łatwo, jak, jeśli nie łatwiej niż lista połączona. Miałem nadzieję, że ktoś poda mi kilka przykładów, kiedy powiązana lista jest wyraźnie lepsza.

Author: Juha Syrjälä, 2008-12-26

13 answers

Listy połączone są preferowane zamiast tablic, gdy:

A) musisz wstawiać/usuwać w czasie stałym z listy (na przykład w obliczeniach w czasie rzeczywistym, gdzie przewidywalność czasu jest absolutnie krytyczna)

B) nie wiesz ile pozycji będzie na liście. W przypadku tablic może być konieczne ponowne zadeklarowanie i skopiowanie pamięci, jeśli tablica będzie zbyt duża

C) nie potrzebujesz losowego dostępu do żadnych elementów

D) chcesz mieć możliwość wstawiania elementów w środku lista (np. Kolejka priorytetów)

Tablice są preferowane, gdy:

A) potrzebujesz indeksowanego / losowego dostępu do elementów

B) znasz liczbę elementów w tablicy z wyprzedzeniem, dzięki czemu możesz przydzielić odpowiednią ilość pamięci dla tablicy

C) potrzebujesz prędkości podczas iteracji przez wszystkie elementy w kolejności. Możesz użyć wskaźnika na tablicy, aby uzyskać dostęp do każdego elementu, podczas gdy musisz wyszukać węzeł na podstawie wskaźnika dla każdego elementu w linked list, co może skutkować błędami strony, które mogą skutkować trafieniami wydajności.

D) pamięć jest problemem. Wypełnione tablice zajmują mniej pamięci niż listy połączone. Każdy element tablicy jest tylko danymi. Każdy węzeł listy połączonej wymaga danych, a także jednego (lub więcej) wskaźnika do innych elementów listy połączonej.

Listy tablic (takie jak te w. Net) dają ci korzyści z tablic, ale dynamicznie przydzielają zasoby dla Ciebie, abyś nie musiał się zbytnio martwić o rozmiarze listy i możesz usuwać elementy w dowolnym indeksie bez żadnego wysiłku lub ponownego tasowania elementów. Pod względem wydajności, arraylists są wolniejsze niż surowe tablice.

 206
Author: Lamar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-26 09:05:57

Tablice mają o (1) losowy dostęp, ale są naprawdę drogie, aby dodawać lub usuwać rzeczy z.

Połączone listy są naprawdę tanie, aby dodawać lub usuwać elementy w dowolnym miejscu i iterację, ale dostęp losowy to O (n).

 45
Author: Dustin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-26 07:08:06

Aby dodać do innych odpowiedzi, większość implementacji array list rezerwuje dodatkową pojemność na końcu listy, aby nowe elementy mogły być dodawane na końcu listy w czasie O(1). Gdy pojemność listy tablic jest przekroczona, nowa, większa tablica jest alokowana wewnętrznie, a wszystkie stare elementy są kopiowane. Zwykle nowa tablica jest dwukrotnie większa od starej. Oznacza to, że średnio dodawanie nowych elementów na końcu listy tablicy jest operacją O (1) w tych wdrożenia. Więc nawet jeśli nie znasz wcześniej liczby elementów, lista tablic może być szybsza od listy połączonej do dodawania elementów, o ile dodajesz je na końcu. Oczywiście wstawianie nowych elementów w dowolnych miejscach na liście tablicy jest nadal operacją O (n).

Dostęp do elementów z listy tablicy jest również szybszy niż lista połączona, nawet jeśli dostęp jest sekwencyjny. Dzieje się tak dlatego, że elementy tablicy są przechowywane w ciągłej pamięci i mogą być buforowane łatwo. Węzły listy połączonej mogą być potencjalnie rozproszone na wielu różnych stronach.

Zalecałbym używanie listy linkowanej tylko wtedy, gdy wiesz, że będziesz wstawiać lub usuwać elementy w dowolnych miejscach. Listy tablic będą szybsze dla prawie wszystkich innych.

 13
Author: Jay Conrod,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-26 09:13:52
Algorithm           ArrayList   LinkedList
seek front            O(1)         O(1)
seek back             O(1)         O(1)
seek to index         O(1)         O(N)
insert at front       O(N)         O(1)
insert at back        O(1)         O(1)
insert after an item  O(N)         O(1)

ArrayLists są dobre dla write-once-read-many lub appenders, ale złe w Dodaj/usuń z przodu lub pośrodku.

 12
Author: Vpn_talent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-01 08:52:25

Zaleta list pojawia się, gdy trzeba wstawić elementy w środku i nie chce się zmieniać rozmiaru tablicy i przesuwać rzeczy wokół.

Masz rację, że zazwyczaj tak nie jest. Miałem kilka bardzo konkretnych przypadków, ale nie za wiele.

 7
Author: Uri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-26 07:07:49

Są to najczęściej używane implementacje kolekcji.

ArrayList:

  • Wstaw/Usuń na końcu ogólnie O (1) najgorszy przypadek O (N)

  • Insert/delete in the middle O (n)

  • Pobierz dowolną pozycję O(1)

LinkedList:

  • Insert/delete in any position O (1) (note if you have a reference to the element)

  • Pobierz w środku O (n)

  • Pobieranie pierwszego lub ostatniego elementu O(1)

Vector: nie używaj go. Jest to stara implementacja podobna do ArrayList, ale ze wszystkimi metodami zsynchronizowanymi. Nie jest to właściwe podejście do udostępnionej listy w środowisku wielowątkowym.

HashMap

Insert / delete / retrieve by key in O (1)

TreeSet insert/delete / contains in O (log N)

HashSet insert/remove/contains / size in O(1)

 2
Author: Praveen Kumar Verma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-04 13:26:41

Wszystko zależy od tego, jaki rodzaj operacji wykonujesz podczas iteracji, wszystkie struktury danych mają kompromis między czasem a pamięcią i w zależności od naszych potrzeb powinniśmy wybrać odpowiedni DS. Są więc przypadki, w których LinkedList jest szybszy niż array i odwrotnie . Rozważmy trzy podstawowe operacje na strukturach danych.

  • Wyszukiwanie

Ponieważ tablica jest indeksową tablicą przeszukiwania struktury danych.get (index) zajmie O(1) czas, podczas gdy linkedlist nie jest indeks DS więc będziesz musiał przejść do indeksu, gdzie indeks

Q.So co za tym stoi ?

Ponieważ tablice są sąsiadującymi blokami pamięci, duże ich fragmenty zostaną załadowane do pamięci podręcznej przy pierwszym dostępie, co sprawia, że dostęp do pozostałych elementów tablicy jest stosunkowo szybki, tak samo jak dostęp do elementów w lokalizacji tablicy odniesienia również zwiększa w ten sposób mniej błędów połowu, Cache location odnosi się do operacji znajdujących się w cache i tym samym wykonać znacznie szybciej w porównaniu do w pamięci, w zasadzie w tablicy maksymalizujemy szanse na dostęp do elementów sekwencyjnych jest w cache. Chociaż połączone listy niekoniecznie znajdują się w ciągłych blokach pamięci, nie ma gwarancji, że elementy, które pojawiają się kolejno na liście, są faktycznie rozmieszczone blisko siebie w pamięci, oznacza to mniej trafień pamięci podręcznej, np. więcej chybień pamięci podręcznej, ponieważ musimy odczyt z pamięci dla każdego dostępu do linkowanego elementu listy, co zwiększa czas potrzebny na dostęp do niego i obniża wydajność, więc jeśli robimy więcej operacji dostępu losowego aka wyszukiwanie, tablica będzie szybka, jak wyjaśniono poniżej.

  • Wstawianie

Jest to łatwe i szybkie w LinkedList, ponieważ wstawianie jest o (1) operacja w LinkedList (w Javie) w porównaniu do array, rozważ przypadek, gdy tablica jest pełna, musimy skopiować zawartość do nowej tablicy, jeśli tablica jest pełna co sprawia, że wstawianie elementu do ArrayList O (n) w najgorszym przypadku, podczas gdy ArrayList również musi zaktualizować swój indeks , jeśli wstawisz coś gdziekolwiek poza końcem tablicy, w przypadku linked list nie musimy zmieniać jego rozmiaru, wystarczy zaktualizować wskaźniki.

  • delecja

Działa jak insertions i lepiej w LinkedList niż array.

 1
Author: Harleen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-16 09:32:25

Hmm, Arraylist może być używany w takich przypadkach jak:

  1. nie jesteś pewien, ile elementów będzie obecnych
  2. ale musisz uzyskać dostęp do wszystkich elementów losowo poprzez indeksowanie

Na przykład, musisz zaimportować i uzyskać dostęp do wszystkich elementów na liście kontaktów (której rozmiar jest dla Ciebie nieznany)

 0
Author: Raghu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-27 20:37:57

Użyj listy połączonej dla sortowania Radix nad tablicami i dla operacji wielomianowych.

 0
Author: gizgok,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-24 15:30:52

1) Jak wyjaśniono powyżej operacje wstawiania i usuwania dają dobrą wydajność (O(1)) w LinkedList w porównaniu do ArrayList(O (n)). Dlatego jeśli istnieje wymóg częstego dodawania i usuwania w aplikacji, LinkedList jest najlepszym wyborem.

2) operacje wyszukiwania (get) są szybkie w Arraylist(O (1)), ale nie w LinkedList(O (n)), więc jeśli jest mniej operacji dodawania i usuwania oraz więcej operacji wyszukiwania, ArrayList byłoby najlepszym rozwiązaniem.

 0
Author: Avanish Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-05 12:01:21

Myślę, że główną różnicą jest to, czy często trzeba wstawiać lub usuwać rzeczy z góry listy.

W przypadku tablicy, jeśli usuniesz coś z góry listy, złożoność jest o (n), ponieważ wszystkie indeksy elementów tablicy będą musiały się przesunąć.

Z listą połączoną jest o(1), ponieważ wystarczy utworzyć węzeł, ponownie przypisać head i przypisać referencję do next jako poprzedni head.

Przy częstym wstawianiu lub usuwaniu na koniec listy, tablice są preferowane, ponieważ złożoność będzie wynosić o( 1), nie jest wymagane ponowne łączenie, ale dla listy połączonej będzie to o(n), ponieważ musisz przejść od głowicy do ostatniego węzła.

Myślę, że wyszukiwanie zarówno w linkowanych listach, jak i tablicach będzie o (log n), ponieważ prawdopodobnie będziesz używał wyszukiwania binarnego.

 0
Author: Curious_goat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-31 16:00:36

Zrobiłem trochę benchmarkingu i stwierdziłem, że Klasa list jest w rzeczywistości szybsza niż LinkedList do losowego wstawiania:

using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            int count = 20000;
            Random rand = new Random(12345);

            Stopwatch watch = Stopwatch.StartNew();
            LinkedList<int> ll = new LinkedList<int>();
            ll.AddLast(0);
            for (int i = 1; i < count; i++)
            {
                ll.AddBefore(ll.Find(rand.Next(i)),i);

            }
            Console.WriteLine("LinkedList/Random Add: {0}ms", watch.ElapsedMilliseconds);

            watch = Stopwatch.StartNew();
            List<int> list = new List<int>();
            list.Add(0);
            for (int i = 1; i < count; i++)
            {
                list.Insert(list.IndexOf(rand.Next(i)), i);

            }
            Console.WriteLine("List/Random Add: {0}ms", watch.ElapsedMilliseconds);

            Console.ReadLine();
        }
    }
}

Potrzeba 900 ms dla linked list i 100 ms dla list class.

Tworzy listy kolejnych liczb całkowitych. Każda nowa liczba całkowita jest wstawiana po liczbie losowej, która jest już na liście. Może Klasa List używa czegoś lepszego niż tablica.

 0
Author: Emil Albert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-19 12:40:50

W rzeczywistości pamięć ma ogromny wpływ na wydajność w rzeczywistym przetwarzaniu.

Zwiększone wykorzystanie strumieniowania dysków w przetwarzaniu" dużych danych " w porównaniu z dostępem losowym pokazuje, jak struktura aplikacji wokół tego może znacznie poprawić wydajność na większą skalę.

Jeśli istnieje jakakolwiek możliwość uzyskania dostępu do tablicy sekwencyjnie, która jest zdecydowanie najlepiej działająca. Projektowanie z tym celem powinno być przynajmniej brane pod uwagę, jeśli wydajność jest ważna.

 0
Author: user3150186,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-07 08:17:39