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

26.03.2019

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

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

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

Но внезапно древняя цивилизация с многовековой историей исчезла : шумные города опустели, и над ними сомкнулись джунгли.

Код майя

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

Но в 6 веке у Тикаля появился соперник: зашла звезда города под названием .

У майя было два города с сильными правителями: Калакмуль и Тикаль. Между ними происходили конфликты . Как правило, их инициатором был Калакмуль: он постоянно заключал союзы с соседями Тикаля против общего врага.

Икин-Чан-Кавиль и Храм Великого Ягуара

Мощным государством Калакмуль стал благодаря решительному и дальновидному правителю. Звали его Икин-Чан-Кавиль .

Он построил одно из самых известных сооружений майя, эта пирамида пережила века: .

Строительство потребовало огромных усилий. Пирамида был не только храмом, но и символом силы и авторитета правителя : предполагалось, что убедившись в могуществе правителя, люди будут переходить на его сторону.

Строить в тропическом лесу и сегодня непросто, а они строили пирамиды орудиями каменного века. Большинство технологий, которые мы применяем при строительстве крупных сооружений, были неизвестны майя: у них не было тяглового скота , не было орудий из металла .

У майя были лишь практически неисчерпаемые запасы известняка и рабочие руки. Каждый подданный государства был обязан ежегодно отработать на правителя определенное время.

Из каменоломен к месту строительства камень приходилось тащить волоком или нести на спине. Для этого у них были корзины с лямкой, или, как ее еще называют – налобной обвязкой . Таким способом можно было нести десятки килограммов камней.

Ступень за ступенью пирамида росла ввысь. По мере необходимости возводили и переставляли деревянные «леса». Блоки обтесывали каменными резцами и деревянными киянками.

Внутреннюю поверхность стен оставляли необработанной, зато снаружи наводили лоск: обмазывали раствором – так называемой «штукатуркой майя» , и красили в красный цвет.

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

Фасад Храма Великого Ягуара обращен за запад , в сторону заходящего солнца. Храм на главной площади Тикаля был символом власти правителя, оплатившего богам долг народа.

Икин-Чан-Кавиль построил его в честь победы над главным соперником , Калакмулем, в 736 году. Затем в 743-744 годах он нанес поражение союзникам Калакмуля, угрожавшим Тикалю: на запада и на востоке. Петля, сдавливавшая «горло» Тикаля, была разорвана.

В честь этой победы он перестраивает и расширяет дворец, возводит новые пирамиды. Тикаль в нынешнем виде – это, в основном, плоды той победы.

Скорее всего, именно он начал строительство самого высокого сооружения Тикаля храма IV . Пирамида объемом в 200 тысяч кубометров камня высотой в 65 метров с 22-этажный дом. С ее вершины, возвышавшейся над тропическим лесом, открывался великолепный вид на город.

В других городах майя тоже строили высокие сооружения, но в эпоху правления Икин-Чан-Кавиля Тикаль был самым могущественным городом цивилизации майя. Но не единственным.

Загадочный правитель

В 400 километрах к западу еще одна династия строила свой акрополь. В 7 веке там появился незаурядный правитель. Он превратил один из самых влажных городов в мире в «Мекку» архитектуры Нового света.

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

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

Наконец, спустя долгих 3 года, он добирается до основания 25-метровой лестницы. Перед ним небольшой проход и каменный саркофаг с 6 скелетами – останками тех, кого принесли в жертву, чтобы они охраняли того, кто построил этот храм. Но имени этого человека он пока не знает.

И вот, наконец, он видит перед собой дверь – огромный треугольный камень. Вместе с помощниками он открывает дверь и входит внутрь.

Там находится склеп размерами 9 метров в длину и 7 в высоту. А в нем- массивный саркофаг из единого куска известняка с резной крышкой с изображением правителя.

Ее кромка окрашена киноварью – красной краской и смазана ядом против возможных грабителей. Если бы этим способом пользовались египтяне, возможно, до нас дошло бы больше древних сокровищ.

Здесь мы видим изображение щита , такой же щит изображен и в святилище. На языке древних майя щит звучит как «пакаль». Альберто Рус открыл гробницу выдающегося правителя майя – Пакаля Великого .

Пакаль Великий

Открытие Храма надписей изменило наши представления о пирамидах майя: они не были просто усыпальницами.

Помимо лестницы строители провели к гробнице скважину в виде тонкостенной трубы . Через эту трубу любое слово, сказанное на вершине пирамиды, было слышно в склепе. Таким образом, можно было напрямую общаться с Пакалем, лежащим в усыпальнице.

20-тонный саркофаг должен был пережить вечность. Чтобы положить внутрь тело, нужно было сдвинуть крышку в сторону. После смерти Пакаля крышку поставили на месту, замуровали вход и засыпали лестницу.

Камнерезы изобразили на крышке символическую картину возрождения Пакаля в загробном мире. А также своего рода таблицу, в которой поместили 640 иероглифов с повествованием об истории правления Пакаля .

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

В 683 году на 68 году правления в возрасте 80 лет великий правитель майя Пакаль скончался . Тело покрасили киноварью и усыпали драгоценностями. Лиц укрыли нефритовой маской.

Кан-Балам

Пакаль был великим правителем, но его сын терпеливо ждал своей очереди – почти 50 лет.

Надо было успеть совершить что-то великое. На помощь пришли законы физики и матушка Природа.

684 год. Великий правитель Пакаль превратил Паленке в город, каких еще не знала культура майя. После 68 лет у власти его похоронили в гробнице, не уступающей усыпальницам египетских фараонов. Продолжить дело, начатое отцом, предстояло его сыну. Его звали Кан-Балам .

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

48-летний правитель приступил к строительству трех храмов сразу . Этот комплекс увековечил его имя.

Он построил «Группу Креста» — один из самых сложных и изящных храмовых комплексов в истории майя. Его творение возвышалось над дворцом его отца. Есть мнение, что этот комплекс отражает характер его создателя: он хотел оставить о себе память, как хотел и его отец.



Он повелел построить три сооружения: Храм Креста, Храм Лиственного Креста и Храм Солнца .

Система исчисления майя

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



Майя опередили остальное человечество, введя символ для обозначения ноля . Набор из трех символов: ракушки, обозначавшей ноль, точки – единицы, и черты – пятерки в различных комбинациях позволял производить операции с огромными числами.

Греки и римляне были выдающимися инженерами, но их математическая система была ограничена, поскольку не имела ноля. Как ни странно, великие строители, философы по сравнению с майя были никудышными математиками.

Не исключено, что архитекторы Кан-Балана умели извлекать из числа квадратный корень и знали о золотом сечении , пропорции, присущие неживой природе, животным и даже человеку - 1 к 1,618.

Соотношение расстояния от макушки до пупка и от пупка до подошв почти точно соответствует .

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

Возможно, что с помощью одних палок и веревки инженеры Кан-Балама умели извлекать . В Храме Креста к этой пропорции близки пилоны при входе, сами врата и стены внутреннего помещения. Размеры боковых стен и фасадов при виде сверху соотносятся как 1 к 1,618.

Чередование квадратов и прямоугольников создает на полу Храма Креста удивительную геометрическую картину, полную мифологической и исторической символики.

Водоснабжение Паленке

Но не все здания в Паленке строились с расчетом на загробную жизнь, архитекторы думали и о более практичных вещах.

Между 800 и 1050 годом Чичен-Ица становится крупным и сильным городом. Сюда стекались люди со всех концов страны, и он извлекал их этого выгоду.

Караколь – астрономическая обсерватория

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

Скорее всего майя пользовались таким приспособлением, как визир . Наблюдая за прохождением звезд через перекрестие визира, они делали определенные выводы.


Несмотря на примитивные инструменты, майя точно вычисляли движения звезд и планет и ход времени.

Караколь не вписывается в общую планировку города, но отклонение в 27,5 градусов на северо-запад соответствует самой северной позиции Венеры на небе.

Здание ориентировано на небесные тела и явления, а именно: движение Венеры и равноденствие .

. Кажется, что узкие щели расположены в беспорядке, но они точно соответствую астрономическим событиям.

Судя по тому, что пропорции и ориентация Караколя не вписываются в общую планировку, мы можем судить о роли Венеры в представлениях майя.

Венера ведет себя не так, как другие небесные тела, она движется по небу то в одном направлении, то в другом. Видимо, Караколь указывал дни, когда Венера меняет направление движения.

Зная закономерности движения небесных тел, майя создали два взаимосвязанных календаря : ритуальный и солнечный Это были самые точные календари Древнего мира .

Солнечный год майя состоял из 365 дней . Кроме того, они с не меньшей точностью определили периоды обращения Венеры и лунных затмений.

Новая эра расцвета майя

Майя потребовалось всего 200 лет, чтобы возродить пришедшую в упадок на юге цивилизацию. Но, как оказалось, на севере их поджидал не менее страшный враг : он уничтожил культуру майя, оставив города нетронутыми.

В 9 веке н.э. города классического периода майя по непонятной причине пустеют, и начинается новая эра расцвета .

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

Главным сооружением Чичен-Ицы стал , или «Замок», построенный в 9-10 веках н.э.

365 ступеней, по количеству дней года гражданского календаря майя. 52 плиты символизируют 52-летний цикл, а 9 ступеней – 18-месячный цикл солнечного календаря.

Храм ориентирован так, что дважды в год тень от Солнца падает определенным образом. При взгляде на балюстраду и северо-западный угол Эль-Кастильо на закате Солнца можно было наблюдать удивительную игру теней . Освещенные треугольники уступов пирамиды заканчивались у подножья каменной головой змеи. С небес на землю спускался «змей», и это означало наступление сезона дождей.

Майя видели в этом проявлению воли бога , «Оперенного змея».

Майя умели определять – дни, когда продолжительность дня и ночи одинакова. Каждый год 21 марта можно было наблюдать нисхождение Кукулькана.

Планировка города вокруг Эль-Кастильо приобрела новое качество – простор : храмы, рынок, площадка для игры в мяч, колоннады.

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

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

Конструкция колонн проста: цилиндрические барабаны ставили один на другой на прослойку из гравия. Сверху клали квадратную плиту, а кровлю делали деревянной и покрывали известковым раствором.



Теперь происходящее внутри храмов было доступно большему числу людей, нежели в эпоху классических пирамид майя. На те пирамиды поднимались только избранные, храмы ставили на вершине, и снизу не было видно, что в них происходит, а здания с колоннами были более доступны .

Гибель цивилизации майя

Однако, так продолжалось недолго, расцвет Чичен-Ицы длился 200 лет, а затем его постигла судьба южных соседей: она загадочно обезлюдела .

Когда испанцы в 1517 году высадились на Юкатане, все города майя были покинуты и заброшены . Наследники рухнувшей цивилизации жили в разрозненных поселениях, но мужественно сопротивлялись .

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

Воины майя убивали конкистадоров тысячами, но их оружие было бессильно против другого врага: болезни . За 100 лет погибло 90% населения Нового Света. Оставшихся в живых ожидали преследования.

Прибыл из Испании, чтобы обратить майя в христианство, и в своем рвении не знал пощады .

Ланда был идеалистом. Он прибыл в Новый Свет, чтобы спасать души, обращать туземцев в истинную веру. Но майя отнюдь не собирались отказываться от своих верований.

12 июля 1562 года Ланда сжег все рукописи майя , полагая их дьявольскими письменами. Были уничтожены знания, накопленные майя за тысячу лет, для истории это была великая трагедия .

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

Археология майя только начинается

Древние майя пытались найти ответы на вопросы, глядя с земли на небо, а сейчас мы ищем ответы, глядя с неба на землю.

Недавно НАСА и с помощью современных технологий попытались найти новые, неизвестные города майя. Холмы, поросшие лесом, вполне могут оказаться руинами древних городов, заброшенных сотни лет назад. Возможно, разгадка тайн майя лежит у нас под ногами.

Археология майя только начинается : до сих пор не исследовано неимоверное число городов, храмов и прочих сооружений. «Золотой» век археологии майя впереди: к концу века это будет одна из наиболее изученных цивилизаций Древнего мира.

Майя были умны, изобретательны, но отличались склонность к насилию. Чем же так привлекает ученых поколение за поколением это высокоразвитая и вместе с тем загадочная цивилизация? Архитектура величественных дворцов и храмов? Замысловатые иероглифы? Или удивительные познания в астрономии и математике с беспрецедентным для древности понятием ноля? Или же народ, сумевший построить не деревню, не городишко, а великолепные города в одном из самых негостеприимных уголков планеты?

Во влажных тропических лесах между и Юкатаном до сир пор скрыты сотни неизвестных городов майя . Только в одном Паленке до сих пор не раскопано полторы тысячи сооружений. Если представить, какие археологические сокровища ждут ученых в городах, подобных Тикалю и Паленке, становится ясно, что джунгли хранят еще много тайн загадочной цивилизации майя .

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

Кольцевой список

Здесь под структурой понимается способ представления информации, посредством которого совокупность отдельно взятых элементов образует нечто единое, обусловленное их взаимосвязью друг с другом. Скомпонованные по каким-либо правилам и логически связанные межу собой, данные могут весьма эффективно обрабатываться, так как общая для них структура предоставляет набор возможностей управления ими – одно из того за счет чего достигаются высокие результаты в решениях тех или иных задач.

Но не каждый объект представляем в произвольной форме, а возможно и вовсе для него имеется лишь один единственный метод интерпретации, следовательно, несомненным плюсом для программиста будет знание всех существующих структур данных. Таким образом, часто приходиться делать выбор между различными методами хранения информации, и от такого выбора зависит работоспособность продукта.

Говоря о не вычислительной технике, можно показать ни один случай, где у информации видна явная структура. Наглядным примером служат книги самого разного содержания. Они разбиты на страницы, параграфы и главы, имеют, как правило, оглавление, то есть интерфейс пользования ими. В широком смысле, структурой обладает всякое живое существо, без нее органика навряд-ли смогла бы существовать.

Вполне вероятно, читателю приходилось сталкиваться со структурами данных непосредственно в информатике, например, с теми, что встроены в язык программирования. Часто они именуются типами данных. К таковым относятся: массивы, числа, строки, файлы и т. д.

Методы хранения информации, называемые «простыми», т. е. неделимыми на составные части, предпочтительнее изучать вместе с конкретным языком программирования, либо же глубоко углубляться в суть их работы. Поэтому здесь будут рассмотрены лишь «интегрированные» структуры, те которые состоят из простых, а именно: массивы, списки, деревья и графы.

Массивы.

Массив – это структура данных с фиксированным и упорядоченным набором однотипных элементов (компонентов). Доступ к какому-либо из элементов массива осуществляется по имени и номеру (индексу) этого элемента. Количество индексов определяет размерность массива. Так, например, чаще всего встречаются одномерные (вектора) и двумерные (матрицы) массивы.

Первые имеют один индекс, вторые – два. Пусть одномерный массив называется A, тогда для получения доступа к его i-ому элементу потребуется указать название массива и номер требуемого элемента: A[i]. Когда A – матрица, то она представляема в виде таблицы, доступ к элементам которой осуществляется по имени массива, а также номерам строки и столбца, на пересечении которых расположен элемент: A, где i – номер строки, j – номер столбца.

В разных языках программирования работа с массивами может в чем-то различаться, но основные принципы, как правило, везде одни. В языке Pascal, обращение к одномерному и двумерному массиву происходит точно так, как это показано выше, а, например, в C++ двумерный массив следует указывать так: A[i][j]. Элементы массива нумеруются поочередно. На то, с какого значения начинается нумерация, влияет язык программирования. Чаще всего этим значением является 0 или 1.

Массивы, описанного типа называются статическими, но существуют также массивы по определенным признакам отличные от них: динамические и гетерогенные. Динамичность первых характеризуется непостоянностью размера, т. е. по мере выполнения программы размер динамического массива может изменяться. Такая функция делает работу с данными более гибкой, но при этом приходится жертвовать быстродействием, да и сам процесс усложняется.

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

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

Списки.

Список – абстрактный тип данных, реализующий упорядоченный набор значений. Списки отличаются от массивов тем, что доступ к их элементам осуществляется последовательно, в то время как массивы – структура данных произвольного доступа. Данный абстрактный тип имеет несколько реализаций в виде структур данных. Некоторые из них будут рассмотрены здесь.

Список (связный список) – это структура данных, представляющая собой конечное множество упорядоченных элементов, связанных друг с другом посредствам указателей. Каждый элемент структуры содержит поле с какой-либо информацией, а также указатель на следующий элемент. В отличие от массива, к элементам списка нет произвольного доступа.

Односвязный список

В односвязном списке, приведенным выше, начальным элементом является Head list (голова списка [произвольное наименование]), а все остальное называется хвостом. Хвост списка составляют элементы, разделенные на две части: информационную (поле info) и указательную (поле next). В последнем элементе вместо указателя, содержится признак конца списка – nil.

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

Двусвязный список

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

Для двух видов списков описанных выше существует подвид, называемый кольцевым списком. Сделать из односвязного списка кольцевой можно добавив всего лишь один указатель в последний элемент, так чтобы он ссылался на первый. А для двусвязного потребуется два указателя: на первый и последний элементы.

Кольцевой список

Помимо рассмотренных видов списочных структур есть и другие способы организации данных по типу «список», но они, как правило, во многом схожи с разобранными, поэтому здесь они будут опущены.

Кроме различия по связям, списки делятся по методам работы с данными. О некоторых таких методах сказано далее.

Стек.

Стек

Стек характерен тем, что получить доступ к его элементом можно лишь с одного конца, называемого вершиной стека, иначе говоря: стек – структура данных, функционирующая по принципу LIFO (last in - first out, «последним пришёл - первым вышел»). Изобразить эту структуру данных лучше в виде вертикального списка, например, стопки каких-либо вещей, где чтобы воспользоваться одной из них нужно поднять все те вещи, что лежат выше нее, а положить предмет можно лишь на вверх стопки.

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

Очередь.

Структура данных «Очередь» использует принцип организации FIFO (First In, First Out - «первым пришёл - первым вышел»). В некотором смысле такой метод более справедлив, чем тот, по которому функционирует стек, ведь простое правило, лежащее в основе привычных очередей в различные магазины, больницы считается вполне справедливым, а именно оно является базисом этой структуры. Пусть данное наблюдение будет примером. Строго говоря, очередь – это список, добавление элементов в который допустимо, лишь в его конец, а их извлечение производиться с другой стороны, называемой началом списка.


Очередь

Дек

Дек (deque - double ended queue, «двухсторонняя очередь») – стек с двумя концами. Действительно, несмотря конкретный перевод, дек можно определять не только как двухстороннюю очередь, но и как стек, имеющий два конца. Это означает, что данный вид списка позволяет добавлять элементы в начало и в конец, и то же самое справедливо для операции извлечения.


Дек

Эта структура одновременно работает по двум способам организации данных: FIFO и LIFO. Поэтому ее допустимо отнести к отдельной программной единице, полученной в результате суммирования двух предыдущих видов списка.

Графы.

Раздел дискретной математики, занимающийся изучением графов, называется теорией графов. В теории графов подробно рассматриваются известные понятия, свойства, способы представления и области применения этих математических объектов. Нас же интересует, лишь те ее аспекты, которые важны в программировании.

Граф – совокупность точек, соединенных линиями. Точки называются вершинами (узлами), а линии – ребрами (дугами).

Как показано на рисунке различают два основных вида графов: ориентированные и неориентированные. В первых ребра являются направленными, т. е. существует только одно доступное направление между двумя связными вершинами, например из вершины 1 можно пройти в вершину 2, но не наоборот. В неориентированном связном графе из каждой вершины можно пройти в каждую и обратно. Частный случай двух этих видов – смешанный граф. Он характерен наличием как ориентированных, так и неориентированных ребер.

Степень входа вершины – количество входящих в нее ребер, степень выхода – количество исходящих ребер.

Ребра графа необязательно должны быть прямыми, а вершины обозначаться именно цифрами, так как показано на рисунке. К тому же встречаются такие графы, ребрам которых поставлено в соответствие конкретное значение, они именуются взвешенными графами, а это значение – весом ребра. Когда у ребра оба конца совпадают, т. е. ребро выходит из вершины F и входит в нее, то такое ребро называется петлей.

Графы широко используются в структурах, созданных человеком, например в компьютерных и транспортных сетях, web-технологиях. Специальные способы представления позволяют использовать граф в информатике (в вычислительных машинах). Самые известные из них: «Матрица смежности», «Матрица инцидентности», «Список смежности», «Список рёбер». Два первых, как понятно из названия, для репрезентации графа используют матрицу, а два последних – список.

Деревья.

Неупорядоченное дерево

Дерево как математический объект это абстракция из соименных единиц, встречающихся в природе. Схожесть структуры естественных деревьев с графами определенного вида говорит о допущении установления аналогии между ними. А именно со связанными и вместе с этим ациклическими (не имеющими циклов) графами. Последние по своему строению действительно напоминают деревья, но в чем то и имеются различия, например, принято изображать математические деревья с корнем расположенным вверху, т. е. все ветви «растут» сверху вниз. Известно же, что в природе это совсем не так.

Поскольку дерево это по своей сути граф, у него с последним многие определения совпадают, либо интуитивно схожи. Так корневой узел (вершина 6) в структуре дерева – это единственная вершина (узел), характерная отсутствием предков, т. е. такая, что на нее не ссылается ни какая другая вершина, а из самого корневого узла можно дойти до любой из имеющихся вершин дерева, что следует из свойства связности данной структуры. Узлы, не ссылающиеся ни на какие другие узлы, иначе говоря, ни имеющие потомков называются листьями (2, 3, 9), либо терминальными узлами. Элементы, расположенные между корневым узлом и листьями – промежуточные узлы (1, 1, 7, 8). Каждый узел дерева имеет только одного предка, или если он корневой, то не имеет ни одного.

Поддерево – часть дерева, включающая некоторый корневой узел и все его узлы-потомки. Так, например, на рисунке одно из поддеревьев включает корень 8 и элементы 2, 1, 9.

С деревом можно выполнять многие операции, например, находить элементы, удалять элементы и поддеревья, вставлять поддеревья, находить корневые узлы для некоторых вершин и др. Одной из важнейших операций является обход дерева. Выделяются несколько методов обхода. Наиболее популярные из них: симметричный, прямой и обратный обход. При прямом обходе узлы-предки посещаются прежде своих потомков, а в обратном обходе, соответственно, обратная ситуация. В симметричном обходе поочередно просматриваются поддеревья главного дерева.

Представление данных в рассмотренной структуре выгодно в случае наличия у информации явной иерархии. Например, работа с данными о биологических родах и видах, служебных должностях, географических объектах и т. п. требует иерархически выраженной структуры, такой как математические деревья.

Аннотация: Дается общее понятие структуры данных как исполнителя, который организует работу с данными: хранение, добавление и удаление, поиск и т.п. Рассматриваются реализации одних структур на базе других, в частности, реализации на базе массива. Приводятся наиболее важные из простейших структур данных: очередь и стек, а также их непрерывные реализации на базе массива. Даются многочисленные примеры использования стека в программировании. Рассматривается обратная польская запись формулы (знак операции после аргументов) и способ ее вычисления на стековой машине. В качестве примера использования обратной польской записи рассматривается графический язык PostScript. Материал иллюстрируется проектом "Cтековый калькулятор", реализованным на языке Си.

Структуры данных

"Алгоритмы + структуры данных = программы". Это - название книги Никлауса Вирта, знаменитого швейцарского специалиста по программированию, автора языков Паскаль , Модула-2, Оберон. С именем Вирта связано развитие структурного подхода к программированию. Н.Вирт известен также как блестящий педагог и автор классических учебников.

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

Общее понятие структуры данных

Структура данных - это исполнитель , который организует работу с данными, включая их хранение, добавление и удаление, модификацию, поиск и т.д. Структура данных поддерживает определенный порядок доступа к ним. Структуру данных можно рассматривать как своего рода склад или библиотеку. При описании структуры данных нужно перечислить набор действий, которые возможны для нее, и четко описать результат каждого действия. Будем называть такие действия предписаниями . С программной точки зрения, системе предписаний структуры данных соответствует набор функций, которые работают над общими переменными.

Структуры данных удобнее всего реализовывать в объектно-ориентированных языках. В них структуре данных соответствует класс , сами данные хранятся в переменных-членах класса (или доступ к данным осуществляется через переменные-члены), системе предписаний соответствует набор методов класса. Как правило, в объектно-ориентированных языках структуры данных реализуются в виде библиотеки стандартных классов: это так называемые контейнерные классы языка C++, входящие в стандартную библиотеку классов STL , или классы, реализующие различные структуры данных из библиотеки Java Developer Kit языка Java .

Тем не менее, структуры данных столь же успешно можно реализовывать и в традиционных языках программирования, таких как Фортран или Си . При этом следует придерживаться объектно-ориентированного стиля программирования: четко выделить набор функций, которые осуществляют работу со структурой данных, и ограничить доступ к данным только этим набором функций. Сами данные реализуются как статические (не глобальные) переменные. При программировании на языке Си структуре данных соответствуют два файла с исходными текстами:

  1. заголовочный, или h-файл, который описывает интерфейс структуры данных, т.е. набор прототипов функций, соответствующий системе предписаний структуры данных;
  2. файл реализации, или Си-файл, в котором определяются статические переменные, осуществляющие хранение и доступ к данным, а также реализуются функции, соответствующие системе предписаний структуры данных

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

  • Перевод
  • Recovery Mode

Екатерина Малахова, редактор-фрилансер, специально для блога Нетологии адаптировала статью Beau Carnes об основных типах структур данных.

«Плохие программисты думают о коде. Хорошие программисты думают о структурах данных и их взаимосвязях», - Линус Торвальдс, создатель Linux.

Структуры данных играют важную роль в процессе разработки ПО, а еще по ним часто задают вопросы на собеседованиях для разработчиков. Хорошая новость в том, что по сути они представляют собой всего лишь специальные форматы для организации и хранения данных.

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

В статье я привожу примеры реализации этих структур данных на JavaScript: они также пригодятся, если вы используете низкоуровневый язык вроде С. В многие высокоуровневые языки, включая JavaScript, уже встроены реализации большинства структур данных, о которых пойдет речь. Тем не менее, такие знания станут серьезным преимуществом при поиске работы и пригодятся при написании высокопроизводительного кода.

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

Связный список - одна из базовых структур данных. Ее часто сравнивают с массивом, так как многие другие структуры можно реализовать с помощью либо массива, либо связного списка. У этих двух типов есть преимущества и недостатки.

Так устроен связный список

Связный список состоит из группы узлов, которые вместе образуют последовательность. Каждый узел содержит две вещи: фактические данные, которые в нем хранятся (это могут быть данные любого типа) и указатель (или ссылку) на следующий узел в последовательности. Также существуют двусвязные списки: в них у каждого узла есть указатель и на следующий, и на предыдущий элемент в списке.

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

Временная сложность связного списка ╔═══════════╦═════════════════╦═══════════════╗ ║ Алгоритм ║Среднее значение ║ Худший случай ║ ╠═══════════╬═════════════════╬═══════════════╣ ║ Space ║ O(n) ║ O(n) ║ ║ Search ║ O(n) ║ O(n) ║ ║ Insert ║ O(1) ║ O(1) ║ ║ Delete ║ O(1) ║ O(1) ║ ╚═══════════╩═════════════════╩═══════════════╝

Упражнения от freeCodeCamp

Стеки

Стек - это базовая структура данных, которая позволяет добавлять или удалять элементы только в её начале. Она похожа на стопку книг: если вы хотите взглянуть на книгу в середине стека, сперва придется убрать лежащие сверху.

Стек организован по принципу LIFO (Last In First Out, «последним пришёл - первым вышел») . Это значит, что последний элемент, который вы добавили в стек, первым выйдет из него.


Так устроен стек

В стеках можно выполнять три операции: добавление элемента (push), удаление элемента (pop) и отображение содержимого стека (pip).

Временная сложность стека ╔═══════════╦═════════════════╦═══════════════╗ ║ Алгоритм ║Среднее значение ║ Худший случай ║ ╠═══════════╬═════════════════╬═══════════════╣ ║ Space ║ O(n) ║ O(n) ║ ║ Search ║ O(n) ║ O(n) ║ ║ Insert ║ O(1) ║ O(1) ║ ║ Delete ║ O(1) ║ O(1) ║ ╚═══════════╩═════════════════╩═══════════════╝

Упражнения от freeCodeCamp

Очереди

Эту структуру можно представить как очередь в продуктовом магазине. Первым обслуживают того, кто пришёл в самом начале - всё как в жизни.


Так устроена очередь

Очередь устроена по принципу FIFO (First In First Out, «первый пришёл - первый вышел»). Это значит, что удалить элемент можно только после того, как были убраны все ранее добавленные элементы.

Очередь позволяет выполнять две основных операции: добавлять элементы в конец очереди (enqueue ) и удалять первый элемент (dequeue ).

Временная сложность очереди ╔═══════════╦═════════════════╦═══════════════╗ ║ Алгоритм ║Среднее значение ║ Худший случай ║ ╠═══════════╬═════════════════╬═══════════════╣ ║ Space ║ O(n) ║ O(n) ║ ║ Search ║ O(n) ║ O(n) ║ ║ Insert ║ O(1) ║ O(1) ║ ║ Delete ║ O(1) ║ O(1) ║ ╚═══════════╩═════════════════╩═══════════════╝

Упражнения от freeCodeCamp

Множества



Так выглядит множество

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

  • Объединение комбинирует все элементы из двух разных множеств, превращая их в одно (без дубликатов).
  • Пересечение анализирует два множества и  создает еще одно из тех элементов, которые присутствуют в обоих изначальных множествах.
  • Разность выводит список элементов, которые есть в одном множестве, но отсутствуют в другом.
  • Подмножество выдает булево значение, которое показывает, включает ли одно множество все элементы другого множества.
Пример реализации на JavaScript

Упражнения от freeCodeCamp

Map

Map - это структура, которая хранит данные в парах ключ/значение, где каждый ключ уникален. Иногда её также называют ассоциативным массивом или словарём. Map часто используют для быстрого поиска данных. Она позволяет делать следующие вещи:
  • добавлять пары в коллекцию;
  • удалять пары из коллекции;
  • изменять существующей пары;
  • искать значение, связанное с определенным ключом.

Так устроена структура map

Упражнения от freeCodeCamp

Хэш-таблицы

Так работают хэш-таблица и хэш-функция

Хэш-таблица - это похожая на Map структура, которая содержит пары ключ/значение. Она использует хэш-функцию для вычисления индекса в массиве из блоков данных, чтобы найти желаемое значение.

Обычно хэш-функция принимает строку символов в качестве вводных данных и выводит числовое значение. Для одного и того же ввода хэш-функция должна возвращать одинаковое число. Если два разных ввода хэшируются с одним и тем же итогом, возникает коллизия. Цель в том, чтобы таких случаев было как можно меньше.

Таким образом, когда вы вводите пару ключ/значение в хэш-таблицу, ключ проходит через хэш-функцию и превращается в число. В дальнейшем это число используется как фактический ключ, который соответствует определенному значению. Когда вы снова введёте тот же ключ, хэш-функция обработает его и вернет такой же числовой результат. Затем этот результат будет использован для поиска связанного значения. Такой подход заметно сокращает среднее время поиска.

Временная сложность хэш-таблицы ╔═══════════╦═════════════════╦═══════════════╗ ║ Алгоритм ║Среднее значение ║ Худший случай ║ ╠═══════════╬═════════════════╬═══════════════╣ ║ Space ║ O(n) ║ O(n) ║ ║ Search ║ O(1) ║ O(n) ║ ║ Insert ║ O(1) ║ O(n) ║ ║ Delete ║ O(1) ║ O(n) ║ ╚═══════════╩═════════════════╩═══════════════╝

Упражнения от freeCodeCamp

Двоичное дерево поиска


Двоичное дерево поиска

Дерево - это структура данных, состоящая из узлов. Ей присущи следующие свойства:

  • Каждое дерево имеет корневой узел (вверху).
  • Корневой узел имеет ноль или более дочерних узлов.
  • Каждый дочерний узел имеет ноль или более дочерних узлов, и так далее.
У двоичного дерева поиска есть два дополнительных свойства:
  • Каждый узел имеет до двух дочерних узлов (потомков).
  • Каждый узел меньше своих потомков справа, а его потомки слева меньше его самого.
Двоичные деревья поиска позволяют быстро находить, добавлять и удалять элементы. Они устроены так, что время каждой операции пропорционально логарифму общего числа элементов в дереве.

Временная сложность двоичного дерева поиска ╔═══════════╦═════════════════╦══════════════╗ ║ Алгоритм ║Среднее значение ║Худший случай ║ ╠═══════════╬═════════════════╬══════════════╣ ║ Space ║ O(n) ║ O(n) ║ ║ Search ║ O(log n) ║ O(n) ║ ║ Insert ║ O(log n) ║ O(n) ║ ║ Delete ║ O(log n) ║ O(n) ║ ╚═══════════╩═════════════════╩══════════════╝


Упражнения от freeCodeCamp

Префиксное дерево

Префиксное (нагруженное) дерево - это разновидность дерева поиска. Оно хранит данные в метках, каждая из которых представляет собой узел на дереве. Такие структуры часто используют, чтобы хранить слова и выполнять быстрый поиск по ним - например, для функции автозаполнения.

Так устроено префиксное дерево

Каждый узел в языковом префиксном дереве содержит одну букву слова. Чтобы составить слово, нужно следовать по ветвям дерева, проходя по одной букве за раз. Дерево начинает ветвиться, когда порядок букв отличается от других имеющихся в нем слов или когда слово заканчивается. Каждый узел содержит букву (данные) и булево значение, которое указывает, является ли он последним в слове.

Посмотрите на иллюстрацию и попробуйте составить слова. Всегда начинайте с корневого узла вверху и спускайтесь вниз. Это дерево содержит следующие слова: ball, bat, doll, do, dork, dorm, send, sense.

Упражнения от freeCodeCamp

Двоичная куча

Двоичная куча - ещё одна древовидная структура данных. В ней у каждого узла не более двух потомков. Также она является совершенным деревом: это значит, что в ней полностью заняты данными все уровни, а последний заполнен слева направо.


Так устроены минимальная и максимальная кучи

Двоичная куча может быть минимальной или максимальной. В максимальной куче ключ любого узла всегда больше ключей его потомков или равен им. В минимальной куче всё устроено наоборот: ключ любого узла меньше ключей его потомков или равен им.

Порядок уровней в двоичной куче важен, в отличие от порядка узлов на одном и том же уровне. На иллюстрации видно, что в минимальной куче на третьем уровне значения идут не по порядку: 10, 6 и 12.


Временная сложность двоичной кучи ╔═══════════╦══════════════════╦═══════════════╗ ║ Алгоритм ║ Среднее значение ║ Худший случай ║ ╠═══════════╬══════════════════╬═══════════════╣ ║ Space ║ O(n) ║ O(n) ║ ║ Search ║ O(n) ║ O(n) ║ ║ Insert ║ O(1) ║ O(log n) ║ ║ Delete ║ O(log n) ║ O(log n) ║ ║ Peek ║ O(1) ║ O(1) ║ ╚═══════════╩══════════════════╩═══════════════╝

Упражнения от freeCodeCamp

Граф

Графы - это совокупности узлов (вершин) и связей между ними (рёбер). Также их называют сетями.

Графы делятся на два основных типа: ориентированные и неориентированные. У неориентированных графов рёбра между узлами не имеют какого-либо направления, тогда как у рёбер в ориентированных графах оно есть.

Чаще всего граф изображают в каком-либо из двух видов: это может быть список смежности или матрица смежности.


Граф в виде матрицы смежности

Список смежности можно представить как перечень элементов, где слева находится один узел, а справа - все остальные узлы, с которыми он соединяется.

Матрица смежности - это сетка с числами, где каждый ряд или колонка соответствуют отдельному узлу в графе. На пересечении ряда и колонки находится число, которое указывает на наличие связи. Нули означают, что она отсутствует; единицы - что связь есть. Чтобы обозначить вес каждой связи, используют числа больше единицы.

Существуют специальные алгоритмы для просмотра рёбер и вершин в графах - так называемые алгоритмы обхода. К их основным типам относят поиск в ширину (breadth-first search ) и в глубину (depth-first search ). Как вариант, с их помощью можно определить, насколько близко к корневому узлу находятся те или иные вершины графа. В видео ниже показано, как на JavaScript выполнить поиск в ширину.