CodeGym /Kursy /Python SELF PL /Podstawowe terminy i definicje

Podstawowe terminy i definicje

Python SELF PL
Poziom 51 , Lekcja 2
Dostępny

3.1 Operacje na danych: wstawianie, usuwanie, wyszukiwanie

Wstawianie (Insert):

Operacja dodawania nowego elementu do struktury danych. Wstawianie może mieć miejsce na początku, na końcu lub w dowolnej pozycji w strukturze danych.

Usuwanie (Delete):

Operacja usuwania elementu ze struktury danych. Usuwanie może odbywać się poprzez wartość elementu, indeks lub pozycję elementu w strukturze danych.

Wyszukiwanie (Search):

Operacja znajdowania elementu w strukturze danych. Wyszukiwanie może odbywać się poprzez wartość lub inne kryteria.

Przykłady operacji:

  • Tablice: Wstawianie i usuwanie wymagają przesunięcia elementów, co może być czasochłonne — O(n).
  • Listy połączone: Wstawianie i usuwanie mogą odbywać się za O(1), jeśli znana jest pozycja węzła.
  • Tabele haszujące: Wyszukiwanie, wstawianie i usuwanie zwykle wykonuje się za O(1) w średnim przypadku.
  • Drzewa: Operacje wyszukiwania, wstawiania i usuwania mogą być wykonywane za O(log n) w zrównoważonych drzewach.

3.2 Podstawowe pojęcia: tablica, lista, stos, kolejka

Tablica

Tablica — to sekwencja elementów jednego typu, do których można uzyskać dostęp przez indeks.

Złożoność operacji: Dostęp przez indeks — O(1), wstawianie i usuwanie — O(n).

Przykład: Tworzenie tablicy, zmiana elementu i wyświetlenie wyniku


# Tworzymy tablicę liczb
arr = [1, 2, 3, 4, 5]

# Zmieniamy element z indeksem 2 (trzeci element, bo indeksowanie zaczyna się od 0)
arr[2] = 10

# Wyświetlamy zmienioną tablicę
print(arr)  # Wyjście: [1, 2, 10, 4, 5]

# Dodajemy nowy element na koniec tablicy
arr.append(6)
print(arr)  # Wyjście: [1, 2, 10, 4, 5, 6]

# Usuwamy element po indeksie
del arr[1]
print(arr)  # Wyjście: [1, 10, 4, 5, 6]

Lista

Lista — to kolekcja elementów, gdzie każdy element zawiera odnośnik do następnego (lista jednokierunkowa) lub do następnego i poprzedniego (lista dwukierunkowa) elementu.

Złożoność operacji: Wstawianie i usuwanie — O(1) przy znanej pozycji, wyszukiwanie — O(n).

Przykład: Tworzenie prostej listy jednokierunkowej i jej przegląd


# Definiujemy strukturę węzła listy
class Node:
    def __init__(self, data):
        self.data = data
        self.next = None

# Tworzymy listę jednokierunkową
node1 = Node("101")
node2 = Node("102")
node3 = Node("103")

# Łączymy węzły
node1.next = node2
node2.next = node3

# Ustawiamy początek listy
list_head = node1

# Przechodzimy przez listę i wyświetlamy dane
current = list_head
while current:
    print(current.data)
    current = current.next

# Wyjście:
# 101
# 102
# 103

Stos (Stack)

Stos — to kolekcja elementów z zasadą LIFO (Last In, First Out): ostatni wszedł — pierwszy wyszedł.

Złożoność operacji: Wstawianie (push) i usuwanie (pop) — O(1).

Przykład: Implementacja i użycie stosu do sprawdzania zbalansowania nawiasów


def is_balanced(expression):
    stack = []
    opening = "({["
    closing = ")}]"
    pairs = {")": "(", "}": "{", "]": "["}
    
    for char in expression:
        if char in opening:
            stack.append(char)
        elif char in closing:
            if not stack or stack.pop() != pairs[char]:
                return False
    
    return len(stack) == 0

