# Практикум №7 по Структури от данни, спец. ИС ## Какво е дърво? ***Дървото*** е йерархична структура от данни, съставена от **върхове** и **ръбове**. То започва с един основен връх, наречен **корен** (root), от който се разклоняват други върхове (наричани **деца**), образувайки по-малки поддървета. ### Основни термини и характеристики: - **корен** (root): началният връх на дървото, който няма родител - **връх** (node): всеки елемент в дървото - **деца**: върховете, които са непосредствено свързани към даден връх - **родител**: връх, който има деца - **листо** (leaf): връх, който няма деца - **вътрешен връх**: връх, който има поне едно дете и не е листо - **поддърво**: множеството от върхове, което включва даден връх и всичките му наследници - **височина на връх**: максималното разстояние от този връх до някое листо в неговото поддърво - **дълбочина на връх**: разстоянието от този връх до корена на дървото - **разклоненост**: максималният брой деца, които има който и да е връх в дървото > **Note:** Нека `T` е дърво с корен `r`, и `v` е връх в `T`: > - **Поддървото, вкоренено** във `v`, включва `v` и всички негови наследници
> - **Височината** на `v` е максималното разстояние от `v` до някое листо в поддървото му
> - **Дълбочината** на v е разстоянието от `v` до корена `r` на `T` ![binaryTree.png](binaryTree.png) ## Основни алгоритми за обхождане на двоично дърво **Обхождането** на дърво е процесът на посещаване на всеки връх в определен ред. Съществуват два основни начина за обхождане на дървета: ### 1. Обхождане в дълбочина (DFS) При **DFS** преминаваме на максимална дълбочина в поддървото, преди да се върнем към съседни възли на по-горно ниво. **Сложност:** O(n), където n е броя на върховете в дървото. Съществуват три основни типа обхождане в дълбочина: #### 1.1 Префиксно обхождане (Preorder) При префиксното обхождане винаги посещаваме текущия връх преди неговите деца. Коренът на дървото е първият връх, който се посещава. Започваме, като следваме пътя наляво, посещавайки всеки връх по реда на срещането му. Когато достигнем листо, се връщаме назад и продължаваме с дясната част на дървото, като отново посещаваме върховете в реда на срещането им. Първо се обработва коренът, след това лявото поддърво и накрая дясното поддърво.
**_Корен → Ляво поддърво → Дясно поддърво_**
![preorder.gif](preorder.gif) #### 1.2 Инфиксно обхождане (Inorder) Първо се обработва лявото поддърво, след това коренът и накрая дясното поддърво.
**_Ляво поддърво → Корен → Дясно поддърво_** > **Забележка:** При двоичните дървета за търсене (**BST**) този тип обхождане извежда елементите в сортиран ред. ![inorder.gif](inorder.gif) #### 1.3 Постфиксно обхождане (Postorder) При постфиксното обхождане първо посещаваме децата на възела, преди да посетим самия него. Първо се обработва лявото поддърво, след това дясното поддърво и накрая коренът.
**_Ляво поддърво → Дясно поддърво → Корен_** ![postorder.gif](postorder.gif) ### 2. Обхождане в ширoчина (BFS) При **BFS** се преминава през възлите ниво по ниво, започвайки от корена и преминавайки към всяко следващо ниво. Изследват се всички възли на дадено ниво, преди да се премине към следващото ниво. Най-често се използва **опашка** (queue), за да се следи реда на върховете, които трябва да се посетят. Започваме от корена, добавяме го в опашката и след това последователно добавяме неговите деца, докато обработваме всеки връх. **Сложност:** O(n), където n е броя на върховете в дървото. ![tree-dfs-vs-bfs.gif](tree-dfs-vs-bfs.gif) ## Задачи [Линк към задачите](https://leetcode.com/problem-list/aw76m7ld/)