Разделы презентаций


Динамические структуры данных

Содержание

Деревья

Слайды и текст этой презентации

Слайд 1Деревья
Динамические структуры данных

ДеревьяДинамические структуры данных

Слайд 2Деревья

Деревья

Слайд 3Деревья
Дерево – это структура данных, состоящая из узлов и соединяющих

их направленных ребер (дуг), причем в каждый узел (кроме корневого)

ведет ровно одна дуга.
Корень – это начальный узел дерева.
Лист – это узел, из которого не выходит ни одной дуги.

корень

Какие структуры – не деревья?

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

Слайд 4Деревья
Предок узла x – это узел, из которого существует путь

по стрелкам в узел x.
Потомок узла x – это узел,

в который существует путь по стрелкам из узла x.
Родитель узла x – это узел, из которого существует дуга непосредственно в узел x.

Сын узла x – это узел, в который существует дуга непосредственно из узла x.
Брат узла x (sibling) – это узел, у которого тот же родитель, что и у узла x.
Высота дерева – это наибольшее расстояние от корня до листа (количество дуг).

ДеревьяПредок узла x – это узел, из которого существует путь по стрелкам в узел x.Потомок узла x

Слайд 5Дерево – рекурсивная структура данных
Рекурсивное определение:
Пустая структура – это дерево.
Дерево

– это корень и несколько связанных с ним деревьев.
Двоичное (бинарное)

дерево – это дерево, в котором каждый узел имеет не более двух сыновей.

Пустая структура – это двоичное дерево.
Двоичное дерево – это корень и два связанных с ним двоичных дерева (левое и правое поддеревья).

Дерево – рекурсивная структура данныхРекурсивное определение:Пустая структура – это дерево.Дерево – это корень и несколько связанных с

Слайд 6Двоичные деревья
Структура узла:
struct Node {
int data;

// полезные данные
Node *left, *right; // ссылки на

левого // и правого сыновей
};
typedef Node *PNode;

Применение:
поиск данных в специально построенных деревьях (базы данных);
сортировка данных;
вычисление арифметических выражений;
кодирование (метод Хаффмана).

Двоичные деревьяСтруктура узла:struct Node { int data;     // полезные данные Node *left, *right;

Слайд 7Двоичные деревья
Многие полезные структуры данных основаны на двоичном дереве:
Двоичное дерево

поиска
Двоичная куча
АВЛ-дерево
Красно-чёрное дерево
Матричное дерево
Дерево Фибоначчи
Суффиксное дерево

Двоичные деревьяМногие полезные структуры данных основаны на двоичном дереве:Двоичное дерево поискаДвоичная кучаАВЛ-деревоКрасно-чёрное деревоМатричное деревоДерево ФибоначчиСуффиксное дерево

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

ключами, а справа – с бóльшими.
Ключ – это характеристика узла,

по которой выполняется поиск (чаще всего – одно из полей структуры).

Как искать ключ, равный x:
если дерево пустое, ключ не найден;
если ключ узла равен x, то стоп.
если ключ узла меньше x, то искать x в левом поддереве;
если ключ узла больше x, то искать x в правом поддереве.

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

Слайд 9Двоичные деревья поиска
Двоичное дерево поиска— это двоичное дерево,
для которого

выполняются следующие
дополнительные условия (свойства дерева поиска):
Оба поддерева —

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

Двоичные деревья поискаДвоичное дерево поиска— это двоичное дерево, для которого выполняются следующие дополнительные условия (свойства дерева поиска):

Слайд 10Двоичные деревья поиска
Поиск в массиве (N элементов):
При каждом сравнении отбрасывается

1 элемент.
Число сравнений – N.
Поиск по дереву (N элементов):
При каждом

сравнении отбрасывается половина оставшихся элементов.
Число сравнений ~ log2N.

быстрый поиск

нужно заранее построить дерево;
желательно, чтобы дерево было минимальной высоты.

Двоичные деревья поискаПоиск в массиве (N элементов):При каждом сравнении отбрасывается 1 элемент.Число сравнений – N.Поиск по дереву

Слайд 11Несбалансированные двоичные деревья поиска (unbalanced)

Это такие деревья, высота правого и

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

становится несбалансированным, когда в него постоянно добавляются элементы большего или меньшего размера

Несбалансированные двоичные деревья поиска (unbalanced)Это такие деревья, высота правого и левого поддеревьев которых отличаются более, чем на

Слайд 12Неполные двоичные деревья поиска (incomplete)
Каждый узел дерева двоичного поиска должен

содержать не более 2 детей.
Но он может иметь 1

ребенка или не иметь детей.
Если в дереве есть такие хотя бы один такой узел, дерево называют неполным.
Неполные двоичные деревья поиска (incomplete)Каждый узел дерева двоичного поиска должен содержать не более 2 детей. Но он

Слайд 13Основные операции в двоичном дереве поиска

Базовый интерфейс двоичного дерева поиска

состоит из трех операций:
Поиск узла, в котором хранится пара (key,

value) с key = K.
Добавление в дерево пары (key, value) = (K, V).
Удаление узла, в котором хранится пара (key, value) с key = K.
Основные операции в двоичном дереве поискаБазовый интерфейс двоичного дерева поиска состоит из трех операций:Поиск узла, в котором

Слайд 14Поиск элемента
Дано: дерево Т и ключ K.
Задача: проверить, есть

ли узел с ключом K в дереве Т, и если

да, то вернуть ссылку на этот узел.
Алгоритм:
Если дерево пусто, сообщить, что узел не найден, и остановиться.
Иначе сравнить K со значением ключа корневого узла X.
Если K=X, выдать ссылку на этот узел и остановиться.
Если K>X, рекурсивно искать ключ K в правом поддереве Т.
Если K
Поиск элемента Дано: дерево Т и ключ K.Задача: проверить, есть ли узел с ключом K в дереве

Слайд 15Добавление элемента
Дано: дерево Т и пара (K,V).
Задача: добавить пару

(K, V) в дерево Т.
Алгоритм:
Если дерево пусто, заменить его на

дерево с одним корневым узлом ((K,V), null, null) и остановиться.
Иначе сравнить K с ключом корневого узла X.
Если K>=X, рекурсивно добавить (K,V) в правое поддерево Т.
Если K
Добавление элемента Дано: дерево Т и пара (K,V).Задача: добавить пару (K, V) в дерево Т.Алгоритм:Если дерево пусто,

Слайд 16Удаление узла
Дано: дерево Т с корнем n и ключом

K.
Задача: удалить из дерева Т узел с ключом K (если

такой есть).
Алгоритм:
Если дерево T пусто, остановиться
Иначе сравнить K с ключом X корневого узла n.
Если K>X, рекурсивно удалить K из правого поддерева Т.
Если KЕсли K=X, то необходимо рассмотреть три случая.
Если обоих детей нет, то удаляем текущий узел и обнуляем ссылку на него у родительского узла.
Если одного из детей нет, то значения полей второго ребёнка m ставим вместо соответствующих значений корневого узла, затирая его старые значения, и освобождаем память, занимаемую узлом m.
Если оба ребёнка присутствуют, то
найдём узел m, являющийся самым левым узлом правого поддерева с корневым узлом Right(n);
присвоим ссылке Left(m) значение Left(n)
ссылку на узел n в узле Parent(n) заменить на Right(n);
освободим память, занимаемую узлом n (на него теперь никто не указывает).
Удаление узла Дано: дерево Т с корнем n и ключом K.Задача: удалить из дерева Т узел с

Слайд 17Реализация алгоритма поиска
//---------------------------------------
// Функция Search – поиск по дереву
// Вход:

Tree - адрес корня,
// x

- что ищем
// Выход: адрес узла или NULL (не нашли)
//---------------------------------------
PNode Search (PNode Tree, int x)
{
if ( ! Tree ) return NULL;
if ( x == Tree->data )
return Tree;
if ( x < Tree->data )
return Search(Tree->left, x);
else
return Search(Tree->right, x);
}

дерево пустое: ключ не нашли…

нашли, возвращаем адрес корня

искать в левом поддереве

искать в правом поддереве

Реализация алгоритма поиска//---------------------------------------// Функция Search – поиск по дереву// Вход: Tree - адрес корня, //

Слайд 18Как построить дерево поиска?
//---------------------------------------------
// Функция AddToTree – добавить элемент к

дереву
// Вход: Tree - адрес корня,
//

x - что добавляем
//----------------------------------------------
void AddToTree (PNode &Tree, int x)
{
if ( ! Tree ) {
Tree = new Node;
Tree->data = x;
Tree->left = NULL;
Tree->right = NULL;
return;
}
if ( x < Tree->data )
AddToTree ( Tree->left, x );
else AddToTree ( Tree->right, x );
}

дерево пустое: создаем новый узел (корень)

адрес корня может измениться

добавляем к левому или правому поддереву

Как построить дерево поиска?//---------------------------------------------// Функция AddToTree – добавить элемент к дереву// Вход: Tree - адрес корня, //

Слайд 19Обход дерева
Обход дерева – это перечисление всех узлов в определенном

порядке.
Обход ЛКП («левый – корень – правый»):
125
98
76
45
59
30
16
Обход ПКЛ («правый –

корень – левый»):

Обход КЛП («корень – левый – правый»):

Обход ЛПК («левый – правый – корень»):

Обход дереваОбход дерева – это перечисление всех узлов в определенном порядке.Обход ЛКП («левый – корень – правый»):125987645593016Обход

Слайд 20Обход дерева – реализация
//---------------------------------------------
// Функция LKP – обход дерева в

порядке ЛКП
// (левый

– корень – правый)
// Вход: Tree - адрес корня
//----------------------------------------------
void LKP( PNode Tree )
{
if ( ! Tree ) return;
LKP ( Tree->left );
printf ( "%d ", Tree->data );
LKP ( Tree->right );
}

обход этой ветки закончен

обход левого поддерева

вывод данных корня

обход правого поддерева


Слайд 21Двоичная куча
Двоичная куча
Структура данных для хранения двоичной кучи

Двоичная кучаДвоичная кучаСтруктура данных для хранения двоичной кучи

Слайд 22Двоичная куча
Двоичная куча (пирамида) — такое двоичное дерево, для которого выполнены

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

лист имеет глубину (расстояние до корня) либо d либо d-1. Иными словами, если назвать слоем совокупность листьев, находящемся на определённой глубине, то все слои, кроме, может быть, последнего, заполнены полностью.
Последний слой заполняется слева направо.
Существуют также кучи, где значение в любой вершине, наоборот, меньше, чем значения её потомков. Такие кучи называются min-heap, а кучи, описанные выше — max-heap.
Двоичная кучаДвоичная куча (пирамида) — такое двоичное дерево, для которого выполнены три условия:Значение в любой вершине больше, чем

Слайд 23Кучи
Max-heap







Значение в любой вершине больше, чем значения ее потомков


Min-heap






Значение в

любой вершине меньше, чем значения ее потомков

КучиMax-heapЗначение в любой вершине больше, чем значения ее потомковMin-heapЗначение в любой вершине меньше, чем значения ее потомков

Слайд 24Красно-чёрное дерево

Красно-чёрное дерево

Слайд 25Красно-чёрное дерево
Красно-чёрное дерево (Red-Black-Tree, RB-Tree) — это одно из самобалансирующихся

двоичных деревьев поиска, гарантирующих логарифмический рост высоты дерева от числа

узлов и быстро выполняющее основные операции дерева поиска: добавление, удаление и поиск узла.
Сбалансированность достигается за счет введения дополнительного атрибута узла дерева — «цвет». Этот атрибут может принимать одно из двух возможных значений — «чёрный» или «красный».
Красно-чёрное дерево обладает следующими свойствами:
Все листья черные.
Все потомки красных узлов черные (т.е. запрещена ситуация с двумя красными узлами подряд).
На всех ветвях дерева, ведущих от его корня к листьям, число чёрных узлов одинаково. Это число называется чёрной высотой дерева.

При этом для удобства листьями красно-чёрного дерева считаются фиктивные «нулевые» узлы, не содержащие данных.
Красно-чёрное деревоКрасно-чёрное дерево (Red-Black-Tree, RB-Tree) — это одно из самобалансирующихся двоичных деревьев поиска, гарантирующих логарифмический рост высоты

Слайд 26АВЛ-дерево
АВЛ-дерево — сбалансированное по высоте двоичное дерево поиска: для каждой

его вершины высота её двух поддеревьев различается не более чем

на 1.
АВЛ-деревья названы по первым буквам фамилий их изобретателей, Г. М. Адельсона-Вельского и Е. М. Ландиса, которые впервые предложили использовать АВЛ-деревья в 1962
АВЛ-деревоАВЛ-дерево — сбалансированное по высоте двоичное дерево поиска: для каждой его вершины высота её двух поддеревьев различается

Слайд 27B-дерево
B-дерево (по-русски произносится как Б-дерево) — структура данных, дерево поиска. С

точки зрения внешнего логического представления, сбалансированное, сильно ветвистое дерево во

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

Слайд 28Пример B-дерева степени 2

Пример B-дерева степени 2

Слайд 292-3-дерево
2-3 дерево — структура данных являющаяся B-деревом степени 1, страницы которого

могут содержать только 2-вершины (вершины с одним полем и 2-мя

детьми) и 3-вершины (вершины с 2-мя полями и 3-мя детьми).
Листовые вершины являются исключением — у них нет детей (но может быть одно или два поля). 2-3 деревья сбалансированы, то есть каждое левое, правое, и центральное поддерево одинаковой высоты, и таким образом содержат равное (или почти равное) число данных.
2-3-дерево2-3 дерево — структура данных являющаяся B-деревом степени 1, страницы которого могут содержать только 2-вершины (вершины с одним

Слайд 30Разбор арифметических выражений
a b + c d + 1 -

/
Как вычислять автоматически:
Инфиксная запись, обход ЛКП
(знак операции между операндами)
(a +

b) / (c + d – 1)

необходимы скобки!

Постфиксная запись, ЛПК (знак операции после операндов)

a + b / c + d – 1

польская нотация,
Jan Łukasiewicz (1920)

скобки не нужны, можно однозначно вычислить!

Префиксная запись, КЛП (знак операции до операндов)

/ + a b - + c d 1

обратная польская нотация,
F. L. Bauer and E. W. Dijkstra

Разбор арифметических выраженийa b + c d + 1 - /Как вычислять автоматически:Инфиксная запись, обход ЛКП(знак операции

Слайд 31Вычисление выражений
Постфиксная форма:
a b + c d +

1 - /
Алгоритм:
взять очередной элемент;
если это

не знак операции, добавить его в стек;
если это знак операции, то
взять из стека два операнда;
выполнить операцию и записать результат в стек;
перейти к шагу 1.

X =

Вычисление выраженийПостфиксная форма:a b + c  d  +  1  -  / Алгоритм:взять

Слайд 32Вычисление выражений
Задача: в символьной строке записано правильное арифметическое выражение, которое

может содержать только однозначные числа и знаки операций +-*\. Вычислить

это выражение.

Алгоритм:
ввести строку;
построить дерево;
вычислить выражение по дереву.

Ограничения:
ошибки не обрабатываем;
многозначные числа не разрешены;
дробные числа не разрешены;
скобки не разрешены.

Вычисление выраженийЗадача: в символьной строке записано правильное арифметическое выражение, которое может содержать только однозначные числа и знаки

Слайд 33Построение дерева
Алгоритм:
если first=last (остался один символ – число), то создать

новый узел и записать в него этот элемент; иначе...
среди элементов

от first до last включительно найти последнюю операцию (элемент с номером k);
создать новый узел (корень) и записать в него знак операции;
рекурсивно применить этот алгоритм два раза:
построить левое поддерево, разобрав выражение из элементов массива с номерами от first до k-1;
построить правое поддерево, разобрав выражение из элементов массива с номерами от k+1 до last.

first

last

k

k+1

k-1

Построение дереваАлгоритм:если first=last (остался один символ – число), то создать новый узел и записать в него этот

Слайд 34Как найти последнюю операцию?
Порядок выполнения операций
умножение и деление;
сложение и вычитание.
Приоритет

(старшинство) – число, определяющее последовательность выполнения операций: раньше выполняются операции

с большим приоритетом:
умножение и деление (приоритет 2);
сложение и вычитание (приоритет 1).
Как найти последнюю операцию?Порядок выполнения операцийумножение и деление;сложение и вычитание.Приоритет (старшинство) – число, определяющее последовательность выполнения операций:

Слайд 35Приоритет операции
//--------------------------------------------
// Функция Priority – приоритет операции
// Вход: символ операции
//

Выход: приоритет или 100, если не операция
//--------------------------------------------
int Priority ( char

c )
{
switch ( c ) {
case '+': case '-': return 1;
case '*': case '/': return 2;
}
return 100;
}

сложение и вычитание: приоритет 1

умножение и деление: приоритет 2

это вообще не операция

Приоритет операции//--------------------------------------------// Функция Priority – приоритет операции// Вход: символ операции// Выход: приоритет или 100, если не операция//--------------------------------------------int

Слайд 36Номер последней операции
//--------------------------------------------
// Функция LastOperation – номер последней операции
// Вход:

строка, номера первого и последнего // символов рассматриваемой

части
// Выход: номер символа - последней операции
//--------------------------------------------
int LastOperation ( char Expr[], int first, int last )
{
int MinPrt, i, k, prt;
MinPrt = 100;
for( i = first; i <= last; i++ ) {
prt = Priority ( Expr[i] );
if ( prt <= MinPrt ) {
MinPrt = prt;
k = i;
}
}
return k;
}

проверяем все символы

вернуть номер символа

нашли операцию с минимальным приоритетом

Номер последней операции//--------------------------------------------// Функция LastOperation – номер последней операции// Вход: строка, номера первого и последнего //

Слайд 37Построение дерева
Структура узла
struct Node {
char data;
Node *left, *right;

};
typedef Node *PNode;
Создание узла для числа (без потомков)
PNode NumberNode (

char c )
{
PNode Tree = new Node;
Tree->data = c;
Tree->left = NULL;
Tree->right = NULL;
return Tree;
}

возвращает адрес созданного узла

один символ, число

Построение дереваСтруктура узлаstruct Node { char data; Node *left, *right; };typedef Node *PNode;Создание узла для числа (без

Слайд 38Построение дерева
//--------------------------------------------
// Функция MakeTree – построение дерева
// Вход: строка, номера

первого и последнего // символов рассматриваемой части
// Выход:

адрес построенного дерева
//--------------------------------------------
PNode MakeTree ( char Expr[], int first, int last )
{
PNode Tree;
int k;
if ( first == last )
return NumberNode ( Expr[first] );
k = LastOperation ( Expr, first, last );
Tree = new Node;
Tree->data = Expr[k];
Tree->left = MakeTree ( Expr, first, k-1 );
Tree->right = MakeTree ( Expr, k+1, last );
return Tree;
}

осталось только число

новый узел: операция

Построение дерева//--------------------------------------------// Функция MakeTree – построение дерева// Вход: строка, номера первого и последнего //

Слайд 39Вычисление выражения по дереву
//--------------------------------------------
// Функция CalcTree – вычисление по дереву
//

Вход: адрес дерева
// Выход: значение выражения
//--------------------------------------------
int CalcTree (PNode Tree)
{
int

num1, num2;
if ( ! Tree->left ) return Tree->data - '0';
num1 = CalcTree( Tree->left);
num2 = CalcTree(Tree->right);
switch ( Tree->data ) {
case '+': return num1+num2;
case '-': return num1-num2;
case '*': return num1*num2;
case '/': return num1/num2;
}
return 32767;
}

вернуть число, если это лист

вычисляем операнды (поддеревья)

выполняем операцию

некорректная операция

Вычисление выражения по дереву//--------------------------------------------// Функция CalcTree – вычисление по дереву// Вход: адрес дерева// Выход: значение выражения//--------------------------------------------int CalcTree

Слайд 40Основная программа
//--------------------------------------------
// Основная программа: ввод и вычисление
// выражения с помощью

дерева
//--------------------------------------------
void main()
{
char s[80];
PNode Tree;
printf ( "Введите выражение

> " );
gets(s);
Tree = MakeTree ( s, 0, strlen(s)-1 );
printf ( "= %d \n", CalcTree ( Tree ) );
getch();
}

Слайд 41Дерево игры
Задача. Перед двумя игроками лежат две кучки камней, в

первой из которых 3, а во второй – 2 камня.

У каждого игрока неограниченно много камней.
Игроки ходят по очереди. Ход состоит в том, что игрок или увеличивает в 3 раза число камней в какой-то куче, или добавляет 1 камень в какую-то кучу.
Выигрывает игрок, после хода которого общее число камней в двух кучах становится не менее 16.
Кто выигрывает при безошибочной игре – игрок, делающий первый ход, или игрок, делающий второй ход? Как должен ходить выигрывающий игрок?
Дерево игрыЗадача.  Перед двумя игроками лежат две кучки камней, в первой из которых 3, а во

Слайд 42Дерево игры
3, 2
игрок 1
3, 6
27, 2
3, 18
3, 3
4, 2
12, 2
4,

6
5, 2
4, 3
9, 3
4, 3
36, 2
4, 18
15, 2
27, 3
игрок 1
игрок

2

игрок 2

9, 2

4, 3

4, 3

ключевой ход

выиграл игрок 1

Дерево игры3, 2игрок 13, 627, 23, 183, 34, 212, 24, 65, 24, 39, 34, 336, 24, 1815,

Обратная связь

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

Email: Нажмите что бы посмотреть 

Что такое TheSlide.ru?

Это сайт презентации, докладов, проектов в PowerPoint. Здесь удобно  хранить и делиться своими презентациями с другими пользователями.


Для правообладателей

Яндекс.Метрика