0 added
0 removed
Original
2026-01-01
Modified
2026-03-10
1
<p>В этой статье пойдет разговор о том,<strong>что такое структуры данных</strong>в контексте разработки программного обеспечения. Кроме общих описаний и понятий, попробуем определить<strong>значение</strong>структур данных в программировании. Отдельное внимание будет уделено строению такой популярной структуры данных, как<strong>массив</strong>. Знание некоторых нюансов позволит вам оптимизировать свою работу и обеспечить грамотное применение этой известнейшей и широко используемой структуры данных.</p>
1
<p>В этой статье пойдет разговор о том,<strong>что такое структуры данных</strong>в контексте разработки программного обеспечения. Кроме общих описаний и понятий, попробуем определить<strong>значение</strong>структур данных в программировании. Отдельное внимание будет уделено строению такой популярной структуры данных, как<strong>массив</strong>. Знание некоторых нюансов позволит вам оптимизировать свою работу и обеспечить грамотное применение этой известнейшей и широко используемой структуры данных.</p>
2
<p>Но начать следует с описания<strong>структуры данных</strong>как таковой. Что же определяет это понятие? Если не вдаваться в сложные определения и термины, можно сказать одним простым предложением: структура данных - это не что иное, как<strong>определенный способ организации данных, обеспечивающий максимально эффективное их использование</strong>. Ничего сложного в этом описании нет и быть не может: ведь у нас всегда есть некая информация в цифровом виде, и этой информацией приходится постоянно оперировать. И чтобы использование было эффективным, нужно все это как-то организовать. Как?</p>
2
<p>Но начать следует с описания<strong>структуры данных</strong>как таковой. Что же определяет это понятие? Если не вдаваться в сложные определения и термины, можно сказать одним простым предложением: структура данных - это не что иное, как<strong>определенный способ организации данных, обеспечивающий максимально эффективное их использование</strong>. Ничего сложного в этом описании нет и быть не может: ведь у нас всегда есть некая информация в цифровом виде, и этой информацией приходится постоянно оперировать. И чтобы использование было эффективным, нужно все это как-то организовать. Как?</p>
3
<p>Способы организации данных, как и их структуры, бывают разные. Но мы сейчас не об этом. Лучше задать следующий вопрос: какие основные операции используются разработчиком? Что конкретно приходится выполнять? В реальности определение всех задач можно свести к следующим:</p>
3
<p>Способы организации данных, как и их структуры, бывают разные. Но мы сейчас не об этом. Лучше задать следующий вопрос: какие основные операции используются разработчиком? Что конкретно приходится выполнять? В реальности определение всех задач можно свести к следующим:</p>
4
<ul><li><strong>доступ</strong>(получаем информацию);</li>
4
<ul><li><strong>доступ</strong>(получаем информацию);</li>
5
<li><strong>поиск</strong>(находим информацию);</li>
5
<li><strong>поиск</strong>(находим информацию);</li>
6
<li><strong>вставка</strong>(добавляем новое);</li>
6
<li><strong>вставка</strong>(добавляем новое);</li>
7
<li><strong>удаление</strong>(удаляем ненужное).</li>
7
<li><strong>удаление</strong>(удаляем ненужное).</li>
8
</ul><p>Для выполнения вышеописанных операций существует множество разных структур данных. Какие-то из них более эффективны, какие-то менее. Получить общее представление о связи структур данных с выполняемыми над ними операциями можно на картинке ниже:</p>
8
</ul><p>Для выполнения вышеописанных операций существует множество разных структур данных. Какие-то из них более эффективны, какие-то менее. Получить общее представление о связи структур данных с выполняемыми над ними операциями можно на картинке ниже:</p>
9
<p>Таким образом, современный разработчик должен понимать (и это важно), что существуют не только разные типы, но и разные структуры данных, причем они по-разному эффективны для решения поставленных задач. Поэтому наличие соответствующих знаний позволяет правильно выбирать структуру с учетом предполагаемых операций, времени и сложности, чтобы потом максимально грамотно ее использовать.</p>
9
<p>Таким образом, современный разработчик должен понимать (и это важно), что существуют не только разные типы, но и разные структуры данных, причем они по-разному эффективны для решения поставленных задач. Поэтому наличие соответствующих знаний позволяет правильно выбирать структуру с учетом предполагаемых операций, времени и сложности, чтобы потом максимально грамотно ее использовать.</p>
10
<p>Теперь поговорим о самом "ярком представителе жанра", нередко используемом в ежедневной разработке, причем вне зависимости от того, какой язык программирования вы используете. По определению это<strong>массив</strong>. </p>
10
<p>Теперь поговорим о самом "ярком представителе жанра", нередко используемом в ежедневной разработке, причем вне зависимости от того, какой язык программирования вы используете. По определению это<strong>массив</strong>. </p>
11
<h2><strong>Массив как структура данных</strong></h2>
11
<h2><strong>Массив как структура данных</strong></h2>
12
<p>Для начала посмотрим на основные операции, которые приходится осуществлять с массивом, а также выполним анализ сложности.</p>
12
<p>Для начала посмотрим на основные операции, которые приходится осуществлять с массивом, а также выполним анализ сложности.</p>
13
<p>Представим, что у нас есть следующий массив:</p>
13
<p>Представим, что у нас есть следующий массив:</p>
14
<p>Что вообще с ним можно сделать? Ну, к примеру, получить нужный элемент, обратившись к индексу.</p>
14
<p>Что вообще с ним можно сделать? Ну, к примеру, получить нужный элемент, обратившись к индексу.</p>
15
<p>Какова сложность такой операции? Если вы подумали про O(1), то вы абсолютно правы. В этом случае число операций не растет и является постоянным, что справедливо, по сути, при любых входных значениях.</p>
15
<p>Какова сложность такой операции? Если вы подумали про O(1), то вы абсолютно правы. В этом случае число операций не растет и является постоянным, что справедливо, по сути, при любых входных значениях.</p>
16
<em>График константной функции либо O(1)</em><p>Для сравнения приведем график квадратичной сложности, где разработчика может ожидать резкое увеличение сложности, причем, как порой даже кажется, на ровном месте.</p>
16
<em>График константной функции либо O(1)</em><p>Для сравнения приведем график квадратичной сложности, где разработчика может ожидать резкое увеличение сложности, причем, как порой даже кажется, на ровном месте.</p>
17
<p>Но вернемся к нашей сложности O(1). Разработчик, используя индекс (уникальный идентификатор), может мгновенно получить любой элемент массива, причем даже несуществующий (в таком случае будет undefined). Точно так же по индексу можно выполнять и запись.</p>
17
<p>Но вернемся к нашей сложности O(1). Разработчик, используя индекс (уникальный идентификатор), может мгновенно получить любой элемент массива, причем даже несуществующий (в таком случае будет undefined). Точно так же по индексу можно выполнять и запись.</p>
18
<p>Но в идеале так делать все же обычно не стоит, так как это чревато неприятными последствиями: к примеру, можно получить "дырки" в нашем массиве и другие "радости мутаций". Однако это тема отдельного разговора. Мы же лучше поговорим о методах. Добавим элемент в конец массива:</p>
18
<p>Но в идеале так делать все же обычно не стоит, так как это чревато неприятными последствиями: к примеру, можно получить "дырки" в нашем массиве и другие "радости мутаций". Однако это тема отдельного разговора. Мы же лучше поговорим о методах. Добавим элемент в конец массива:</p>
19
<p>Сложность операции будет тоже O(1).</p>
19
<p>Сложность операции будет тоже O(1).</p>
20
<p>А что насчет удаления с конца?</p>
20
<p>А что насчет удаления с конца?</p>
21
<p>Тут мы тоже имеем O(1). Неплохо. Давайте посмотрим, что у нас получается при добавлении и удалении с начала массива:</p>
21
<p>Тут мы тоже имеем O(1). Неплохо. Давайте посмотрим, что у нас получается при добавлении и удалении с начала массива:</p>
22
<p>А вот здесь несколько иная картина. И вставка, и удаление элементов с начала списка обладают линейной сложностью О(n).</p>
22
<p>А вот здесь несколько иная картина. И вставка, и удаление элементов с начала списка обладают линейной сложностью О(n).</p>
23
<p>А все потому, что при манипуляции элементами из начала списка нам надо обновлять индексы всех последующих элементов. Когда происходит удаление, элемент, который был вторым, должен уже стать первым, а вторым станет третий и так далее. Аналогично и при вставке в начало: надо обновлять индексы всех последующих элементов.</p>
23
<p>А все потому, что при манипуляции элементами из начала списка нам надо обновлять индексы всех последующих элементов. Когда происходит удаление, элемент, который был вторым, должен уже стать первым, а вторым станет третий и так далее. Аналогично и при вставке в начало: надо обновлять индексы всех последующих элементов.</p>
24
<p>Таким образом, это уже менее эффективно. Именно потому разные реализации стеков (stack) основываются не на unshift & shift, а на push & pop. Немного отвлечемся и вспомним про такую структуру данных, как<strong>стек</strong>. Стек можно представить как стопку книг: лежащую сверху мы берем для чтения первой, а если добавляем новую книгу, то кладем ее поверх стопки, то есть теперь уже она становится первой для чтения. Такой подход называют LIFO - last in, first out. Наиболее популярными в разработке являются различные стеки операций, к примеру:</p>
24
<p>Таким образом, это уже менее эффективно. Именно потому разные реализации стеков (stack) основываются не на unshift & shift, а на push & pop. Немного отвлечемся и вспомним про такую структуру данных, как<strong>стек</strong>. Стек можно представить как стопку книг: лежащую сверху мы берем для чтения первой, а если добавляем новую книгу, то кладем ее поверх стопки, то есть теперь уже она становится первой для чтения. Такой подход называют LIFO - last in, first out. Наиболее популярными в разработке являются различные стеки операций, к примеру:</p>
25
<p>- стек изменений в редакторе кода (для получения возможности быстро отменять изменения, возвращаясь к предыдущим состояниям);</p>
25
<p>- стек изменений в редакторе кода (для получения возможности быстро отменять изменения, возвращаясь к предыдущим состояниям);</p>
26
<p>- стек передвижения по веб-страницам в браузере (для обеспечения быстрого перехода по страницам).</p>
26
<p>- стек передвижения по веб-страницам в браузере (для обеспечения быстрого перехода по страницам).</p>
27
<p>Также стоит упомянуть и прочие методы работы с массивами, имеющие сложность О(n) - это, по сути, почти все основные методы, используемые при работе с массивами - всё, что мы ищем, фильтруем, переворачиваем, перебираем и даже трансформируем в строку (toString) - всё вышеперечисленное имеет сложность O(n).</p>
27
<p>Также стоит упомянуть и прочие методы работы с массивами, имеющие сложность О(n) - это, по сути, почти все основные методы, используемые при работе с массивами - всё, что мы ищем, фильтруем, переворачиваем, перебираем и даже трансформируем в строку (toString) - всё вышеперечисленное имеет сложность O(n).</p>
28
<p>На этом все, если хотите знать большое, вам могут быть полезны следующие статьи:</p>
28
<p>На этом все, если хотите знать большое, вам могут быть полезны следующие статьи:</p>
29
<p>- "<a>Структуры и типы данных</a>";</p>
29
<p>- "<a>Структуры и типы данных</a>";</p>
30
<p>- "<a>Топ-8 структур данных для программиста</a>";</p>
30
<p>- "<a>Топ-8 структур данных для программиста</a>";</p>
31
<p>- "<a>Дерево как структура данных. Двоичные деревья</a>".</p>
31
<p>- "<a>Дерево как структура данных. Двоичные деревья</a>".</p>
32
<p><em>Источник: https://dou.ua/lenta/articles/what-you-should-know-about-algorithms/.</em></p>
32
<p><em>Источник: https://dou.ua/lenta/articles/what-you-should-know-about-algorithms/.</em></p>
33
<a></a>
33
<a></a>