# Sprawdzamy różne wyrażenia
print(is_balanced("({[]})"))  # Wyjście: True
print(is_balanced("([)]"))    # Wyjście: False
print(is_balanced("(("))      # Wyjście: False

Kolejka (Queue)

Kolejka — to kolekcja elementów z zasadą FIFO (First In, First Out): pierwszy wszedł — pierwszy wyszedł.

Złożoność operacji: Wstawianie (enqueue) i usuwanie (dequeue) — O(1).

Przykład: Implementacja i użycie kolejki do symulacji przetwarzania zadań


from collections import deque

class TaskQueue:
    def __init__(self):
        self.queue = deque()

    def add_task(self, task):
        self.queue.append(task)
        print(f"Zadanie '{task}' dodane do kolejki")

    def process_task(self):
        if self.queue:
            task = self.queue.popleft()
            print(f"Przetwarzanie zadania: '{task}'")
        else:
            print("Kolejka jest pusta")

    def display_queue(self):
        print("Obecna kolejka zadań:", list(self.queue))

# Tworzymy i używamy kolejki zadań
task_queue = TaskQueue()

task_queue.add_task("Wysłać email")
task_queue.add_task("Zaktualizować bazę danych")
task_queue.add_task("Stworzyć raport")

task_queue.display_queue()

task_queue.process_task()
task_queue.process_task()

task_queue.display_queue()

# Wyjście:
# Zadanie 'Wysłać email' dodane do kolejki
# Zadanie 'Zaktualizować bazę danych' dodane do kolejki
# Zadanie 'Stworzyć raport' dodane do kolejki
# Obecna kolejka zadań: ['Wysłać email', 'Zaktualizować bazę danych', 'Stworzyć raport']
# Przetwarzanie zadania: 'Wysłać email'
# Przetwarzanie zadania: 'Zaktualizować bazę danych'
# Obecna kolejka zadań: ['Stworzyć raport']

3.3 Różnice między różnymi typami struktur danych

Oto kluczowe różnice między różnymi typami struktur danych:

Tablice:

  • Dostęp: Szybki dostęp przez indeks — O(1).
  • Zmiana rozmiaru: Stały rozmiar, zwiększenie wymaga kopiowania wszystkich elementów — O(n).
  • Odpowiedni dla: Losowego dostępu do elementów, gdy rozmiar danych jest znany z góry.

Listy połączone:

  • Dostęp: Wolny dostęp przez indeks — O(n).
  • Zmiana rozmiaru: Łatwo zmieniany rozmiar, wstawianie i usuwanie zajmują O(1).
  • Odpowiedni dla: Częstego dodawania i usuwania elementów.

Stos:

  • Zasada działania: LIFO.
  • Operacje: Wstawianie i usuwanie tylko na jednym końcu — O(1).
  • Odpowiedni dla: Odwrotnego porządku wykonywania zadań, zarządzania wywołaniami funkcji.

Kolejka:

  • Zasada działania: FIFO.
  • Operacje: Wstawianie i usuwanie na różnych końcach — O(1).
  • Odpowiedni dla: Zarządzania zadaniami w kolejności ich przyjścia.

3.4 Zastosowanie różnych struktur danych

Przykłady zastosowania różnych struktur danych w praktyce:

Tablice

Przechowywanie danych o ustalonej długości, takich jak dni tygodnia czy miesiące w roku.

Przykład: Użycie tablicy do pracy z dniami tygodnia


# Tworzymy tablicę z dniami tygodnia
days = ["Poniedziałek", "Wtorek", "Środa", "Czwartek", "Piątek", "Sobota", "Niedziela"]

# Uzyskujemy dzień tygodnia po indeksie (np. trzeci dzień)
print(days[2])  # Wyjście: Środa

# Zmieniamy nazwę dnia
days[0] = "Poniedziałek (początek tygodnia)"
print(days[0])  # Wyjście: Poniedziałek (początek tygodnia)

# Przechodzimy przez wszystkie dni tygodnia
for day in days:
    print(day)

# Wyjście:
# Poniedziałek (początek tygodnia)
# Wtorek
# Środa
# Czwartek
# Piątek
# Sobota
# Niedziela

Listy połączone

Implementacja dynamicznych kolekcji, gdzie elementy mogą być dodawane i usuwane z środka kolekcji.

Przykład: Implementacja i użycie listy połączonej do przechowywania listy zadań


class TodoItem:
    def __init__(self, task):
        self.task = task
        self.next = None

class TodoList:
    def __init__(self):
        self.head = None

    def add_task(self, task):
        new_item = TodoItem(task)
        if not self.head:
            self.head = new_item
        else:
            current = self.head
            while current.next:
                current = current.next
            current.next = new_item

    def display_tasks(self):
        current = self.head
        if not current:
            print("Lista zadań jest pusta")
        else:
            while current:
                print(f"- {current.task}")
                current = current.next

# Tworzymy i używamy listy zadań
todo = TodoList()
todo.add_task("Kupić produkty")
todo.add_task("Zadzwonić do mamy")
todo.add_task("Przygotować prezentację")

print("Moja lista zadań:")
todo.display_tasks()

# Wyjście:
# Moja lista zadań:
# - Kupić produkty
# - Zadzwonić do mamy
# - Przygotować prezentację

Stos

Odwrotny porządek wykonywania zadań, na przykład przetwarzanie wywołań funkcji w rekurencji, cofanie operacji (undo).

Przykład: Użycie stosu do odwracania łańcucha znaków


def reverse_string(s):
    stack = []
    # Umieszczamy każdy znak łańcucha na stosie
    for char in s:
        stack.append(char)
    
    reversed_s = ''
    # Wyciągamy znaki ze stosu, tworząc odwrotny łańcuch
    while stack:
        reversed_s += stack.pop()
    
    return reversed_s

# Przykład użycia
original = "Hello, World!"
reversed_str = reverse_string(original)
print(f"Łańcuch oryginalny: {original}")
print(f"Łańcuch odwrotny: {reversed_str}")

# Wyjście:
# Łańcuch oryginalny: Hello, World!
# Łańcuch odwrotny: !dlroW ,olleH

Kolejka

Zarządzanie zadaniami w kolejności ich przyjścia, na przykład zadania na drukarce, kolejki w obsłudze klienta.

Przykład: Symulacja kolejki drukowania dokumentów


from collections import deque

class PrinterQueue:
    def __init__(self):
        self.queue = deque()

    def add_document(self, document):
        self.queue.append(document)
        print(f"Dokument '{document}' dodany do kolejki drukowania")

    def print_document(self):
        if self.queue:
            document = self.queue.popleft()
            print(f"Drukowanie dokumentu: '{document}'")
        else:
            print("Kolejka drukowania jest pusta")

    def display_queue(self):
        print("Obecna kolejka drukowania:", list(self.queue))

# Tworzymy i używamy kolejki drukowania
printer = PrinterQueue()
printer.add_document("Raport")
printer.add_document("Prezentacja")
printer.add_document("Umowa")
printer.display_queue()
printer.print_document()
printer.print_document()
printer.display_queue()

# Wyjście:
# Dokument 'Raport' dodany do kolejki drukowania
# Dokument 'Prezentacja' dodany do kolejki drukowania
# Dokument 'Umowa' dodany do kolejki drukowania
# Obecna kolejka drukowania: ['Raport', 'Prezentacja', 'Umowa']
# Drukowanie dokumentu: 'Raport'
# Drukowanie dokumentu: 'Prezentacja'
# Obecna kolejka drukowania: ['Umowa']

W tym przykładzie stworzyliśmy prostą symulację kolejki drukowania. Dokumenty są dodawane na koniec kolejki i drukowane w kolejności ich przyjścia, co demonstruje zasadę FIFO (First In, First Out).

Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION