Menu
Coddy logo textTech

Kolejka (FIFO)

Ostatnia aktualizacja

Kolejka ma dwa aktywne końce. Nowe wartości dołączają na końcu, a wychodzą z początku, więc najpierw obsługiwane jest to, co czekało najdłużej. To FIFO i dokładnie tak zachowuje się kolejka do okienka: dołączanie na końcu i obsługa od początku sprawiają, że czekanie jest sprawiedliwe. Kliknij Odtwórz powyżej i zobacz, jak wartości wchodzą z jednej strony i wychodzą z drugiej.

Ponieważ każdy koniec jest śledzony przez własny indeks lub wskaźnik, obie operacje kosztują O(1) i żadna nie przesuwa pozostałych danych. Dlatego kolejki leżą u podstaw wszystkiego, co przetwarza pracę w kolejności nadejścia: zadań drukowania, kolejek zadań i wiadomości, buforów żądań oraz przeszukiwania wszerz, które odwiedza graf poziom po poziomie właśnie dlatego, że trzyma swoją granicę w kolejce. Przenieś koniec usuwania na tył, a otrzymasz stos.

Złożoność czasowa i pamięciowa

Dla kolejki opartej na buforze cyklicznym lub liście jednokierunkowej, czyli dwóch standardowych implementacjach:

OperacjaZłożonośćUwagi
EnqueueO(1)Zapisz na końcu i przesuń indeks końca.
DequeueO(1)Odczytaj z początku i przesuń indeks początku, bez przesuwania danych.
Peek (początek)O(1)Odczytaj wartość z początku bez jej usuwania.
WyszukiwanieO(n)Kolejka nie służy do tego: aby zajrzeć do środka, trzeba ją opróżnić.
PamięćO(n)Jedno pole na każdą czekającą wartość.

Krok po kroku

KrokCo się dzieje
1Kolejka jest na początku pusta, a początek i koniec wskazują to samo pole.
2Enqueue zapisuje wartość na końcu, a potem przesuwa koniec o jeden.
3Każde kolejne enqueue trafia za wartości, które już czekają.
4Dequeue odczytuje wartość z początku, a potem przesuwa początek o jeden.
5Zwracana wartość to zawsze ta, która czekała najdłużej.
6Gdy początek spotka koniec, kolejka znów jest pusta, a dalsze dequeue to błąd.

Przykład krok po kroku

Dodanie 3, 7, 5, a potem opróżnienie kolejki:

OperacjaKolejka (od początku do końca)Zwraca
enqueue(3)[3]nic
enqueue(7)[3, 7]nic
enqueue(5)[3, 7, 5]nic
dequeue()[7, 5]3, najstarsza wartość
dequeue()[5]7
dequeue()[]5, najnowsza wartość, na końcu

Kiedy używać kolejki

Używaj, gdyUnikaj, gdy
Pracę trzeba obsłużyć w kolejności nadejścia: kolejki zadań, bufory żądań, bufory wydrukuPotrzebujesz najpierw najnowszego elementu, a to jest stos
Przeglądasz dane poziom po poziomie, jak robi to przeszukiwanie wszerzElementy trzeba obsługiwać według priorytetu, a nie kolejności nadejścia; wtedy pasuje kopiec
Producent i konsument działają z różną szybkością i potrzebują bufora między sobąMusisz wyszukiwać w środku danych lub odwoływać się do nich po indeksie
Chcesz wstawiania i usuwania w O(1) bez przesuwania elementówImplementujesz ją przez przesuwanie tablicy przy każdym dequeue, co daje O(n)

Queue: kod

Przejrzysta, gotowa do uruchomienia implementacja algorytmu Queue w językach: Python, JavaScript, Java, C++, C. Wybierz język, skopiuj kod albo otwórz go od razu w edytorze online Coddy.

Queue: kod (Python)

Python
1from collections import deque2
3queue = deque()4
5# Enqueue three values at the rear6for value in [3, 7, 5]:7    queue.append(value)8    print(f"enqueue {value} -> {list(queue)}")9
10# Dequeue them from the front: first in, first out11while queue:12    value = queue.popleft()13    print(f"dequeue {value} -> {list(queue)}")14
15print("empty:", len(queue) == 0)
Uruchom ten kod w edytorze Python online

Kolejka: najczęstsze pytania

Co oznacza FIFO?
First in, first out (pierwszy wszedł, pierwszy wyszedł): następna obsługiwana jest wartość, która czekała najdłużej. Codziennym przykładem jest kolejka do kasy biletowej. Stos działa według odwrotnej zasady, LIFO.
Czym różni się kolejka od stosu?
Tylko tym, z którego końca się usuwa. Oba dodają na końcu w O(1); kolejka usuwa z początku (FIFO), a stos z tego samego końca, na który dodaje (LIFO). Poza tym ich tabele złożoności są identyczne.
Jakie są podstawowe operacje na kolejce?
enqueue dodaje wartość na końcu, dequeue usuwa i zwraca wartość z początku, peek (lub front) odczytuje początek bez usuwania, a is_empty informuje, czy coś czeka. Wszystkie cztery kosztują O(1).
Dlaczego dequeue jest wolne, gdy używam zwykłej tablicy?
Bo usunięcie indeksu 0 z tablicy przesuwa wszystkie pozostałe elementy w lewo, przez co każde dequeue kosztuje O(n). Prawdziwe implementacje unikają tego dzięki buforowi cyklicznemu, który przesuwa indeks początku, albo liście jednokierunkowej ze wskaźnikiem na głowę. collections.deque w Pythonie i ArrayDeque w Javie robią to za ciebie, a list.pop(0) nie.
Czym jest kolejka cykliczna?
To kolejka w tablicy o stałym rozmiarze, w której indeksy początku i końca wracają do 0, gdy dojdą do końca tablicy. Wykorzystuje ponownie pola zwolnione przez dequeue, więc kolejka o pojemności n działa bez końca, zamiast wyjść poza koniec tablicy.
Gdzie kolejki są używane w prawdziwych programach?
W kolejkach zadań i wiadomości między usługami, w buforach wydruku i zadań, w buforach żądań serwerów WWW, w buforach klawiatury i zdarzeń, w potokach producent-konsument oraz w przeszukiwaniu wszerz, gdzie to właśnie kolejka sprawia, że przechodzenie odbywa się poziom po poziomie.
Ilustracja języków programowania w Coddy

Opanuj algorytmy z Coddy

ZACZNIJ