Advertisement
Guest User

Untitled

a guest
Dec 5th, 2019
100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.03 KB | None | 0 0
  1. #include "pch.h"
  2. #include <iostream>
  3. #include <conio.h>
  4. #include <stdlib.h>
  5.  
  6. using namespace std;
  7.  
  8. const unsigned char KEY_MAX_LENGTH = 5;
  9.  
  10. struct node                                                 //Представление узла дерева
  11. {
  12.     int key;                                                //Ключ узла
  13.     unsigned char height;                                   //Высота поддерева с корнем в данном узле
  14.     node* left;                                             //Указатель на левое поддерево
  15.     node* right;                                            //Указатель на правое поддерево
  16.  
  17.     node(int k)                                             //Конструктор создаёт новый узел (высота 1) с заданным ключом "k"
  18.     {
  19.         key = k;                                            //Заданныйы ключ для конструктора
  20.         left = right = nullptr;                             //Указатели на левое и правое поддерево не указывают не на что, потому что этих поддеревьев нет
  21.         height = 1;                                         //Выосота
  22.     }
  23. };
  24.  
  25. unsigned char height(node* p)                               //Вычисляет высоту дерева (даже, если оно пустое)
  26. {
  27.     if (p)
  28.     {
  29.         return p->height;                                   //Если дерево не пустое, то выводим его высоту
  30.     }
  31.     else
  32.     {
  33.         return 0;                                           //Если дерево пустое, то выводим его высоту ("ноль")
  34.     }
  35. }
  36.  
  37. int bfactor(node* p)                                        //Вычисляет "Balance factor" заданного узла (работает только с ненулевыми указателями)
  38. {
  39.     return height(p->right) - height(p->left);              //"Balance factor" - это разница высот между правым и левым поддеревьями
  40. }
  41.  
  42. void fixheight(node* p)                                     //Функция восстановления корректного значения поля height заданного узла (при условии, что значения этого поля в правом и левом дочерних узлах являются  корректными)
  43. {
  44.     unsigned char hl = height(p->left);                     //Вычисление высоты левого поддерева
  45.     unsigned char hr = height(p->right);                    //Вычисление высоты правого поддерева
  46.  
  47.     if (hl > hr)
  48.     {
  49.         p->height = hl + 1;
  50.     }
  51.     else
  52.     {
  53.         p->height = hr + 1;
  54.     }
  55. }
  56.  
  57. node* rotateleft(node* q)                                   //Левый поворот
  58. {
  59.     node* p = q->right;
  60.     q->right = p->left;
  61.     p->left = q;
  62.  
  63.     fixheight(q);
  64.     fixheight(p);
  65.  
  66.     return p;
  67. }
  68.  
  69. node* rotateright(node* p)                                  //Правый поворот  
  70. {
  71.     node* q = p->left;
  72.     p->left = q->right;
  73.     q->right = p;
  74.  
  75.     fixheight(p);
  76.     fixheight(q);
  77.  
  78.     return q;
  79. }
  80.  
  81. node* balance(node* p)                                      //Фкнкция балансировки
  82. {                                                           //Балансоровка сводится к проверке услоовий и выполнению поворотов
  83.     fixheight(p);                                           //Восстановим корректное значение высоты узла
  84.  
  85.     if (bfactor(p) == 2)                                    //Если разница между высотой правого и левого поддеревьв этого узла равна 2, то узнаем разницу между высотой правого и левого поддеревьев его правого поддерева                    
  86.     {
  87.         if (bfactor(p->right) < 0)                          //И если эта разница окажется меньше "0", то правое поддерево "стартового" узла совершит правый поворот
  88.         {
  89.             p->right = rotateright(p->right);
  90.         }
  91.  
  92.         return rotateleft(p);                               //В конце совершим левый поворот для обрабатываемого узла
  93.     }
  94.  
  95.     if (bfactor(p) == -2)                                   //Если разница между высотой правого и левого поддеревьв этого узла равна -2, то узнаем разницу между высотой правого и левого поддеревьев его левого поддерева                     
  96.     {
  97.         if (bfactor(p->left) > 0)                           //И если эта разница окажется больше "0", то левое поддерево "стартового" узла совершит левый поворот
  98.  
  99.         {
  100.             p->left = rotateleft(p->left);
  101.         }
  102.  
  103.         return rotateright(p);                              //В конце совершим правый поворот для обрабатываемого узла
  104.     }
  105.     return p;
  106. }
  107.  
  108. node* insert(node* p, int k)                                //Функция вставки нового ключа в АВЛ-дерево выполняется с помощью спуска вниз по дереву, выбирая направление (правое или левое)
  109. {
  110.     if (!p)                                                 //Если этого узла ещё не существует, то сюда и вставляем                                       
  111.     {
  112.         return new node(k);
  113.     }
  114.  
  115.     if (k < p->key)                                         //Если вставляемый ключ меньше ключа проверяемого узла, то  идёт вставка в левое поддерево
  116.     {
  117.         p->left = insert(p->left, k);
  118.     }
  119.  
  120.     else                                                    //Если вставляемый ключ больше ключа проверяемого узла, то  идёт вставка в правое поддерево
  121.     {
  122.         p->right = insert(p->right, k);
  123.     }
  124.  
  125.     return balance(p);                                      //Баланисруем текущий узел
  126. }
  127.  
  128. node* findmin(node* p)                                      //Функция поиска узла с минимальным ключом
  129. {
  130.     if (p->left)                                            //Спускаемся влево
  131.     {
  132.         return findmin(p->left);
  133.     }
  134.     else
  135.     {
  136.         return p;                                           //Самый левый узел будет содержать ключ с минимальным значением
  137.     }
  138. }
  139.  
  140. node* removemin(node* p)                                    //Функция даления узла с минимальным ключом
  141. {
  142.     if (p->left == 0)                                       //По определению АВЛ-дерева, у минимального элемента справа либо подвешен единственный узел, либо там пусто
  143.     {
  144.         return p->right;                                    //В обоих случаях надо вернуть указатель на правый узел
  145.     }
  146.  
  147.     p->left = removemin(p->left);
  148.  
  149.     return balance(p);                                      //И по пути назад выполинть балансировку
  150. }
  151.  
  152. node* remove(node* p, int k)                                //Функция удаления ключа из дерева
  153. {
  154.     if (!p)                                                 //Если дерево пустое, то нечего удалять
  155.     {
  156.         return 0;
  157.     }
  158.  
  159.     if (k < p->key)                                         //Спускаемся вниз, пока не найдём наш ключ
  160.     {
  161.         p->left = remove(p->left, k);
  162.     }
  163.  
  164.     else {
  165.         if (k > p->key)
  166.         {
  167.             p->right = remove(p->right, k);
  168.         }
  169.         else                                                //Как только находим
  170.         {
  171.             node* q = p->left;                              //Запомним в "q" левое поддерево узла, который собираемся удалять
  172.             node* r = p->right;                             //Запомним в "r" правое поддерево узла, который собираемся удалять
  173.  
  174.             delete p;                                       //Удаляем сам узел
  175.  
  176.             if (!r)                                         //Если правое поддерерво пустое, то возвращаем указатель на левое поддерево
  177.             {
  178.                 return q;
  179.             }
  180.  
  181.             node* min = findmin(r);                         //Если правое поддерерво не пустое, то находим там минимальный элемент "min"
  182.  
  183.             min->right = removemin(r);                      //Справа подвесим к "min" то, что получилось из "r"
  184.             min->left = q;                                  //Слева подвесим к min "q"
  185.  
  186.             return balance(min);                            //Возвращаем "min" после его балансировки
  187.         }
  188.     }
  189.     return balance(p);                                      //После выхода из рекурсии выполняем балансировку
  190. }
  191.  
  192. bool search(node* p, int k)                                 //Функция поиска ключа           
  193. {
  194.     bool res = false;
  195.  
  196.     if (p)                                                  //Если дерево пустое, то нет смысла искать
  197.     {
  198.         if (k == p->key)                                    //Если нашли, получаем истину
  199.         {
  200.             return true;
  201.         }
  202.         if (k < p->key)                                     //Если ключ, который мы ищем меньше того, на котором мы остановились, то спусакамся влево
  203.         {
  204.             res = search(p->left, k);
  205.         }
  206.         if (k > p->key)                                     //Если ключ, который мы ищем больше того, на котором мы остановились, то спусакамся вправо
  207.         {
  208.             res = search(p->right, k);
  209.         }
  210.     }
  211.     return res;                                             //Если после всего дерева такого ключа нет, то получаем ложь
  212. }
  213.  
  214. void printGL(node* p, int height)                           //Функция вывода АВЛ-дерева
  215. {
  216.     if (p)                                                  //Если дерево пустое, то нет смысла выводить
  217.     {
  218.         if (p->left)
  219.         {
  220.             height--;
  221.             printGL(p->left, height);
  222.             height++;
  223.         }
  224.         for (int i = 0; i < height; i++)
  225.         {
  226.             cout << "\t";
  227.         }
  228.         cout << p->key;
  229.         cout << endl;
  230.  
  231.         if (p->right)
  232.         {
  233.             height--;
  234.             printGL(p->right, height);
  235.             height++;
  236.         }
  237.     }
  238. }
  239.  
  240. int main()
  241. {
  242.     char choice = 0;
  243.     node* p = nullptr;
  244.     do {
  245.         system("cls");
  246.         cout << "Please, make a choice: " << endl;
  247.  
  248.         cout << "1 - add" << endl;
  249.         cout << "2 - remove" << endl;
  250.         cout << "3 - search" << endl;
  251.         cout << "4 - print" << endl;
  252.  
  253.         choice = _getch();
  254.         switch (choice) {
  255.         case '1':
  256.             int a;
  257.             cout << "Enter a key: ";
  258.  
  259.             cin >> a;
  260.  
  261.             if (!p) {
  262.                 p = new node(a);
  263.             }
  264.             else {
  265.                 if (search(p, a)) {
  266.                     cout << a << " already exist!" << endl;
  267.                 }
  268.                 else {
  269.                     p = insert(p, a);
  270.                     cout << "insertion of " << a << " has been made succesfully" << endl;
  271.                 }
  272.             }
  273.             system("pause");
  274.             break;
  275.         case '2':
  276.             if (p) {
  277.                 cout << "Enter a key that you wanna remove: ";
  278.                 int a;
  279.                 cin >> a;
  280.                 if (search(p, a)) {
  281.                     p = remove(p, a);
  282.                     cout << "remove of " << a << " has been made succesfully" << endl;
  283.                 }
  284.                 else {
  285.                     cout << a << " doesn't exist!" << endl;
  286.                 }
  287.             }
  288.             else {
  289.                 cout << "Your tree is empty" << endl;
  290.             }
  291.             system("pause");
  292.             break;
  293.         case '3':
  294.             if (p) {
  295.                 cout << "Enter a key that you wanna search: ";
  296.                 int a;
  297.                 cin >> a;
  298.                 if (search(p, a))
  299.                     cout << a << " has been found succesfully" << endl;
  300.                 else
  301.                     cout << a << " has not been found" << endl;
  302.             }
  303.             else {
  304.                 cout << "Your tree is empty" << endl;
  305.             }
  306.             system("pause");
  307.             break;
  308.         case '4':
  309.             if (p) {
  310.                 cout << "Your tree: " << endl;
  311.                 printGL(p, p->height - 1);
  312.             }
  313.             else {
  314.                 cout << "Your tree is empty" << endl;
  315.             }
  316.             system("pause");
  317.             break;
  318.         }
  319.     } while (choice != 27);
  320.     _getch();
  321. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement