Начнём с холодильника
Прежде чем мы дойдём до страшных слов вроде «Big-O» и «массив», давайте договоримся об одной простой вещи. Структура данных — это не код. Это способ хранить вещи так, чтобы ими было удобно пользоваться. И вы пользуетесь структурами данных каждый день, просто не называете их так.
Представьте, что вы собрались в магазин. Вы можете держать список покупок в голове: «молоко, хлеб, яйца, сыр». А можете записать его на бумажку. Бумажка со списком — это уже структура данных. У неё есть свойства: пункты идут по порядку, можно вычеркнуть купленное, можно дописать новый пункт в конец.
А теперь представьте кухонную полку со специями. Это тоже способ хранить вещи — но другой. На полке у каждой банки есть своё место. Вы не «листаете» полку сверху вниз, чтобы найти соль, — вы сразу тянетесь к нужному месту, потому что помните, где она стоит.
Список на бумажке и полка со специями — это две разные структуры данных. И главная идея всего курса вот в чём: разные способы хранения данных удобны для разных задач. Список удобно дописывать. С полки удобно сразу брать нужное по «адресу». Когда вы выбираете структуру данных в программе, вы выбираете, что именно вам будет удобно и быстро, а что — медленно и больно.
Что значит «структура» в слове «структура данных»
Слово «данные» здесь означает просто «вещи, которые мы храним»: числа, имена, цены, строки текста. А «структура» — это как именно они разложены и какие действия с ними удобны.
Сравните два способа хранить телефоны друзей.
- В куче на столе валяются бумажки, на каждой имя и номер. Чтобы найти телефон Ани, вы перебираете бумажки одну за другой, пока не наткнётесь на нужную.
- В записной книжке с алфавитными вкладками вы открываете букву «А» и сразу находите Аню.
Данные одинаковые — телефоны друзей. А структура разная. И от структуры зависит, сколько усилий уйдёт на поиск. Это и есть суть: структура данных определяет, насколько легко делать с данными то, что вам нужно.
Списки в Python
В Python самая первая структура данных, с которой вы знакомитесь, — это список (по-английски list). Список похож на ту самую бумажку с покупками: пункты идут по порядку, и каждый можно достать.
покупки = ["молоко", "хлеб", "яйца", "сыр"]
print(покупки)
print("Всего пунктов:", len(покупки))
Вывод:
['молоко', 'хлеб', 'яйца', 'сыр']
Всего пунктов: 4
Список хранит элементы по порядку. У каждого элемента есть номер места — он называется индекс. И вот здесь важная деталь: в программировании счёт начинается не с единицы, а с нуля. Первый элемент имеет индекс 0, второй — индекс 1, и так далее.
покупки = ["молоко", "хлеб", "яйца", "сыр"]
print(покупки[0]) # самый первый
print(покупки[1]) # второй
print(покупки[3]) # четвёртый, последний
Вывод:
молоко
хлеб
яйца
сыр
Обращение по индексу покупки[0] — это как «взять банку с третьей полки». Вы не перебираете весь список с начала, вы сразу указываете место и забираете элемент. Почему это работает мгновенно — мы разберём в следующем уроке, когда поговорим про память. Пока просто запомните: достать элемент по индексу — это очень быстро, как протянуть руку к нужной полке.
Что со списком можно делать
Список — гибкая структура. Как и в бумажном списке покупок, в него можно дописывать пункты, убирать их и менять.
покупки = ["молоко", "хлеб"]
покупки.append("яйца") # дописать в конец
print(покупки)
покупки[0] = "кефир" # заменить первый пункт
print(покупки)
последний = покупки.pop() # снять последний пункт
print("Сняли:", последний)
print(покупки)
Вывод:
['молоко', 'хлеб', 'яйца']
['кефир', 'хлеб', 'яйца']
Сняли: яйца
['кефир', 'хлеб']
Метод append дописывает элемент в конец — ровно как вы дописываете «яйца» в конец бумажки. Это удобно и быстро. А вот вставить пункт в середину списка — уже сложнее: представьте, что вам нужно втиснуть строчку между первой и второй на плотно исписанной бумажке. Придётся всё, что ниже, сдвинуть вниз. В программе это тоже стоит усилий, и об этом мы поговорим в следующих модулях.
Слово «массив» — почти то же самое
В книжках по программированию вы будете часто встречать слово массив (по-английски array). Пока считайте, что массив — это близкий родственник списка: упорядоченный набор элементов, к которым можно обращаться по индексу.
В чистом виде массив устроен немного строже, чем список Python (в нём обычно лежат данные одного типа и заранее известного размера), но идея та же — «полка с пронумерованными местами». Список Python внутри устроен на основе массива, и весь следующий модуль курса будет про то, как именно. Пока достаточно интуиции: массив и список — это упорядоченные «полки с номерами мест».
Примечание: разница между «массивом» и «списком» в разных языках своя. В Python вы почти всегда работаете со списком (
list). Слово «массив» приберегите для разговоров про устройство внутри — туда мы и движемся.
Почему это важно для всего курса
Может показаться: «ну список и список, что тут изучать». Но именно выбор структуры данных решает, будет ли ваша программа работать за секунду или за час. Список покупок удобен для одного, полка со специями — для другого. В программировании структур больше: списки, словари, множества, очереди, деревья. Каждая хороша для своих задач.
Весь этот курс — про то, чтобы вы научились выбирать правильную структуру под задачу и понимали, почему одна работает быстро, а другая медленно. Начинаем с самого простого — со списка, потому что он ближе всего к интуиции «бумажки с пунктами».
Структура данных — это способ хранить вещи так, чтобы ими было удобно пользоваться. Список Python — это упорядоченная «бумажка с пунктами»: элементы идут по порядку, у каждого есть номер места (индекс, считаем с нуля), достать по индексу — мгновенно.
Попробуй сам
Создайте свой список — например, список любимых блюд. Затем:
блюда = ["паста", "плов", "борщ"]
# 1. Выведите первый и последний элемент по индексу
print(блюда[0])
print(блюда[2])
# 2. Допишите ещё одно блюдо в конец
блюда.append("окрошка")
print(блюда)
# 3. Замените второй элемент на другое блюдо
блюда[1] = "ризотто"
print(блюда)
Вывод:
паста
борщ
['паста', 'плов', 'борщ', 'окрошка']
['паста', 'ризотто', 'борщ', 'окрошка']
Поэкспериментируйте: что выведет блюда[10]? (Подсказка: индекса 10 не существует — Python сообщит об ошибке IndexError. Это нормально, так вы узнаёте границы списка.)
В следующем уроке разберёмся, почему достать элемент по индексу так быстро — и для этого заглянем внутрь памяти компьютера. Без страшных слов, на пальцах.