Разное

Дерево пустое: Бинарные деревья поиска и рекурсия – это просто / Хабр

пустое дерево — это… Что такое пустое дерево?



пустое дерево
мат. empty tree

Большой англо-русский и русско-английский словарь.
2001.

  • пустое высказывание
  • пустое коническое сечение

Смотреть что такое «пустое дерево» в других словарях:

  • Дерево Фибоначчи — АВЛ дерево с наименьшим числом вершин при заданной высоте (глубине). Если для какой либо из вершин высота поддерева, для которого эта вершина является корнем, равна , то правое и левое поддерево этой вершины имеют высоты равные соответственно и …   Википедия

  • Дерево суффиксов — Суффиксное дерево  способ организации данных (строк), позволяющий выяснять, входит ли строка w в строку t, за время O(|w|), где |w|  длина строки w. Содержание 1 Основные определения и описание структуры 2 Свойства суффиксных д …   Википедия

  • ПУСТОЕ ПОЛЕ — см. Движения глаз, Пуркинье дерево. Большой психологический словарь. М.: Прайм ЕВРОЗНАК. Под ред. Б.Г. Мещерякова, акад. В.П. Зинченко. 2003 …   Большая психологическая энциклопедия

  • Суффиксное дерево — Суффиксное дерево  бор, содержащий все суффиксы некоторой строки (и только их). Позволяет выяснять, входит ли строка w в исходную строку t, за время O(|w|), где |w|  длина строки w. Содержание 1 Основные определения и описание структуры …   Википедия

  • Двоичное дерево поиска — Тип Дерево Временная сложность в О символике В среднем В худшем случае Расход памяти O(n) O(n) Поиск O(h) O(n) Вставка O(h) O(n) Удаление O(h) O(n) где h высота дерева …   Википедия

  • Броселианд — Долина без возврата в лесу Броселианд Броселианд (фр. Brocéliande, брет …   Википедия

  • смоква — см’оква плод смоковничного дерева (смоковницы), широко распространенного в Палестине и до настоящего времени. Нам этот плод известен как инжир. Смоковница высокое и тенистое дерево, листья его широкие, густые. Именно из этих листьев сделали себе… …   Библия. Ветхий и Новый заветы. Синодальный перевод. Библейская энциклопедия арх. Никифора.

  • смоква — см’оква плод смоковничного дерева (смоковницы), широко распространенного в Палестине и до настоящего времени. Нам этот плод известен как инжир. Смоковница высокое и тенистое дерево, листья его широкие, густые. Именно из этих листьев сделали себе… …   Полный и подробный Библейский Словарь к русской канонической Библии

  • Стубель — левый приток Горыни, на Волыни, Стубла – правый приток Стыри; связано с сербск. цслав. стубль источник , болг. стубел пустое дерево, сруб колодца , стублица деревянное корыто, из которого поят скотину , сербохорв. сту̀блина колода, выдолбленное… …   Этимологический словарь русского языка Макса Фасмера

  • заскорузлый — за(с)корузлый (о руках), напр. у Мельникова; укр. закорузлий наряду с закорублий – то же; восходит к болг. коруба дуплистое, пустое дерево, дупло , согласно Мi. ЕW (132) и Бернекеру (1, 577). Далее ср. кора …   Этимологический словарь русского языка Макса Фасмера

  • заскорузлый — за(с)корузлый (о руках), напр. у Мельникова; укр. закорузлий наряду с закорублий – то же; восходит к болг. коруба дуплистое, пустое дерево, дупло , согласно Мi. ЕW (132) и Бернекеру (1, 577). Далее ср. кора …   Этимологический словарь русского языка Макса Фасмера

Сонник Дерево огромное пустое внутри. К чему снится Дерево огромное пустое внутри видеть во сне

Отражает самоощущение человека.

Ствол олицетворяет место человека в обществе.

Листва – взаимоотношения с другими людьми.

Корни отражают стабильность и серьезность цели.

Кора – символ вашей уязвимости или защиты.

Лес, несколько деревьев представляют группу людей, семью.

Дерево с зеленой пышной кроной – к благополучию, дружеской поддержке.

Сухие, без листьев деревья – к трудностям, одиночеству.

Плодовые деревья – прибыль, достаток.

Цветущие деревья – любовь, чувства.

Сухие ветви – отмершие чувства и отношения.

Поврежденная кора – кто-то воспользуется вашим доверием.

Дрова, бревна – умершие или давно забытые люди чем-то напомнят о себе.

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

Выделим отдельные характеристики дерева. Посмотрим, что они говорят сновидцу.

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

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

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

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

А что, если вам снится пень? Этот знак не страшен (если дерево не ломалось на ваших глазах). Скорее всего, данный сон подчеркивает, что вы, как обычно, проявите консервативность в делах и отношениях, не примите перемен, обещанных сновидением.

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

Ветви, свисающие вниз, показывают, что вам, вероятно, не хватит энергии решить возникшие задачи.

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

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

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

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

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

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

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

Древо жизни — это символическая ось мира. Значение этого Древа в том, что оно объединяет такие разные стихии как воздух, земля и вода, т. е. те элементы, которые необходимы для существования всего живого на земле.

Древо жизни часто изображается в виде креста, увитого листьями. Но жизнь человека неотделима и от Древа познания. Это Древо «искушает» человека как плодами добра, так и зла. История грехопадения Адама и Евы связана с этим Древом.

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

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

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

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

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

Если восхождение на гору — скорее, символ материального роста, то влезание на дерево — переход на новый духовный уровень.

В древних ритуалах использовалось такое действие, как влезание на шест.

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

пустое дерево — это… Что такое пустое дерево?



пустое дерево

Mathematics: empty tree

Универсальный русско-английский словарь.
Академик.ру.
2011.

  • пустое дело!
  • пустое задание

Смотреть что такое «пустое дерево» в других словарях:

  • Дерево Фибоначчи — АВЛ дерево с наименьшим числом вершин при заданной высоте (глубине). Если для какой либо из вершин высота поддерева, для которого эта вершина является корнем, равна , то правое и левое поддерево этой вершины имеют высоты равные соответственно и …   Википедия

  • Дерево суффиксов — Суффиксное дерево  способ организации данных (строк), позволяющий выяснять, входит ли строка w в строку t, за время O(|w|), где |w|  длина строки w. Содержание 1 Основные определения и описание структуры 2 Свойства суффиксных д …   Википедия

  • ПУСТОЕ ПОЛЕ — см. Движения глаз, Пуркинье дерево. Большой психологический словарь. М.: Прайм ЕВРОЗНАК. Под ред. Б.Г. Мещерякова, акад. В.П. Зинченко. 2003 …   Большая психологическая энциклопедия

  • Суффиксное дерево — Суффиксное дерево  бор, содержащий все суффиксы некоторой строки (и только их). Позволяет выяснять, входит ли строка w в исходную строку t, за время O(|w|), где |w|  длина строки w. Содержание 1 Основные определения и описание структуры …   Википедия

  • Двоичное дерево поиска — Тип Дерево Временная сложность в О символике В среднем В худшем случае Расход памяти O(n) O(n) Поиск O(h) O(n) Вставка O(h) O(n) Удаление O(h) O(n) где h высота дерева …   Википедия

  • Броселианд — Долина без возврата в лесу Броселианд Броселианд (фр. Brocéliande, брет …   Википедия

  • смоква — см’оква плод смоковничного дерева (смоковницы), широко распространенного в Палестине и до настоящего времени. Нам этот плод известен как инжир. Смоковница высокое и тенистое дерево, листья его широкие, густые. Именно из этих листьев сделали себе… …   Библия. Ветхий и Новый заветы. Синодальный перевод. Библейская энциклопедия арх. Никифора.

  • смоква — см’оква плод смоковничного дерева (смоковницы), широко распространенного в Палестине и до настоящего времени. Нам этот плод известен как инжир. Смоковница высокое и тенистое дерево, листья его широкие, густые. Именно из этих листьев сделали себе… …   Полный и подробный Библейский Словарь к русской канонической Библии

  • Стубель — левый приток Горыни, на Волыни, Стубла – правый приток Стыри; связано с сербск. цслав. стубль источник , болг. стубел пустое дерево, сруб колодца , стублица деревянное корыто, из которого поят скотину , сербохорв. сту̀блина колода, выдолбленное… …   Этимологический словарь русского языка Макса Фасмера

  • заскорузлый — за(с)корузлый (о руках), напр. у Мельникова; укр. закорузлий наряду с закорублий – то же; восходит к болг. коруба дуплистое, пустое дерево, дупло , согласно Мi. ЕW (132) и Бернекеру (1, 577). Далее ср. кора …   Этимологический словарь русского языка Макса Фасмера

  • заскорузлый — за(с)корузлый (о руках), напр. у Мельникова; укр. закорузлий наряду с закорублий – то же; восходит к болг. коруба дуплистое, пустое дерево, дупло , согласно Мi. ЕW (132) и Бернекеру (1, 577). Далее ср. кора …   Этимологический словарь русского языка Макса Фасмера

Предложения со словосочетанием ПУСТЫЕ ДЕРЕВЯННЫЕ ЯЩИКИ

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

Увы! От тех и других не осталось никакого другого следа, кроме пустого деревянного ящика. Сомнений не оставалось: мы имели дело с грабежом.

Усевшись на пустой деревянный ящик из-под овощей, инженер заговорил.

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

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




Привет! Меня зовут Лампобот, я компьютерная программа, которая помогает делать
Карту слов. Я отлично
умею считать, но пока плохо понимаю, как устроен ваш мир. Помоги мне разобраться!

Спасибо! Я обязательно научусь отличать широко распространённые слова от узкоспециальных.


Насколько понятно значение слова ремонтный (прилагательное):

Кристально
понятно

Понятно
в общих чертах

Могу только
догадываться

Понятия не имею,
что это

Другое
Пропустить

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

А когда открыла их, то увидела перед собой просторные, заваленные пустыми деревянными ящиками из-под рассады сени.

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

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

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

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

В углу стояли пустые деревянные ящики для картофеля , поставленные друг на друга.

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

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

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

Вокруг высились горы пустых деревянных ящиков и всякий мусор.

Вокруг костра на обломках мебели и пустых деревянных ящиках сидели странного вида люди.

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

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

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

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

Рядом валялся пустой деревянный ящик.

Запасной выход просто завалили пустыми деревянными ящиками.

Во дворе крайне сосредоточенный молодой человек со светлыми всклокоченными волосами старательно пытался сложить горкой пустые деревянные ящики.

Села чуть в сторонке на пустой деревянный ящик из-под патронов.

– Почти, – отвечает гномиха вытаскивая своего товарища из-под горы пустых деревянных ящиков из под патронов. – Спасибо за заботу.

Проехала тележка с пустыми деревянными ящиками и парой турнепсов.

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

Удар получился сильный и болезненный, но я не выпустил из лёгких воздух, и к потолку класса мгновенно поднялся новый звук – БУМ! – будто кто стукнул большим молотком по пустому деревянному ящику.

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

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

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

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

В кузове друзья нашли пустые деревянные ящики с предупреждающими надписями «Осторожно», «Опасный груз», «Взрывоопасно».

Пустые деревянные ящики валяются вокруг станин, я хватаю со стопки всё новые и новые.

пустое дерево — с английского на русский

См. также в других словарях:

  • Дерево Фибоначчи — АВЛ дерево с наименьшим числом вершин при заданной высоте (глубине). Если для какой либо из вершин высота поддерева, для которого эта вершина является корнем, равна , то правое и левое поддерево этой вершины имеют высоты равные соответственно и …   Википедия

  • Дерево суффиксов — Суффиксное дерево  способ организации данных (строк), позволяющий выяснять, входит ли строка w в строку t, за время O(|w|), где |w|  длина строки w. Содержание 1 Основные определения и описание структуры 2 Свойства суффиксных д …   Википедия

  • ПУСТОЕ ПОЛЕ — см. Движения глаз, Пуркинье дерево. Большой психологический словарь. М.: Прайм ЕВРОЗНАК. Под ред. Б.Г. Мещерякова, акад. В.П. Зинченко. 2003 …   Большая психологическая энциклопедия

  • Суффиксное дерево — Суффиксное дерево  бор, содержащий все суффиксы некоторой строки (и только их). Позволяет выяснять, входит ли строка w в исходную строку t, за время O(|w|), где |w|  длина строки w. Содержание 1 Основные определения и описание структуры …   Википедия

  • Двоичное дерево поиска — Тип Дерево Временная сложность в О символике В среднем В худшем случае Расход памяти O(n) O(n) Поиск O(h) O(n) Вставка O(h) O(n) Удаление O(h) O(n) где h высота дерева …   Википедия

  • Броселианд — Долина без возврата в лесу Броселианд Броселианд (фр. Brocéliande, брет …   Википедия

  • смоква — см’оква плод смоковничного дерева (смоковницы), широко распространенного в Палестине и до настоящего времени. Нам этот плод известен как инжир. Смоковница высокое и тенистое дерево, листья его широкие, густые. Именно из этих листьев сделали себе… …   Библия. Ветхий и Новый заветы. Синодальный перевод. Библейская энциклопедия арх. Никифора.

  • смоква — см’оква плод смоковничного дерева (смоковницы), широко распространенного в Палестине и до настоящего времени. Нам этот плод известен как инжир. Смоковница высокое и тенистое дерево, листья его широкие, густые. Именно из этих листьев сделали себе… …   Полный и подробный Библейский Словарь к русской канонической Библии

  • Стубель — левый приток Горыни, на Волыни, Стубла – правый приток Стыри; связано с сербск. цслав. стубль источник , болг. стубел пустое дерево, сруб колодца , стублица деревянное корыто, из которого поят скотину , сербохорв. сту̀блина колода, выдолбленное… …   Этимологический словарь русского языка Макса Фасмера

  • заскорузлый — за(с)корузлый (о руках), напр. у Мельникова; укр. закорузлий наряду с закорублий – то же; восходит к болг. коруба дуплистое, пустое дерево, дупло , согласно Мi. ЕW (132) и Бернекеру (1, 577). Далее ср. кора …   Этимологический словарь русского языка Макса Фасмера

  • заскорузлый — за(с)корузлый (о руках), напр. у Мельникова; укр. закорузлий наряду с закорублий – то же; восходит к болг. коруба дуплистое, пустое дерево, дупло , согласно Мi. ЕW (132) и Бернекеру (1, 577). Далее ср. кора …   Этимологический словарь русского языка Макса Фасмера

Лекция: Деревья — Студопедия

Данная лекция будет посвящена изучению и реализации на Прологе такой структуры данных, как деревья .
Начнем с маленького введения из теории графов , частным случаем которых являются деревья .
Обычно графом называют пару множеств: множество вершин и множество дуг (множество пар из множества вершин).Различают ориентированные и неориентированные графы . В ориентированном графе каждая дуга имеет направление (рассматриваются упорядоченные пары вершин). Графически обычно принято изображать вершины графа точками, а связи между ними — линиями, соединяющими точки-вершины.
Путем называется последовательность вершин, соединенных дугами. Для ориентированного графа направление пути должно совпадать с направлением каждой дуги, принадлежащей пути . Циклом называется путь , у которого совпадают начало и конец.
Две вершины ориентированного графа , соединенные дугой, называются отцом и сыном (или главной и подчиненной вершинами). Известно, что если граф не имеет циклов , то обязательно найдется хотя бы одна вершина, которая не является ничьим сыном. Такую вершину называют корневой. Если из одной вершины достижима другая, то первая называется предком , вторая — потомком .
Деревом называется граф , у которого одна вершина корневая, остальные вершины имеют только одного отца и все вершины являются потомками корневой вершины.
Листом дерева называется его вершина, не имеющая сыновей. Кроной дерева называется совокупность всех листьев . Высотой дерева называется наибольшая длина пути от корня к листу .
Нам будет удобно использовать следующее рекурсивное определение бинарного дерева : дерево либо пусто, либо состоит из корня , а также левого и правого поддеревьев, которые в свою очередь также являются деревьями .
В вершинах дерева может храниться информация любого типа. Для простоты в этой лекции будем считать, что в вершинах дерева располагаются целые числа. Тогда соответствующее этому определению описание альтернативного домена будет выглядеть следующим образом:
DOMAINS
tree=empty;tr(i,tree,tree)
/* дерево либо пусто, либо
состоит из корня (целого числа),
левого и правого поддеревьев,
также являющихся деревьями */
Заметим, что идентификатор empty не является зарезервированным словом Пролога. Вместо него вполне можно употреблять какое-нибудь другое обозначение для пустого дерева . Например, можно использовать для обозначения дерева , не имеющего вершин, идентификатор nil, как в Лиспе, или void, как в Си. То же самое относится и к имени домена (и имени функтора): вместо tree (tr) можно использовать любой другой идентификатор.
Например, дерево

 
можно задать следующим образом:
tr(2,tr(7,empty, empty),tr(3,tree(4,empty,empty),
tr(1,empty,empty))).
Теперь займемся написанием предикатов для реализации операций на бинарных деревьях .
Пример. Начнем с реализации предиката, который будет проверять принадлежность значения дереву . Предикат будет иметь два аргумента. Первым аргументом будет исходное значение, вторым — дерево , в котором мы ищем данное значение.
Следуя рекурсивному определению дерева , заметим, что некоторое значение принадлежит данному дереву , если оно либо содержится в корне дерева , либо принадлежит левому поддереву, либо принадлежит правому поддереву. Других вариантов нет.
Запишем это рассуждение на Прологе.
tree_member(X,tr(X,_,_)):-!. /* X — является корнем
дерева */
tree_member(X,tr(_,L,_)):-
tree_member(X,L),!. /* X принадлежит
левому поддереву */
tree_member(X,tr(_,_,R)):-
tree_member(X,R). /* X принадлежит
правому поддереву */
Пример. Разработаем предикат, который будет заменять в дереве все вхождения одного значения на другое. У предиката будет четыре аргумента: три входных (значение, которое нужно заменять; значение, которым нужно заменять; исходное дерево ), четвертым — выходным — аргументом будет дерево , полученное в результате замены всех вхождений первого значения на второе.
Базис рекурсивного решения будет следующий. Из пустого дерева можно получить только пустое дерево . При этом абсолютно неважно, что на что мы заменяем. Шаг рекурсии зависит от того, находится ли заменяемое значение в корне дерева . Если находится, то нужно заменить корневое значение вторым значением, после чего перейти к замене первого значения на второе в левом и правом поддереве. Если же в корне содержится значение, отличное от заменяемого, то оно должно остаться. Замену нужно произвести в левом и правом поддеревьях.
tree_replace(_,_,empty,empty). /* пустое дерево
остается пустым деревом*/
tree_replace(X,Y,tr(X,L,R),tr(Y,L1,R1)):-
/* корень содержит заменяемое
значение X*/
!,tree_replace(X,Y,L,L1),
/* L1 — результат замены
в дереве L всех вхождений X
на Y */
tree_replace(X,Y,R,R1).
/* R1 — результат замены
в дереве R всех вхождений X
на Y */
tree_replace(X,Y,tr(K,L,R),tr(K,L1,R1)):-
/* корень не содержит
заменяемое значение X */
tree_replace(X,Y,L,L1),
/* L1 — результат замены
в дереве L всех вхождений X
на Y */
tree_replace(X,Y,R,R1).
/* R1 — результат замены
в дереве R всех вхождений X
на Y */

Первый (входной) параметр — дерево , второй (выходной) — количество вершин в дереве .





Как всегда, пользуемся рекурсией. Базис: в пустом дереве количество вершин равно нулю. Шаг рекурсии: чтобы посчитать количество вершин дерева , нужно посчитать количество вершин в левом и правом поддереве, сложить полученные числа и добавить к результату единицу (посчитать корень дерева ).

Пишем:

tree_length (empty,0). /* В пустом дереве

нет вершин */

tree_length(tr(_,L,R),N):-

tree_length (L,N1),

/* N1 — число вершин

левого поддерева */

tree_length (R,N2),

/* N2 — число вершин

правого поддерева */

N=N1+N2+1. /* число вершин

исходного дерева

получается сложением

N1, N2 и единицы */

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

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

Запишем:

tree_leaves(empty,0). /* в пустом дереве

листьев нет */

tree_leaves(tr(_,empty,empty),1):-!.

/* в дереве с одним корнем —

один лист */

tree_leaves(tr(_,L,R),N):-

tree_leaves(L,N1),

/* N1 — количество листьев

в левом поддереве */

tree_leaves(R,N2),

/* N2 — количество листьев

в правом поддереве */

N=N1+N2.

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

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

На Прологе это записывается следующим образом:

tree_sum (empty,0). /* В пустом дереве

вершин нет */

tree_sum(tr(X,L,R),N):-

tree_sum (L,N1),

/* N1 — сумма элементов

левого поддерева */

tree_sum (R,N2),

/* N2 — сумма элементов

правого поддерева */

N=N1+N2+X. /* складываем N1, N2

и корневое значение */

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

Базис рекурсии будет основан на том, что высота пустого дерева равна нулю. Шаг рекурсии — на том, что для подсчета высоты всего дерева нужно найти высоты левого и правого поддеревьев, взять их максимум и добавить единицу (учесть уровень, на котором находится корень дерева ). Предикат max (или max2), вычисляющий максимум из двух элементов, был разработан нами еще в третьей лекции. Мы воспользуемся им при вычислении высоты дерева .

Получается следующее.

tree_height(empty,0). /* Высота пустого

дерева равна нулю */

tree_height(tr(_,L,R),D) :-

tree_height(L,D1),

/* D1 — высота левого

поддерева */

tree_height(R,D2),

/* D2 — высота правого

поддерева */

max(D1,D2,D_M),

/* D_M — максимум из высот

левого и правого поддеревьев */

D=D_M+1.

/* D — высота дерева получается

путем увеличения числа D_M

на единицу*/

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

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

Модифицированный предикат будет выглядеть следующим образом:

tree_member2(X,tr(X,_,_)):-!. /* X — корень

дерева */

tree_member2(X,tr(K,L,_)):-

X<K,!,

tree_member2(X,L).

/* X — принадлежит

левому поддереву */

tree_member2(X,tr(K,_,R)):-

X>K,!,

tree_member2(X,R).

/* X — принадлежит

правому поддереву */

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

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

Запишем на Прологе реализацию этих рассуждений.

tree_insert(X,empty,tr(X,empty,empty)).

/* вставляем X в пустое дерево,

получаем дерево с X в корневой

вершине,пустыми левым и

правым поддеревьями */

tree_insert(X,tr(X,L,R),tr(X,L,R)):-!.

/* вставляем X в дерево

со значением X в корневой

вершине, оставляем исходное

дерево без изменений */

tree_insert(X,tr(K,L,R),tr(K,L1,R)):-

X<K,!,

tree_insert(X,L,L1).

/* вставляем X в дерево

с большим X элементом в

корневой вершине, значит,

нужно вставить X в левое

поддерево исходногодерева */

tree_insert(X,tr(K,L,R),tr(K,L,R1)):-

tree_insert(X,R,R1).

/* вставляем X в дерево

с меньшим X элементом

в корневой вершине, значит,

нужно вставить X в правое

поддерево исходного дерева */

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

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

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

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

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

tree_gen(0,empty):-!. /* ноль вершин

соответствует пустому дереву */

tree_gen (N,T):-

random(100,X),

/* X — случайное число

из промежутка [0,100) */

N1= N-1,

tree_gen (N1,T1),

/* T1 — дерево, имеющее

N-1 вершин */

tree_insert(X,T1,T). /* вставляем X

в дерево T1 */

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

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

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

Другой вариант: можно поменять местами вызов предикатов random и tree_gen и после генерации случайного числа проверять с помощью предиката tree_member2, не содержится ли это значение в уже построенном дереве . Если его там нет, значит, его можно спокойно вставить в двоичный справочник с помощью предиката tree_insert. Если же это значение уже содержится в одной из вершин дерева , значит, нужно сгенерировать новое случайное число, после чего опять проверить его наличие и т.д.

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

Эту проблему можно обойти, если сделать первый аргумент предиката random зависящим от заказанного числа вершин дерева (заведомо больше).

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

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

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

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

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

Запишем оба эти предиката.

Начнем со вспомогательного предиката, удаляющего минимальный элемент двоичного справочника .

tree_del_min(tr(X,empty,R), R, X).

/* Если левое поддерево пусто,

то минимальный элемент — корень,

а дерево без минимального

элемента — это правое поддерево.*/

tree_del_min(tr(K,L,R), tr(K,L1,R), X):-

tree_del_min(L, L1, X).

/* Левое поддерево не пусто,

значит, оно содержит минимальное

значениевсего дерева,

которое нужно удалить */

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

tree_delete(X,tr(X,empty,R), R):-!.

/* X совпадает с корневым

значением исходного дерева,

левое поддерево пусто */

tree_delete (X,tr(X,L,empty), L):-!.

/* X совпадает с корневым

значением исходного дерева,

правое поддерево пусто */

tree_delete (X,tr(X,L,R), tr(Y,L,R1)):-

tree_del_min(R,R1, Y).

/* X совпадает с корневым

значением исходного

дерева, причем ни левое, ни

правое поддеревья не пусты */

tree_delete (X,tr(K,L,R), tr(K,L1,R)):-

X<K,!,

tree_delete (X,L,L1).

/* X меньше корневого значения

дерева */

tree_delete (X,tr(K,L,R), tr(K,L,R1)):-

tree_delete (X,R,R1).

/* X больше корневого значения

дерева */

Пример. Создадим предикат, который будет преобразовывать произвольный список в двоичный справочник . Предикат будет иметь два аргумента. Первый (входной) — произвольный список, второй (выходной) — двоичный справочник , построенный из элементов первого аргумента.

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

То же самое на Прологе:

list_tree([],empty). /* Пустому списку

соответствует пустое дерево */

list_tree([H|T],Tr):-

list_tree(T,Tr1),

/* Tr1 — дерево, построенное

из элементов хвоста

исходного списка */

tree_insert(H,Tr1,Tr).

/* Tr — дерево, полученное

в результате вставки

головы списка в дерево Tr1 */

Пример. Создадим обратный предикат, который будет «сворачивать» двоичный справочник в список с сохранением порядка элементов. Предикат будет иметь два аргумента. Первый (входной) — произвольный двоичный справочник , второй (выходной) — список, построенный из элементов первого аргумента.

tree_list(empty,[]). /* Пустому дереву

соответствует пустой список */

tree_list(tr(K,L,R),S):-

tree_list(L,T_L),

/* T_L — список,

построенный из элементов

левого поддерева */

tree_list(R,T_R),

/* T_L — список,

построенный из элементов

правого поддерева */

conc(T_L,[K|T_R],S).

/* S — список, полученный

соединением списков T_L

и [K|T_R] */

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

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

sort_listT(L,L_S):-

list_tree(L,T),

/* T- двоичный справочник,

построенный из элементов

исходного списка L */

tree_list(T,L_S).

/* L_S — список, построенный из

элементов двоичного

справочника T */

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

Самостоятельные задания

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

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

Создайте предикат, находящий максимальное из значений, находящихся в вершинах дерева.

Создайте предикат, проверяющий, что дерево является двоичным справочником.

Создайте предикат, переписывающий дерево в двоичный справочник.

Создайте предикат, который будет находить среднеарифметическое значений, находящихся в вершинах дерева.

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

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

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

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

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

Создайте предикат, подсчитывающий количество всех вершин данного дерева заданной высоты.

Создайте предикат, выводящий значения находящиеся в вершинах заданной высоты.

Создайте предикат, проверяющий, является ли одно дерево поддеревом второго.

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

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

Двоичное дерево с целыми числами в узлах

Copyright (c) 2010 ilynva  - http://ilynva.livejournal.com/20359.html
New BSD License (see http://www.opensource.org/licenses/bsd-license.php)



Порешал  задачу с сайта http://sites.google.com/site/kubenskiy/Home/2009-2010/functional/tasks 
под номером 5 и вариантом 1.

Дано двоичное дерево [0] с целыми числами (Binary tree with integers [2] | (англ. binary search tree, BST)) 
в узлах. Дерево задано следующим описанием типа данных [3]:

> data Tree = Empty | Node Tree Integer Tree
>    deriving (Show, Read, Eq)                     

Написать функцию построения дерева такого типа. Для распечатки результата можно написать функцию для 
представления дерева в виде строки или воспользоваться системным классом Show.

Начнем с класса Show. Добавим в определение типа deriving (Show, Read, Eq) сделав Tree частью Show [1]. Для проверки 
определим вручную несколько бинарных деревьев. Как всегда первое дерево пустое tree1. Корень без листьев tree2.

> tree1 = Empty
> tree2 = Node Empty 10 Empty
> showTree tree = show tree

Проверим вывод дерева: 

*Main> show tree2
"Node Empty 10 Empty"
it :: String

*Main> read (show tree2)::Tree
Node Empty 10 Empty
it :: Tree

Так, поиграемся с функцией предложенной в книжке Изучай хаскель ради добра[3]. Там предложена функция создания дерева
, которая принимает дерево и элемент и добавляет элемент к дереву. 

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

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

> singleton :: Integer -> Tree
> singleton x = Node  Empty x Empty

*Main> singleton 5
Node Empty 5 Empty

Вставка элемента в дерево.

> treeInsert :: Integer -> Tree  -> Tree 

Паттерн матчинг для пустого дерева. Сюда мы вставим наше значение используя вспомогательную функцию  singleton,
которая заменит при вставке значение деревом.

> treeInsert x Empty = singleton x

*Main> treeInsert 10 Empty
Node Empty 10 Empty

Рассмотрим вставку в не в пустое дерево. Используем охраняющие выражения (guards) для проверок различных вариантов. 
Первое, если наш вставляемый элемент равен значению корневого элемента, то просто возвращаем текущее дерево.
Важное свойство упорядоченного дерева поиска - все элементы его различны!
*Main>  treeInsert 10 (treeInsert 10 (treeInsert 10 Empty))
Node Empty 10 Empty

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

*Main> treeInsert 7 (treeInsert 10 Empty)
Node (Node Empty 7 Empty) 10 Empty

Так же (но с соответствующими поправками) дело обстоит если значение больше чем корневой элемент.

*Main> treeInsert 13 (treeInsert 10 Empty)
Node Empty 10 (Node Empty 13 Empty)


> treeInsert x (Node left a right)
>     | x == a = Node left x right
>     | x < a  = Node (treeInsert x left) a  right
>     | x > a  = Node left a (treeInsert x right)

Функция проверки вхождения элемента в двоичное дерево с целыми числами

> treeElem :: Integer -> Tree  -> Bool
> treeElem x Empty = False

Граничное условие для пустого дерева возвращает ложь - вхождения нужного значения нет.
*Main> treeElem 10 Empty
False

Рассмотрим охраняющие выражения (guards) для непустого дерева. Первое равенство дает нам право вернуть истину, 
говорящую о том, что искомый элемент есть в дереве. Так как наше дерево является деревом поиска [4] для  искомого 
элемента меньше корневого, начинаем рекурсивно искать в левом поддереве. Если искомый элемент больше -  
тогда ищем в правом поддереве.

> treeElem x (Node left a right)
>     | x == a = True
>     | x < a  = treeElem x left
>     | x > a  = treeElem x right

Поищем в дереве:
*Main> treeInsert 7 (treeInsert 11 (treeInsert 12 (treeInsert 10 Empty)))
Node (Node Empty 7 Empty) 10 (Node (Node Empty 11 Empty) 12 Empty)
*Main> treeElem 12 (treeInsert 7 (treeInsert 11 (treeInsert 12 (treeInsert 10 Empty))))
True
*Main> treeElem 64 (treeInsert 7 (treeInsert 11 (treeInsert 12 (treeInsert 10 Empty))))
False
Для тестирования включил ghci при вызове start interpreter из Емакса.
*Main> let nums = [8,6,4,1,7,3,5] 
*Main> let numsTree = foldr treeInsert Empty nums
*Main> numsTree
Node (Node (Node Empty 1 Empty) 3 (Node Empty 4 Empty)) 5 (Node (Node Empty 6 Empty) 7 (Node Empty 8 Empty))

Функция fromList :: [Integer] -> Tree строит  дерево поиска, содержащее значения из 
заданного списка целых.

> fromList :: [Integer] -> Tree
> fromList nums = foldr treeInsert Empty nums
> nums = [8,6,4,1,7,3,5]

*Main> fromList nums
Node (Node (Node Empty 1 Empty) 3 (Node Empty 4 Empty)) 5 (Node (Node Empty 6 Empty) 7 (Node Empty 8 Empty))

В самом худшем случае двоичное дерево поиска может быть вырожденным и сложность операций поиска будет как у списка.
*Main> fromList [1..10]
Node (Node (Node (Node (Node (Node (Node (Node (Node (Node Empty 1 Empty) 2 Empty) 3 Empty) 4 Empty) 5 Empty) 6 Empty) 
7 Empty) 8 Empty) 9 Empty) 10 Empty

Функция преобразования дерева в список значений

> toList :: Tree -> [Integer]
> toList tree = toList' tree []
> toList' :: Tree -> [Integer] -> [Integer]
> toList' Empty list = list
> toList'(Node left a right) list = toList' left (a: (toList' right list))

*Main> toList (fromList nums)
[1,3,4,5,6,7,8]

> treeList :: Tree -> [Integer]
> treeList Empty = []
> treeList (Node left v right) = treeList left ++ [v] ++ treeList right

*Main> treeList (fromList nums)
[1,3,4,5,6,7,8]
it :: [Integer]

Сделаем следущее
*Main> fromList (toList (fromList nums))
Node (Node (Node (Node (Node (Node (Node Empty 1 Empty) 3 Empty) 4 Empty) 5 Empty) 6 Empty) 7 Empty) 8 Empty
*Main> fromList nums
Node (Node (Node Empty 1 Empty) 3 (Node Empty 4 Empty)) 5 (Node (Node Empty 6 Empty) 7 (Node Empty 8 Empty))
Видно, что деревья на выходе разные. Или еще
*Main> treeInsert 50 (treeInsert 4 (Node Empty 5 Empty))
Node (Node Empty 4 Empty) 5 (Node Empty 50 Empty)
*Main> treeInsert 5 (treeInsert 4 (Node Empty 50 Empty))
Node (Node Empty 4 (Node Empty 5 Empty)) 50 Empty

Реализуем функцию удаления узла или листа из дерева не нарушая свойства упорядоченности. Дерево должно остаться
деревом поиска. Алгоритм возьмем с википедии [4]:

> treeRemove :: Tree -> Integer -> Tree

Дано: дерево Тree.
Задача: удалить из дерева Тree узел с элементом равным  K (если таквой имеется в дереве).
Алгоритм:
   Если дерево Tree пусто, вернем пустое дерево.
                                    
> treeRemove Empty _ = (Empty)
> treeRemove (Node left x right) k                                     
  
   Иначе сравнить K с элементом-ключом X корневого узла n.
      Если K>X, рекурсивно удалить K из правого поддерева Тree.

>   | k > x = Node left x (treeRemove right k)     
  
      Если K<X, рекурсивно удалить K из левого поддерева Тree.

>   | k < x = Node (treeRemove left k) x right

      Если K=X, то необходимо рассмотреть три случая:

>   | k == x = 

          1) Если обоих детей нет, то удаляем текущий узел. В парадигме функционального подхода мы просто
             вставляем в дерево пустое дерево. Нужно еще помнить, что из-за чистоты функций мы строим рекурсивно
             новое дерево.
             *Main> treeRemove (Node Empty 10 Empty) 10
               Empty
               it :: Tree
  
>         if (left == Empty) && (right == Empty)  
>             then Empty
  
          2) Если одного из детей нет, то значения полей второго ребёнка m ставим вместо соответствующих 
             значений корневого узла n, затирая его старые значения. Или перефразируя. Если  у удаляемой вершины 
             нет правого(левого) сына, мы можем убрать ее и вместо нее вставить левое поддерево, не нарушая 
             упорядоченность. Или еще - если удаляемый узел имеет только одного "сына", то его значение можно 
             заменить значением этого "сына"

>             else if (right == Empty) 
>                     then left
>                     else if (left == Empty)
>                              then right

          3) Если оба ребёнка присутствуют, то:

>                              else if  (left /= Empty) && (right /= Empty) 

                 a) найдём узел m, являющийся самым левым узлом правого поддерева, или если 
                    сказать по другому - найдем в правом поддереве минимум: treeMin right;
                 а) заменяем его (удаляемый узел) элементом с наименьшим значением среди потомков правого 
                    "сына" treeMin right (или элементом с наибольшим значением среди потомков левого "сына").
                    Мы не будем так делать, хотя это кажется разумным если heightTree left > heightTree right.
                 
>                                      then (Node left (treeMin right) (treeRemove right (treeMin right)))
>                                      else error "treeRemove :: Эта ветка никогда не должна выполняться!!!"

> treeMin :: Tree -> Integer
> treeMin tree  = head (treeList tree)

*Main> fromList nums
Node (Node (Node Empty 1 Empty) 3 (Node Empty 4 Empty)) 5 (Node (Node Empty 6 Empty) 7 (Node Empty 8 Empty))
it :: Tree
*Main> treeMin (fromList nums)
1

Потестируем функцию удаления элемента из дерева. 1) Удаление из пустого дерева.
*Main> treeRemove Empty 10
Empty
2) Удаляемый элемент не содержит детей потомков и является листом.
*Main> treeRemove (treeInsert 10 Empty) 10
Empty
*Main> treeInsert 5 (treeInsert 10 Empty)
Node (Node Empty 5 Empty) 10 Empty
Это дерево
         10
        /
       5
*Main> treeRemove (treeInsert 5 (treeInsert 10 Empty)) 5
Node Empty 10 Empty
*Main> treeInsert 15 (treeInsert 10 Empty)
Node Empty 10 (Node Empty 15 Empty)
Это дерево
         10
           \
            15
*Main> treeRemove (treeInsert 15 (treeInsert 10 Empty)) 10
Node Empty 15 Empty
it :: Tree
*Main> treeRemove (treeInsert 15 (treeInsert 10 Empty)) 15
Node Empty 10 Empty

*Main> (treeInsert 7(treeInsert 15 (treeInsert 10 Empty)))
Node (Node Empty 7 Empty) 10 (Node Empty 15 Empty)
it :: Tree
         10
        /  \        
       7   15

*Main> treeRemove  (treeInsert 7(treeInsert 15 (treeInsert 10 Empty))) 10
Node (Node Empty 7 Empty) 15 Empty
it :: Tree                  

         15
        /
       7

Построим такое дерево вида

> testTreeManual = (Node  (Node (Node Empty 4 Empty) 7 (Node Empty 6 Empty)) 10 (Node Empty 15 (Node Empty 24 Empty)))

         10
        /  \        
       7   15                  
      / \    \        
     4   6    24      

Удалим 7
*Main> treeRemove testTreeManual 7
Node (Node (Node Empty 4 Empty) 6 Empty) 10 (Node Empty 15 (Node Empty 24 Empty))
         10
        /  \           
       6    15            
      /      \        
     4        24      

Удалим 10
*Main> treeRemove testTreeManual 10
Node (Node (Node Empty 4 Empty) 7 (Node Empty 6 Empty)) 15 (Node Empty 24 Empty)
         15
        /  \        
       7    24       
      / \ 
     4   6              

Высота дерева — это максимальная длина пути от корня дерева до одного из листов дерева. 

> heightTree :: Tree -> Integer
> heightTree Empty = 0
> heightTree (Node l _ r) = (max (heightTree l) (heightTree r)) + 1

Вес дерева равный количеству узлов, листья тоже считаем

> weightTree :: Tree -> Integer
> weightTree Empty = 0
> weightTree (Node left _  right) = (weightTree left) + (weightTree right) + 1

*Main> heightTree (fromList nums)
3
*Main> weightTree (fromList nums)
7
*Main> length (treeList (fromList nums))
7


================================================================================================================
0. http://ru.wikipedia.org/wiki/Двоичное_дерево
1. http://www.haskell.ru/derived.html
2. http://habrahabr.ru/blogs/algorithm/65617/
3. http://translated.by/you/learn-you-a-haskell-for-great-good-making-our-own-types-and-typeclasses/into-ru/?page=5
4. http://ru.wikipedia.org/wiki/Двоичное_дерево_поиска
5. http://www.citforum.ru/programming/theory/sorting/sorting2.shtml#4_1_1 Двоичные деревья, 
   Сбалансированные двоичные деревья, Деревья оптимального поиска.
6. http://rain.ifmo.ru/cat/view.php/vis/trees/binary-search-2002 Визуализаторы
7. http://haskell.org/haskellwiki/Shootout/Binary_trees
8. http://hackage.haskell.org/packages/archive/TreeStructures/0.0.2/doc/html/src/Data-Tree-Splay.html
9. http://volvo71.narod.ru/faq_folder/bin_tree.htm Бинарные деревья (основные понятия)
<img src="http://learnyouahaskell.com/binarytree.png"


http://th2.ihep.su/soloviev/perevod/Perelman_trans.htm
http://arxiv.org/abs/math/0211159
http://arxiv.org/abs/math/0303109
http://arxiv.org/abs/math/0307245

пустых деревьев — это … Что такое пустое дерево?

  • Обход дерева — Алгоритмы поиска по графам и деревьям Альфа-бета-обрезка A * B * Алгоритм Беллмана – Форда Луч Лучшее первое Двунаправленное… Wikipedia

  • Пусто — Пустота (?; 215), a. [Сравните. {Emptier}; супер {Самый пустой}.] [AS. emtig, [ae] mtig, [ae] metig, фр. [ae] mta, [ae] metta, тишина, досуг, отдых; неопределенного происхождения; ср. Г. Эмсиг занят.] 1. Ничего не содержит; ничего не держит или не имеет внутри;…… The Collaborative International Dictionary of English

  • Дерево — / tree /, n.Сэр Герберт Бирбом / Bear Bohm /, (Герберт Бирбом), 1853-1917, английский актер и театральный менеджер; брат Макса Бирбома. * * * I Древесное многолетнее растение. У большинства деревьев есть единственный самонесущий ствол, содержащий древесные ткани, а в… Universalium

  • Древо жизни — Чтобы узнать о других значениях, см. Древо жизни (значения). Изображение норвежского Иггдрасиля в 1847 году, описанное в исландской прозе Эдда Олуфом Олуфсеном Багге. Концепция дерева жизни, дерева с множеством ветвей, иллюстрирующего идею, что вся жизнь на…… Википедия

  • дерево — древовидный, прил./ tree /, n., v., деревья, деревья. п. 1. растение с постоянно древесным основным стеблем или стволом, обычно вырастающим до значительной высоты и обычно развивающимся ветвями на некотором расстоянии от земли. 2. любой кустарник,…… Универсал

  • Дерево (теория графов) — Деревья Помеченное дерево с 6 вершинами и 5 ребрами Вершины v Ребра v 1 Хроматическое число… Wikipedia

  • Древовидная декомпозиция — Граф с восемью вершинами и его древовидная декомпозиция на дерево с шестью узлами.Каждое ребро графа соединяет две вершины, перечисленные вместе в некотором узле дерева, и каждая вершина графа указана в узлах смежного поддерева…… Wikipedia

  • Дерево — Чтобы узнать о других значениях, см. Дерево (значения). Деревья на горе в северной части штата Юта ранней осенью… Wikipedia

  • Синдром пустого носа — Классификация в МКБ 10 T81.9 Ничего не значащая Komplikation eines Eingriffes J34.8 Sonstige näher bezeichnete Krankheiten der Nase und der Nasennebenhölenia

    Deutsch6

  • Дерево (описательная теория множеств) — В описательной теории множеств дерево на множестве X — это набор конечных последовательностей элементов X, замкнутых относительно подпоследовательностей.{… Википедия

  • Христианские школы «Древо жизни» — Инфобокс Название школы = Древо жизни Христианские школы imagesize = caption = девиз = установленный = 1978 тип = Частная, конфессия для подготовки к колледжу = Принадлежность к Церкви Христа = авторитет = оценки = K ndash; 12 президент = Лезли Ноулз…… Википедия

  • .

    стоковых иллюстраций пустых деревьев — 3944 стоковых иллюстраций, векторных изображений и клипарт пустых деревьев

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

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

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

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

    Пустая сцена с деревянным столом. Деревянный стол тропические листья, пальмы. Ночной вид на тропические листья

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

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

    Пустой шаблон с двумя старыми деревьями. Иллюстрация пустого шаблона с двумя старыми деревьями

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

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

    Пустое белое знамя между двумя пальмами. Концепция путешествия. 3д иллюстрация

    Пустой бумажный шаблон с соснами и камнями внизу. Иллюстрация пустого бумажного шаблона с соснами и камнями внизу

    .

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *

    2021 © Все права защищены. Карта сайта