Stos (stack)

  • Informatyka
  • struktura danych LIFO
  • operacje stosu
  • push pop peek
  • implementacja stosu
  • zastosowania stosu
  • stack overflow underflow

Podcast

Stos i Kolejka: Porządki w Danych0:00 / 10:04
0:001:00 pozostało

Stos, znany również jako stack w informatyce, to jedna z najbardziej fundamentalnych i intuicyjnych abstrakcyjnych struktur danych. Można go sobie wyobrazić jako stos talerzy: aby dodać nowy talerz, kładziemy go na wierzchu istniejącego stosu. Aby zdjąć talerz, zawsze bierzemy ten, który leży na samej górze. Ta prosta analogia doskonale oddaje kluczową zasadę działania stosu: LIFO (Last In, First Out), co oznacza „ostatni wszedł, pierwszy wyszedł”. Element, który został dodany do stosu jako ostatni, będzie pierwszym, który zostanie z niego usunięty.

Stos (Stack) – Co To Jest i Jak Działa?

Stos to struktura danych, w której elementy są dodawane i usuwane z jednego końca, zwanego wierzchołkiem. Dzięki temu działa on na zasadzie LIFO (Last In, First Out), co czyni go niezwykle użytecznym w wielu algorytmach i aplikacjach programistycznych. Zrozumienie jego mechaniki jest kluczowe dla każdego programisty.

Zasada Działania LIFO (Last In, First Out)

Zasada LIFO jest sercem stosu. Wyobraź sobie kolejkę do kasy w sklepie. Zwykła kolejka działa na zasadzie FIFO (First In, First Out – pierwszy wszedł, pierwszy wyszedł), gdzie osoba, która przyszła pierwsza, jest obsługiwana jako pierwsza. Stos działa odwrotnie. Jeśli wyobrazimy sobie stos książek, to książka, którą położyliśmy na samym końcu, jest tą, którą najłatwiej i najszybciej możemy zdjąć. Aby dostać się do książek położonych niżej, musimy najpierw zdjąć te, które leżą na nich. Ta specyficzna kolejność dostępu do danych sprawia, że stos jest niezwykle użyteczny w wielu algorytmach i aplikacjach.

Podstawowe Operacje na Stosie – push, pop, peek

Stos obsługuje dwie główne operacje, które definiują jego funkcjonalność:

Operacja Push (wstawienie na stos)

Operacja push służy do dodawania nowego elementu na wierzch stosu. Kiedy wykonujemy push, nowy element staje się nowym wierzchołkiem stosu. Jeśli stos jest pełny (co ma znaczenie w niektórych implementacjach), próba dodania elementu spowoduje błąd nazywany przepełnieniem stosu (stack overflow).

Operacja Pop (usunięcie ze stosu)

Operacja pop służy do usuwania elementu z wierzchu stosu. Zawsze usuwany jest element, który został dodany jako ostatni. Po usunięciu elementu, poprzedni element staje się nowym wierzchołkiem. Jeśli stos jest pusty, próba usunięcia elementu spowoduje błąd nazywany niedomiarem stosu (stack underflow).

Operacja Peek / Top (podgląd wierzchołka stosu)

Operacja Peek (lub Top) zwraca wartość elementu znajdującego się na wierzchu stosu, ale go nie usuwa. Jest to przydatne, gdy chcemy sprawdzić, co jest na górze, bez modyfikowania stosu.

Operacja IsEmpty (sprawdzenie, czy stos jest pusty)

Operacja IsEmpty sprawdza, czy stos nie zawiera żadnych elementów. Zwraca wartość logiczną prawda, jeśli stos jest pusty, i fałsz w przeciwnym razie.

Operacja IsFull (sprawdzenie, czy stos jest pełny)

Operacja IsFull sprawdza, czy stos osiągnął swoją maksymalną pojemność. Jest to istotne w implementacjach o stałym rozmiarze, np. z użyciem tablicy.

Sprawdź, co już wiesz

Test · 20 pytań · pierwsze 3 za darmo

Pytanie 1 z 30%

Materiały zawierają szczegółowy przykład implementacji operacji `peek` dla stosu opartego na tablicy.

