JavaRush /Курсы /Модуль 1: Python Core /Основные термины и определения

Основные термины и определения

Модуль 1: Python Core
15 уровень , 2 лекция
Открыта

3.1 Операции над данными: вставка, удаление, поиск

Вставка (Insert):

Операция добавления нового элемента в структуру данных. Вставка может происходить в начале, в конце или в произвольной позиции структуры данных.

Удаление (Delete):

Операция удаления элемента из структуры данных. Удаление может происходить по значению элемента, по индексу или по позиции элемента в структуре данных.

Поиск (Search):

Операция нахождения элемента в структуре данных. Поиск может происходить по значению или по другим критериям.

Примеры операций:

  • Массивы: Вставка и удаление требуют сдвига элементов, что может быть затратным по времени — O(n).
  • Связные списки: Вставка и удаление могут происходить за O(1), если известна позиция узла.
  • Хеш-таблицы: Поиск, вставка и удаление обычно выполняются за O(1) в среднем случае.
  • Деревья: Операции поиска, вставки и удаления могут выполняться за O(log n) в сбалансированных деревьях.

3.2 Базовые понятия: массив, список, стек, очередь

Массив

Массив — это последовательность элементов одного типа, к которым можно получить доступ по индексу.

Сложность операций: Доступ по индексу — O(1), вставка и удаление — O(n).

Пример: Создание массива, изменение элемента и вывод результата


# Создаём массив чисел
arr = [1, 2, 3, 4, 5]

# Изменяем элемент с индексом 2 (третий элемент, так как индексация начинается с 0)
arr[2] = 10

# Выводим изменённый массив
print(arr)  # Вывод: [1, 2, 10, 4, 5]

# Добавляем новый элемент в конец массива
arr.append(6)
print(arr)  # Вывод: [1, 2, 10, 4, 5, 6]

# Удаляем элемент по индексу
del arr[1]
print(arr)  # Вывод: [1, 10, 4, 5, 6]

Список

Список — это коллекция элементов, где каждый элемент содержит ссылку на следующий (односвязный список) или на следующий и предыдущий (двусвязный список) элемент.

Сложность операций: Вставка и удаление — O(1) при известной позиции, поиск — O(n).

Пример: Создание простого односвязного списка и его обход


# Определяем структуру узла списка
class Node:
    def __init__(self, data):
        self.data = data
        self.next = None

# Создаём односвязный список
node1 = Node("101")
node2 = Node("102")
node3 = Node("103")

# Связываем узлы
node1.next = node2
node2.next = node3

# Устанавливаем начало списка
list_head = node1

# Проходим по списку и выводим данные
current = list_head
while current:
    print(current.data)
    current = current.next

# Вывод:
# 101
# 102
# 103

Стек (Stack)

Стек — это коллекция элементов с принципом LIFO (Last In, First Out): последний добавился — первый вышел.

Сложность операций: Вставка (push) и удаление (pop)O(1).

Пример: Реализация и использование стека для проверки сбалансированности скобок


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

# Проверяем различные выражения
print(is_balanced("({[]})"))  # Вывод: True
print(is_balanced("([)]"))    # Вывод: False
print(is_balanced("(("))      # Вывод: False

Очередь (Queue)

Очередь — это коллекция элементов с принципом FIFO (First In, First Out): первый добавился — первый вышел.

Сложность операций: Вставка (enqueue) и удаление (dequeue)O(1).

Пример: Реализация и использование очереди для симуляции обработки задач


from collections import deque

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

    def add_task(self, task):
        self.queue.append(task)
        print(f"Задача '{task}' добавлена в очередь")

    def process_task(self):
        if self.queue:
            task = self.queue.popleft()
            print(f"Обработка задачи: '{task}'")
        else:
            print("Очередь пуста")

    def display_queue(self):
        print("Текущая очередь задач:", list(self.queue))

# Создаём и используем очередь задач
task_queue = TaskQueue()

task_queue.add_task("Отправить email")
task_queue.add_task("Обновить базу данных")
task_queue.add_task("Создать отчёт")

task_queue.display_queue()

task_queue.process_task()
task_queue.process_task()

task_queue.display_queue()

# Вывод:
# Задача 'Отправить email' добавлена в очередь
# Задача 'Обновить базу данных' добавлена в очередь
# Задача 'Создать отчёт' добавлена в очередь
# Текущая очередь задач: ['Отправить email', 'Обновить базу данных', 'Создать отчёт']
# Обработка задачи: 'Отправить email'
# Обработка задачи: 'Обновить базу данных'
# Текущая очередь задач: ['Создать отчёт']

3.3 Отличия между различными типами структур данных

Вот ключевые отличия между различными типами структур данных:

Массивы:

  • Доступ: Быстрый доступ по индексу — O(1).
  • Изменение размера: Фиксированный размер, увеличение требует копирования всех элементов — O(n).
  • Подходит для: Случайного доступа к элементам, когда размер данных известен заранее.

Связные списки:

  • Доступ: Медленный доступ по индексу — O(n).
  • Изменение размера: Легко изменяемый размер, вставка и удаление занимают O(1).
  • Подходит для: Частого добавления и удаления элементов.

Стек:

  • Принцип работы: LIFO.
  • Операции: Вставка и удаление только на одном конце — O(1).
  • Подходит для: Обратного порядка выполнения задач, управления вызовами функций.

Очередь:

  • Принцип работы: FIFO.
  • Операции: Вставка и удаление на разных концах — O(1).
  • Подходит для: Управления задачами в порядке их поступления.

3.4 Применение различных структур данных

Примеры применения различных структур данных на практике:

Массивы

Хранение данных фиксированной длины, таких как дни недели или месяцы в году.

Пример: Использование массива для работы с днями недели


# Создаём массив с днями недели
days = ["Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота", "Воскресенье"]

# Получаем день недели по индексу (например, третий день)
print(days[2])  # Вывод: Среда

# Изменяем название дня
days[0] = "Понедельник (начало недели)"
print(days[0])  # Вывод: Понедельник (начало недели)

# Проходим по всем дням недели
for day in days:
    print(day)

# Вывод:
# Понедельник (начало недели)
# Вторник
# Среда
# Четверг
# Пятница
# Суббота
# Воскресенье

Связные списки

Реализация динамических коллекций, где элементы могут добавляться и удаляться из середины коллекции.

Пример: Реализация и использование связного списка для хранения списка дел


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("Список дел пуст")
        else:
            while current:
                print(f"- {current.task}")
                current = current.next

# Создаём и используем список дел
todo = TodoList()
todo.add_task("Купить продукты")
todo.add_task("Позвонить маме")
todo.add_task("Подготовить презентацию")

print("Мой список дел:")
todo.display_tasks()

# Вывод:
# Мой список дел:
# - Купить продукты
# - Позвонить маме
# - Подготовить презентацию

Стек

Обратный порядок выполнения задач, например, обработка вызовов функций в рекурсии, отмена операций (undo).

Пример: Использование стека для обращения строки


def reverse_string(s):
    stack = []
    # Помещаем каждый символ строки в стек
    for char in s:
        stack.append(char)
    
    reversed_s = ''
    # Извлекаем символы из стека, формируя обратную строку
    while stack:
        reversed_s += stack.pop()
    
    return reversed_s

# Пример использования
original = "Hello, World!"
reversed_str = reverse_string(original)
print(f"Оригинальная строка: {original}")
print(f"Обращённая строка: {reversed_str}")

# Вывод:
# Оригинальная строка: Hello, World!
# Обращённая строка: !dlroW ,olleH

Очередь

Управление задачами в порядке их поступления, например, задания на принтере, очереди в обслуживании клиентов.

Пример: Симуляция очереди печати документов


from collections import deque

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

    def add_document(self, document):
        self.queue.append(document)
        print(f"Документ '{document}' добавлен в очередь печати")

    def print_document(self):
        if self.queue:
            document = self.queue.popleft()
            print(f"Печать документа: '{document}'")
        else:
            print("Очередь печати пуста")

    def display_queue(self):
        print("Текущая очередь печати:", list(self.queue))

# Создаём и используем очередь печати
printer = PrinterQueue()
printer.add_document("Отчёт")
printer.add_document("Презентация")
printer.add_document("Договор")
printer.display_queue()
printer.print_document()
printer.print_document()
printer.display_queue()

# Вывод:
# Документ 'Отчёт' добавлен в очередь печати
# Документ 'Презентация' добавлен в очередь печати
# Документ 'Договор' добавлен в очередь печати
# Текущая очередь печати: ['Отчёт', 'Презентация', 'Договор']
# Печать документа: 'Отчёт'
# Печать документа: 'Презентация'
# Текущая очередь печати: ['Договор']

В этом примере мы создали простую симуляцию очереди печати. Документы добавляются в конец очереди и печатаются в порядке их поступления, что демонстрирует принцип FIFO (First In, First Out).

Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