Коды Прюфера — различия между версиями
| м (ё) | м (rollbackEdits.php mass rollback) | ||
| (не показаны 3 промежуточные версии 3 участников) | |||
| Строка 6: | Строка 6: | ||
| # Вершина <tex>v</tex> и инцидентное ей ребро удаляются из дерева. | # Вершина <tex>v</tex> и инцидентное ей ребро удаляются из дерева. | ||
| <br> | <br> | ||
| − | Полученная последовательность называется '''кодом Прюфера''' ''(англ.  | + | Полученная последовательность называется '''кодом Прюфера''' ''(англ. Prüfer code)'' для заданного дерева. | 
| {{Лемма | {{Лемма | ||
| Строка 49: | Строка 49: | ||
| == Пример построения кода Прюфера == | == Пример построения кода Прюфера == | ||
| [[Файл: Prufer.png|500px]] | [[Файл: Prufer.png|500px]] | ||
| + | |||
| + | == Алгоритм декодирования кодa Прюфера == | ||
| + | |||
| + | В массиве вершин исходного дерева <tex>V</tex> найдём вершину <tex>v_{min}</tex> с минимальным номером, не содержащуюся в массиве с кодом Прюфера <tex>P</tex>, т.е. такую, что она является листом или концом уже добавленного в граф ребра, т.е. она стала листом в процессе построения кода Прюфера (по первому пункту построения). Вершина <tex>p_1</tex> была добавлена в код Прюфера как инцидентная листу с минимальным номером (по второму пункту построения), поэтому в исходном дереве существует ребро {<tex>p_1</tex>, <tex>v_{min}</tex>}, добавим его в список ребер. Удалим первый элемент из массива <tex>Р</tex>, а вершину <tex>v_{min}</tex> - из массива <tex>V</tex> т.к. она больше не может являться листом (по третьему пункту построения). Будем выполнять вышеуказанные действия, пока массив <tex>P</tex> не станет пустым. В конце работы алгоритма в массиве <tex>V</tex> останутся две вершины, составляющие последнее ребро дерева (это следует из построения). | ||
| + | |||
| + | === Реализация === | ||
| + |  # P - код Прюфера | ||
| + |  # V - вершины | ||
| + |  '''function''' buildTree(P, V): | ||
| + |     '''while'' '''not'' P.empty(): | ||
| + |        u = P[0] | ||
| + |        v = min(x '''<tex>\in</tex>''' V: P.count(x) == 0) | ||
| + |        G.push({u, v}) | ||
| + |        P.erase(0) | ||
| + |        V.erase(indexOf(v)) | ||
| + |     G.push({v[0], v[1]}) | ||
| + |     '''return''' G | ||
| + | |||
| == Пример декодирования кода Прюфера == | == Пример декодирования кода Прюфера == | ||
Текущая версия на 19:06, 4 сентября 2022
Содержание
Алгоритм построения кодов Прюфера
Кодирование Прюфера переводит помеченные деревья порядка  в последовательность чисел от  до  по алгоритму:
Пока количество вершин больше двух:
- Выбирается лист с минимальным номером.
- В код Прюфера добавляется номер вершины, смежной с .
- Вершина и инцидентное ей ребро удаляются из дерева.
Полученная последовательность называется кодом Прюфера (англ. Prüfer code) для заданного дерева.
| Лемма: | 
| Номер вершины  встречается в коде Прюфера тогда и только тогда, когда  не является листом, причём встречается этот номер к коде дерева в точности  раз. | 
| Доказательство: | 
| 
 | 
| Лемма: | 
| По любой последовательности длины  из чисел от  до  можно построить помеченное дерево,
для которого эта последовательность является кодом Прюфера. | 
| Доказательство: | 
| Доказательство проведем по индукции по числу  верно. Индукционный переход: Пусть для числа верно, построим доказательство для : Пусть у нас есть последовательность:Выберем минимальное число не лежащее в . По предыдущей лемме вершина, которую мы удалили первой. Соединим и ребром. Выкинем из последовательности число . Перенумеруем вершины, для всех заменим на . А теперь мы можем применить предположение индукции. | 
| Теорема: | 
| Кодирование Прюфера задаёт биекцию между множествами помеченных деревьев порядка  и последовательностями длиной  из чисел от  до  | 
| Доказательство: | 
| 
 | 
Следствием из этой теоремы является формула Кэли.
Пример построения кода Прюфера
Алгоритм декодирования кодa Прюфера
В массиве вершин исходного дерева найдём вершину с минимальным номером, не содержащуюся в массиве с кодом Прюфера , т.е. такую, что она является листом или концом уже добавленного в граф ребра, т.е. она стала листом в процессе построения кода Прюфера (по первому пункту построения). Вершина была добавлена в код Прюфера как инцидентная листу с минимальным номером (по второму пункту построения), поэтому в исходном дереве существует ребро {, }, добавим его в список ребер. Удалим первый элемент из массива , а вершину - из массива т.к. она больше не может являться листом (по третьему пункту построения). Будем выполнять вышеуказанные действия, пока массив не станет пустым. В конце работы алгоритма в массиве останутся две вершины, составляющие последнее ребро дерева (это следует из построения).
Реализация
# P - код Прюфера
# V - вершины
function buildTree(P, V):
   while not P.empty():
      u = P[0]
      v = min(x  V: P.count(x) == 0)
      G.push({u, v})
      P.erase(0)
      V.erase(indexOf(v))
   G.push({v[0], v[1]})
   return G
Пример декодирования кода Прюфера
См. также
- Связь матрицы Кирхгофа и матрицы инцидентности
- Матрица Кирхгофа
- Количество помеченных деревьев
- Подсчет числа остовных деревьев с помощью матрицы Кирхгофа