Przećwicz to na fiszkach

15 fiszek · pierwsze 3 za darmo, bez konta

1 / 15

Czym jest stos w informatyce?

Stos to abstrakcyjna struktura danych działająca na zasadzie LIFO (Last In, First Out).

Dotknij, aby odwrócić · Przesuń, aby nawigować

Implementacja Stosu za Pomocą Tablicy (tablica Stosu)

Jedną z najprostszych i najczęściej spotykanych metod implementacji stosu jest użycie tablicy (lub listy w niektórych językach programowania). W tej implementacji, tablica przechowuje elementy stosu, a specjalny wskaźnik (często nazywany top lub wierzchołek) śledzi indeks ostatnio dodanego elementu, czyli wierzchołka stosu. Załóżmy, że mamy tablicę tablicaStosu o maksymalnym rozmiarze N i zmienną wierzchołek, która początkowo ma wartość -1 (oznacza to pusty stos).

Jak działa push(element) w tablicowej implementacji stosu?

  1. Sprawdź, czy wierzchołek jest mniejszy niż N-1. Jeśli nie, stos jest pełny (przepełnienie).
  2. Zwiększ wierzchołek o 1 (wierzchołek = wierzchołek + 1).
  3. Umieść element w tablicaStosu[wierzchołek].

Jak działa pop() w tablicowej implementacji stosu?

  1. Sprawdź, czy wierzchołek jest większy lub równy 0. Jeśli nie, stos jest pusty (niedomiar).
  2. Pobierz element z tablicaStosu[wierzchołek].
  3. Zmniejsz wierzchołek o 1 (wierzchołek = wierzchołek - 1).
  4. Zwróć pobrany element.

Jak działa peek() w tablicowej implementacji stosu?

  1. Sprawdź, czy wierzchołek jest większy lub równy 0. Jeśli nie, stos jest pusty.
  2. Zwróć tablicaStosu[wierzchołek].

Jak działa isEmpty() w tablicowej implementacji stosu?

  1. Zwróć prawda, jeśli wierzchołek jest równy -1. W przeciwnym razie zwróć fałsz.

Złożoność Czasowa Operacji na Stosie (O(1))

Jedną z kluczowych zalet stosu jest jego efektywność. Wszystkie podstawowe operacje – push, pop i peek – mają stałą złożoność czasową, oznaczaną jako O(1). Oznacza to, że czas potrzebny na wykonanie tych operacji jest niezależny od liczby elementów znajdujących się na stosie. Niezależnie od tego, czy stos zawiera jeden element, czy milion, dodanie lub usunięcie elementu z wierzchołka zawsze zajmuje mniej więcej tyle samo czasu. Jest to możliwe, ponieważ operacje te zawsze dotyczą tylko jednego, konkretnego miejsca w pamięci (wierzchołka stosu), bez konieczności przeszukiwania czy przesuwania innych elementów.

Przykłady Działania Stosu – Sekwencja Operacji

Rozważmy pusty stos, na którym wykonujemy sekwencję operacji, aby zobaczyć, jak zmienia się jego zawartość i wierzchołek:

  1. push(10): Stos: [10] (wierzchołek: 10)
  2. push(20): Stos: [10, 20] (wierzchołek: 20)
  3. push(30): Stos: [10, 20, 30] (wierzchołek: 30)
  4. pop(): Zwraca 30. Stos: [10, 20] (wierzchołek: 20)
  5. push(40): Stos: [10, 20, 40] (wierzchołek: 40)
  6. peek(): Zwraca 40. Stos: [10, 20, 40] (wierzchołek: 40)
  7. pop(): Zwraca 40. Stos: [10, 20] (wierzchołek: 20)
  8. pop(): Zwraca 20. Stos: [10] (wierzchołek: 10)
  9. pop(): Zwraca 10. Stos: [] (pusty)
  10. pop(): Błąd: niedomiar stosu (stack underflow).

Najczęstsze Błędy i Pułapki Przy Używaniu Stosu

Podczas pracy ze stosami studenci często popełniają kilka typowych błędów, które mogą prowadzić do nieprawidłowego działania programów:

Próba dostępu do elementów innych niż wierzchołek stosu

Stos z definicji pozwala na dostęp tylko do elementu na wierzchołku. Próba odczytania lub modyfikacji elementu znajdującego się głębiej w stosie jest niezgodna z jego zasadą działania i może prowadzić do błędów logicznych lub naruszeń bezpieczeństwa pamięci w niektórych implementacjach.

Wykonanie pop na pustym stosie (niedomiar)

Jest to bardzo częsty błąd. Zawsze należy sprawdzić, czy stos nie jest pusty przed próbą usunięcia z niego elementu. W przeciwnym razie program może się zawiesić lub zwrócić nieprzewidywalne wyniki.

Wykonanie push na pełnym stosie (przepełnienie)

W implementacjach stosu o stałym rozmiarze (np. z użyciem tablicy o z góry określonej wielkości) próba dodania elementu do pełnego stosu spowoduje przepełnienie. Należy zawsze sprawdzić, czy jest wolne miejsce przed dodaniem elementu.

Mylenie LIFO z FIFO

Czasami studenci mylą stos z kolejką, która działa na zasadzie FIFO (First In, First Out). Ważne jest, aby pamiętać o odmiennej kolejności dostępu do danych w stosie (LIFO).

Zastosowania Stosu w Praktyce Informatyki

Stosy są wszechobecne w informatyce i mają wiele praktycznych zastosowań, od codziennych aplikacji po fundamentalne mechanizmy działania systemów:

Funkcja Cofania (Undo/Redo) w programach

W edytorach tekstu, programach graficznych czy systemach operacyjnych, funkcja „cofnij” (undo) jest często implementowana za pomocą stosu. Każda wykonana akcja jest „wpychana” na stos. Gdy użytkownik wybiera „cofnij”, ostatnia akcja jest „ściągana” ze stosu i jej efekt jest odwracany. Podobnie działa „ponów” (redo), często z użyciem drugiego stosu.

Historia Przeglądania w Przeglądarkach Internetowych

Przycisk „Wstecz” w przeglądarce internetowej działa na zasadzie stosu. Każda odwiedzona strona jest dodawana na stos. Kiedy klikamy „Wstecz”, przeglądarka pobiera ostatnio odwiedzoną stronę ze stosu i wyświetla ją.

Zarządzanie Wywołaniami Funkcji (Stos Wywołań)

Kiedy program wykonuje funkcję, a ta funkcja wywołuje inną funkcję, system operacyjny używa stosu (tzw. stosu wywołań) do zarządzania tymi wywołaniami. Adres powrotu, zmienne lokalne i parametry funkcji są „wpychane” na stos, gdy funkcja jest wywoływana. Kiedy funkcja kończy działanie, te dane są „ściągane” ze stosu, a program wraca do miejsca, z którego funkcja została wywołana. Jest to kluczowe dla działania rekurencji.

Sprawdzanie Poprawności Nawiasów w wyrażeniach

W językach programowania, wyrażeniach matematycznych czy plikach konfiguracyjnych często używa się nawiasów (okrągłych (), kwadratowych [], klamrowych {}) do grupowania elementów. Stos może być użyty do sprawdzenia, czy nawiasy są poprawnie zagnieżdżone i sparowane. Algorytm polega na tym, że gdy napotkamy nawias otwierający, wpychamy go na stos. Gdy napotkamy nawias zamykający, ściągamy element ze stosu i sprawdzamy, czy jest to odpowiadający mu nawias otwierający. Jeśli stos jest pusty na końcu lub nawiasy nie pasują, wyrażenie jest niepoprawne.

Przykład sprawdzania nawiasów:

Rozważmy wyrażenie ({[a+b]*c}):

  1. ( : push (
  2. { : push {
  3. [ : push [
  4. a, +, b, *, c: ignoruj (nie są nawiasami)
  5. ] : pop [. Pasuje. Stos: ( {
  6. } : pop {. Pasuje. Stos: (
  7. ) : pop (. Pasuje. Stos: [] (pusty)

Na końcu stos jest pusty, więc nawiasy są poprawne.

Co Obserwować i Wypróbować w Symulacji Stosu (Stack)

Interaktywna symulacja stosu pozwoli na lepsze zrozumienie jego działania. Podczas korzystania z symulacji zwróć uwagę na następujące aspekty:

  • Wizualizacja LIFO: Obserwuj, jak elementy są dodawane i usuwane. Zauważ, że nowy element zawsze pojawia się na samej górze stosu, a usuwany jest zawsze ten, który jest na górze. Animacja operacji push pokaże, jak element „wskakuje” na wierzchołek, a animacja pop – jak element „wyskakuje” z wierzchołka. To bezpośrednio ilustruje zasadę LIFO.
  • Stan wierzchołka: Śledź wskaźnik wierzchołka stosu. Zobacz, jak zmienia się jego pozycja po każdej operacji push (zwiększa się) i pop (zmniejsza się).
  • Puste i pełne stany: Spróbuj wykonać operację pop na pustym stosie. Symulacja powinna wyraźnie zasygnalizować błąd niedomiaru. Podobnie, jeśli symulacja ma ograniczony rozmiar stosu, spróbuj dodać zbyt wiele elementów, aby zobaczyć, jak reaguje na przepełnienie.
  • Sekwencje operacji: Wykonaj różne sekwencje operacji push i pop, aby utrwalić zrozumienie, jak zmienia się zawartość stosu. Na przykład, dodaj kilka elementów, usuń jeden, dodaj kolejny, a następnie usuń wszystkie. Obserwuj, w jakiej kolejności elementy są zwracane.
  • Operacja peek: Jeśli symulacja oferuje operację peek, użyj jej, aby zobaczyć, że element na wierzchołku jest pokazywany, ale nie jest usuwany ze stosu, co odróżnia ją od pop.

Symulacja jest doskonałym narzędziem do eksperymentowania i wizualnego potwierdzenia teoretycznych założeń dotyczących stosu. Pozwala na praktyczne zrozumienie, dlaczego stos jest tak efektywną i użyteczną strukturą danych w informatyce.

FAQ: Stos (Stack) – Najczęściej Zadawane Pytania

Czym różni się stos od kolejki?

Stos (stack) działa na zasadzie LIFO (Last In, First Out), co oznacza, że ostatnio dodany element jest pierwszym, który zostanie usunięty. Kolejka natomiast działa na zasadzie FIFO (First In, First Out), gdzie pierwszy dodany element jest pierwszym usuwanym, podobnie jak w zwykłej kolejce do kasy.

Jakie są podstawowe operacje na stosie?

Podstawowe operacje na stosie to push (dodanie elementu na wierzch), pop (usunięcie elementu z wierzchołka) oraz peek (odczytanie elementu z wierzchołka bez jego usuwania). Często spotyka się też operacje isEmpty (sprawdzenie, czy stos jest pusty) i isFull (sprawdzenie, czy stos jest pełny).

Co to jest niedomiar stosu (stack underflow) i przepełnienie stosu (stack overflow)?

Niedomiar stosu (stack underflow) to błąd, który występuje, gdy próbujesz usunąć element (pop) z pustego stosu. Przepełnienie stosu (stack overflow) to błąd, który występuje, gdy próbujesz dodać element (push) do stosu, który osiągnął swoją maksymalną pojemność, np. w przypadku implementacji stosu o stałym rozmiarze.

Czy stos jest efektywną strukturą danych?

Tak, stos jest bardzo efektywną strukturą danych. Wszystkie podstawowe operacje (push, pop, peek) mają stałą złożoność czasową O(1). Oznacza to, że czas ich wykonania jest niezależny od liczby elementów na stosie, co czyni stos szybkim i wydajnym dla wielu zastosowań.

Przećwicz to, nie tylko przeczytaj

15 fiszek, test z wyjaśnieniami i podcast do tego tematu. Konto jest darmowe i zaczynasz tam, gdzie skończyłeś.

  • Bez karty płatniczej
  • Strona i aplikacja mobilna
  • 330 000+ uczniów
Zacznij za darmo

Powiązane tematy