Website Summary Files Commits Branches @commit @diff @stats
diff options
context:
space:
mode:
Commit496341d47228944b97b084f17ab086da191a11f1 (patch)
Author
 Stoycho Kyosev <stoycho.kk@gmail.com>
2022-12-07 22:05:42 +0200
Committer
 Stoycho Kyosev <stoycho.kk@gmail.com>
2022-12-07 22:05:42 +0200
Files9dd98ad27ab159b86a0413a8542f1adb4471ec10
Data-structures-and-algorithms-496341d47228944b97b084f17ab086da191a11f1.tar
Data-structures-and-algorithms-496341d47228944b97b084f17ab086da191a11f1.tar.gz
Data-structures-and-algorithms-496341d47228944b97b084f17ab086da191a11f1.zip
Parent51d55feba53fb7af4901147922cc9a212e62ecbc (diff)
Add first half of Seminar09
1 files changed, 105 insertions, 0 deletions
-rw-r--r--Seminar09/README.md105
diff --git a/Seminar09/README.md b/Seminar09/README.md
new file mode 100644
index 0000000..c167b2e
--- /dev/null
+++ b/Seminar09/README.md
@@ -0,0 +1,105 @@
+# Дървета - част 2. Балансирани дървета, ротации и задачи върху дървета.
+
+## Минимум и максимум в дърво
+Последния семинар разглеждахме задачата за намиране на минимален или максимален елемент в дърво. Тази задача е сравнително лесна, но нека разгледаме следния случай:
+
+```cpp
+template<class T>
+T maxElem(const Tree<T>* t) {
+ T result = t->data;
+
+ if(t->left != nullptr)
+ result = std::max(result, maxElem(t->left));
+
+ if(t->right != nullptr)
+ result = std::max(result, maxElem(t->right));
+
+ return result;
+}
+```
+Това решение работи почти винаги. Какво става ако t e nullptr?
+
+Ако знаехме, че дървото е от тип int, лесно можехме да връщаме INT_MAX, но в случая не знаем какъв тип е скрит зад Т.
+Един от начините да се справим с този проблем е да връщаме T* вместо Т. Така, ако дървото е nullptr ние също ще връщаме nullptr. Това е валиден начин, и може би стандартния начин по който бихме подходили в С или във версиите на С++ преди С++17.
+
+## std::optional\<T>
+std::optional\<T> е клас който в някакъв смисъл "обвива" елемент от тип Т. Както името подсказва той или има стойност.. или няма.
+Този тип се поддържа от с++17, та ако искате да го използвате бъдете сигурни, че компилирате с правилната версия на с++.
+
+Примерно, кодът използвайки std::optional би изглеждал по следния начин:
+
+```cpp
+#include<optional>
+#include"tree-utils.h"
+
+template<class T>
+std::optional<T> max(const Tree<T>* t) {
+ if (t == nullptr)
+ return {}; // Това означава, че std::optional<T> няма стойност
+
+ std::optional<T> left = max(t->left); // Вземи макса на левия
+ std::optional<T> right = max(t->left); // Вземи макса на десния
+
+ T res = t->data;
+ // Ако левия има value тоест дървото не е празно...
+ if (left.has_value() && left.value() > res)
+ res = left.value();
+
+ // Аналогично за десния
+ if (right.has_value() && right.value() > res)
+ res = right.value();
+
+ return res;
+}
+
+int main() {
+ Tree<int>* t = nullptr;
+ std::optional<int> result = max(t);
+
+ if(result.has_value())
+ std::cout << "Max element is: " << result.value() << std::endl;
+ else
+ std::cout << "Empty tree!!";
+}
+```
+Логиката зад std::optional далеч не идва от с++. Езици като Haskell, Rust и други поддържат подобни структури.
+
+## Балансирани дървета
+Последния семинар дефинирахме височина на дърво и се разбрахме, че това ще бъде важно понятие за нас. Намекнахме, че е желателно да държим дърветата си ниски. Едно свойство на дърветата, което ги държи сравнително ниски е **балансираността.**
+
+Двоично дърво наричаме **балансирано** ако за всеки негов възел височините на лявото поддърво и на дясното поддърво се различават **най - много с единица**.
+
+Също така дърво ще наричаме **идеално балансирано** ако за всеки негов възел броя на възлите в лявото поддърво и броя на възлите в дясното поддърво се различават най - много с единица.
+
+В балансираните и идеално балансираните дървета сложността на операциите добавяне, търсене, изтриване стават O(log<sub>2</sub>(n)).
+
+С балансирани дървета ще се занимаваме много подробно следващия път. Засега само дефинираме неща, които ще ни бъдат от голяма полза при реализацията на едно такова дърво.
+
+## Ротации и запазване на балансираността
+
+Ще бъдат качени на 8ми за да имам време да систематизирам информацията. Извинявам се за забавянето!
+
+## Задача първа
+Да се напише функция, която проверява дали дадено дърво е двоично наредено дърво.
+
+## Задача втора
+Да се напише функция, която от сортиран вектор построява двоично наредено дърво.
+
+## Задача трета
+Да се напише функция, която премахва възел от двоично наредено дърво.
+
+## Задача четвърта
+Да се напише функция, която проверява дали две дървета са еднакви.
+
+## Задача пета
+Да се реализират ляво и дясна ротация за произволно дърво.
+
+## Задача шеста (За домашно)
+Нека имаме двоично наредено дърво T от цели числа.
+pred(x) = max{y | y е ключ на възел в Т и y < x} // Предшественик
+succ(x) = min{y | y е ключ на възел в T и y > x} // Наследник
+Да се реализира pred(t, x) и succ(t, x).
+Бележка: Не е нужно х да се съдържа в дървото.
+
+## Задача седма (Контролно)
+Да се напише функция, която намира сумата на всички елементи на двоично наредено дърво от цели числа, които имат нечетен брой наследници в интервала [x, y] (т.е. сумата на броя елементи в лявото поддърво и броя елементи в дясното поддърво в интервала [x, y] е нечетно число). Нека x и y са параметри на функцията. \ No newline at end of file