Sanady

Untitled

Dec 9th, 2019
353
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.81 KB | None | 0 0
  1. // Tema: Binarny vyhladavaci strom
  2. // Autor: Pavol Marak
  3.  
  4. #define _CRT_SECURE_NO_WARNINGS
  5. #include <iostream>
  6. #include <string>
  7. #include <queue>
  8. using namespace std;
  9.  
  10. // Binarny vyhladavaci strom je datova struktura
  11. // umoznujuca rychle vyhladavanie uzlov.
  12. //
  13. // Vlastnost:
  14. //  * pre lubovolny uzol U v strome plati:
  15. //      a) uzly v lavom podstrome su mensie ako U
  16. //      b) uzly v pravom podstrome su vacsie ako U
  17. //  * vsetky uzly v strome su unikatne
  18.  
  19. // uzol binarneho vyhladavacieho stromu
  20. struct Node {
  21.     int value; // hodnota uzla
  22.     Node *left; // smernik na laveho potomka
  23.     Node *right; // smernik na praveho potomka
  24. };
  25.  
  26. // strom
  27. struct Tree {
  28.     Node *root; // koren stromu
  29. };
  30.  
  31. // rekurzivna funkcia na pridanie uzla do stromu
  32. Node* addNodeRecursive(Node* root, const int value){
  33.     if(root){
  34.         if(value < root->value){
  35.             root->left = addNodeRecursive(root->left,value);
  36.         }
  37.         else if(value > root->value){
  38.             root->right = addNodeRecursive(root->right,value);
  39.         }
  40.         else{
  41.             throw string{"uzol sa uz v strome nachadza"};
  42.         }
  43.         return root;
  44.     }
  45.     return new Node{value,nullptr,nullptr};
  46. }
  47.  
  48. // funkcia na pridanie uzla do stromu
  49. void addNode(Tree* tree, const int value){
  50.     tree->root = addNodeRecursive(tree->root,value);
  51. }
  52.  
  53. // funkcia, ktora vrati novy binarny vyhladavaci strom
  54. // vytvoreny z hodnot inicializacneho zoznamu
  55. Tree* createTree(const initializer_list<int>& i){
  56.     Tree* tree{new Tree{nullptr}};
  57.     // pridavanie do stromu
  58.     cout << "Pridavanie uzlov do stromu:" << endl << endl;
  59.     for(const int u: i){
  60.         cout << "Uzol " << u << ": ";
  61.         try {
  62.             addNode(tree,u);
  63.             cout << "bol pridany" << endl;
  64.         } catch (const string& e) {
  65.             cout << e << endl;
  66.         }
  67.     }
  68.     return tree;
  69. }
  70.  
  71. // funkcia na vyhladanie uzla v strome
  72. // ak bol uzol najdeny, funkcia vrati jeho adresu
  73. // ak uzol nebol najdeny, funkcia vrati 'nullptr'
  74. Node* searchNode(Tree* tree, const int value){
  75.     Node* tmp = tree->root;
  76.     while(tmp){
  77.         if(value < tmp->value){
  78.             tmp = tmp->left; // vnorenie do laveho podstromu
  79.         }
  80.         else if(value > tmp->value){
  81.             tmp = tmp->right; // vnorenie do praveho podstromu
  82.         }
  83.         else{
  84.             // nasli sme hladany uzol
  85.             return tmp;
  86.         }
  87.     }
  88.     // nenasli sme hladany uzol
  89.     return nullptr;
  90. }
  91.  
  92. // funkcia na vyhladanie minimalneho uzla v
  93. // binarnom vyhladavacom strome
  94. Node* findMinNode(Node* node){
  95.     Node* minNode{nullptr};
  96.     while(node){
  97.         minNode = node;
  98.         node = node->left;
  99.     }
  100.     return minNode;
  101. }
  102.  
  103. // Alternativa 1 - nerekurzivna verzia
  104. // funkcia na vymazanie uzla s hodnotou 'value' zo stromu
  105. // ak bol uzol vymazany, funkcia vrati 'true'
  106. // ak nebol uzol vymazany, funkcia vrati 'false'
  107. bool removeNode1(Tree* tree, int value){
  108.     Node* child{nullptr}, *prev{nullptr};
  109.     Node* tmp = tree->root;
  110.     bool left_right{false}; // 0 - left, 1 - right
  111.     while(tmp){
  112.         // navigacna cast
  113.         if(value < tmp->value){
  114.             prev = tmp;
  115.             left_right = 0;
  116.             tmp = tmp->left;
  117.         }
  118.         else if(value > tmp->value){
  119.             prev = tmp;
  120.             left_right = 1;
  121.             tmp = tmp->right;
  122.         }
  123.         // nasli sme uzol, ktory ideme vymazat
  124.         else{
  125.             // existuje len lavy potomok alebo ziadny potomok
  126.             if(!tmp->right){
  127.                 child = tmp->left;
  128.             }
  129.             // existuje len pravy potomok alebo ziadny potomok
  130.             else if(!tmp->left){
  131.                 child = tmp->right;
  132.             }
  133.             // existuju sucasne obidvaja potomkovia
  134.             else{
  135.                 // musime najst najmensi uzol v pravom podstrome od uzla 'tmp'
  136.                 // tzv. inorder successor
  137.                 Node* tmp2 = findMinNode(tmp->right);
  138.                 // a skopirovat jeho hodnotu do 'tmp'
  139.                 tmp->value = tmp2->value;
  140.                 // potom vymazeme inorder successora v pravom podstrome
  141.                 prev = tmp;
  142.                 tmp = tmp->right;
  143.                 left_right = 1;
  144.                 value = tmp2->value;
  145.                 continue;
  146.             }
  147.             // vymazavacia cast
  148.             delete tmp;
  149.             // ak vymazavame koren stromu
  150.             if(!prev){
  151.                 tree->root = child;
  152.             }
  153.             else{
  154.                 if(!left_right){
  155.                     prev->left = child;
  156.                 }
  157.                 else{
  158.                     prev->right = child;
  159.                 }
  160.             }
  161.             return true;
  162.         }
  163.     }
  164.     // uzol s hodnotou 'value' sa v strome nenachadzal
  165.     return false;
  166. }
  167.  
  168. // rekurzivna funkcia na vymazanie uzla s hodnotou 'value' zo stromu
  169. Node* removeNode2Recursive(Node* root, const int value){
  170.     if(!root){
  171.         return root;
  172.     }
  173.     if(value < root->value){
  174.         root->left = removeNode2Recursive(root->left,value);
  175.     }
  176.     else if(value > root->value){
  177.         root->right = removeNode2Recursive(root->right,value);
  178.     }
  179.     // nasli sme uzol, ktory sa vymaze
  180.     else{
  181.         // 'root' ma len laveho potomka
  182.         if(!root->right){
  183.             Node* tmp = root->left;
  184.             delete root;
  185.             return tmp;
  186.         }
  187.         // 'root' ma len praveho potomka
  188.         else if(!root->left){
  189.             Node* tmp = root->right;
  190.             delete root;
  191.             return tmp;
  192.         }
  193.         // 'root' ma obidvoch potomkov
  194.         else{
  195.             // najdeme najmensi uzol v pravom podstrome 'root'
  196.             Node* smallestNode = findMinNode(root->right);
  197.             // skopirujem jeho hodnotu do 'root'
  198.             root->value = smallestNode->value;
  199.             // vymazeme ho
  200.             root->right = removeNode2Recursive(root->right,smallestNode->value);
  201.         }
  202.     }
  203.     return root;
  204. }
  205.  
  206. // Alternativa 2 - tato funkcia vyuziva rekurzivnu funkciu
  207. // na vymazanie uzla
  208. // funkcia na vymazanie uzla s hodnotou 'value' zo stromu
  209. void removeNode2(Tree* tree, int value){
  210.     tree->root = removeNode2Recursive(tree->root,value);
  211. }
  212.  
  213. // rekurzivna funkcia na vymazanie vsetkych uzlov v strome
  214. // pozn. treba prejst stromom v style postorder
  215. void removeTreeRecursive(Node* root){
  216.     if(root){
  217.         removeTreeRecursive(root->left);
  218.         removeTreeRecursive(root->right);
  219.         delete root;
  220.     }
  221. }
  222.  
  223. // funkcia na vymazanie vsetkych uzlov v strome aj samotneho stromu
  224. void removeTree(Tree** tree){
  225.     removeTreeRecursive((*tree)->root);
  226.     delete *tree;
  227.     *tree = nullptr;
  228. }
  229.  
  230. // rekurzivna funkcia na prechod stromom v style preorder
  231. void preorderRecursive(Node* root){
  232.     if(root){
  233.         cout << root->value << " ";
  234.         preorderRecursive(root->left);
  235.         preorderRecursive(root->right);
  236.     }
  237. }
  238.  
  239. // funkcia na prechod stromom v style preorder
  240. void preorder(Tree* tree){
  241.     preorderRecursive(tree->root);
  242. }
  243.  
  244. // rekurzivna funkcia na prechod stromom v style inorder
  245. void inorderRecursive(Node* root){
  246.     if(root){
  247.         inorderRecursive(root->left);
  248.         cout << root->value << " ";
  249.         inorderRecursive(root->right);
  250.     }
  251. }
  252.  
  253. // funkcia na prechod stromom v style inorder
  254. void inorder(Tree* tree){
  255.     inorderRecursive(tree->root);
  256. }
  257.  
  258. // rekurzivna funkcia na prechod stromom v style postorder
  259. void postorderRecursive(Node* root){
  260.     if(root){
  261.         postorderRecursive(root->left);
  262.         postorderRecursive(root->right);
  263.         cout << root->value << " ";
  264.     }
  265. }
  266.  
  267. // funkcia na prechod stromom v style postorder
  268. void postorder(Tree* tree){
  269.     postorderRecursive(tree->root);
  270. }
  271.  
  272. // funkcia na prechod stromom v style levelorder
  273. void levelorder(Tree* tree){
  274.     if(tree->root){
  275.         Node* tmp = tree->root;
  276.         queue<Node*> q;
  277.         q.push(tmp);
  278.         while(!q.empty()){
  279.             cout << q.front()->value << " ";
  280.             if(q.front()->left){
  281.                 q.push(q.front()->left);
  282.             }
  283.             if(q.front()->right){
  284.                 q.push(q.front()->right);
  285.             }
  286.             q.pop();
  287.         }
  288.     }
  289. }
  290.  
  291. // rekurzivna funkcia na zistenie hlbky uzla s hodnotou 'value'
  292. // poznamka: koren ma hlbku 0
  293. int depthNodeRecursive(Node* root, const int value){
  294.     if(root){
  295.         if(value < root->value){
  296.             return 1+depthNodeRecursive(root->left,value);
  297.         }
  298.         else if(value > root->value){
  299.             return 1+depthNodeRecursive(root->right,value);
  300.         }
  301.         else{
  302.             return 0;
  303.         }
  304.     }
  305.     throw string{
  306.         "Uzol s hodnotou " + to_string(value) + " sa v strome nenachadza"
  307.     };
  308. }
  309.  
  310. // funkcia na zistenie hlbky uzla s hodnotou 'value'
  311. // poznamka: koren ma hlbku 0
  312. int depthNode(Tree* tree, const int value){
  313.     return depthNodeRecursive(tree->root,value);
  314. }
  315.  
  316. // rekurzivna funkcia na zistenie hlbky stromu
  317. int depthTreeRecursive(Node* root){
  318.     if(root){
  319.         int leftDepth = 1+depthTreeRecursive(root->left);
  320.         int rightDepth = 1+depthTreeRecursive(root->right);
  321.         if(leftDepth>rightDepth){
  322.             return leftDepth;
  323.         }
  324.         return rightDepth;
  325.     }
  326.     return -1;
  327. }
  328.  
  329. // funkcia na zistenie hlbky stromu
  330. // poznamka: koren ma hlbku 0
  331. int depthTree(Tree* tree){
  332.     return depthTreeRecursive(tree->root);
  333. }
  334.  
  335. // testovacia funkcia pre binarny vyhladavaci strom
  336. void test_tree(){
  337.     // vytvorenie binarneho vyhladavacieho stromu z dodanych hodnot
  338.     Tree* tree = createTree({8,3,1,6,4,7,10,14,13,13});
  339.  
  340.     cout << endl;
  341.  
  342.     // vyhladavanie v strome
  343.     cout << "Vyhladavanie uzlov v strome:" << endl << endl;
  344.     Node* result_search{nullptr};
  345.     for(const int i: {8,6,13,100}){
  346.         result_search = searchNode(tree,i);
  347.         cout << "Uzol " << i << " " << (result_search?"":"ne") << "bol najdeny" << endl;
  348.     }
  349.     cout << endl;
  350.  
  351.     // odstranenie uzla (alterantiva 1)
  352.     cout << "Vymazavanie uzlov zo stromu:" << endl << endl;
  353.     bool result_remove_node;
  354.     for(const int i: {4,10,8,999}){
  355.         result_remove_node = removeNode1(tree,i);
  356.         cout << "Uzol " << i << " " << (result_remove_node?"":"ne") << "bol vymazany" << endl;
  357.     }
  358.     cout << endl;
  359.  
  360.     // odstranenie uzla (alternativa 2)
  361.     //    cout << "Vymazavanie uzlov zo stromu:" << endl << endl;
  362.     //    for(const int i: {1,7,-2,999}){
  363.     //        removeNode2(tree,i);
  364.     //    }
  365.     //    cout << endl;
  366.  
  367.     // vymazanie celeho stromu
  368.     removeTree(&tree);
  369.     cout << "Strom bol vymazany" << endl << endl;
  370.  
  371.     // vytvorime strom odznova
  372.     tree = createTree({8,3,1,6,4,7,10,14,13});
  373.     cout << endl;
  374.  
  375.     // preorder prechod stromom
  376.     cout << "Prechod stromom preorder:" << endl;
  377.     preorder(tree);
  378.     cout << endl << endl;
  379.  
  380.     // inorder prechod stromom
  381.     cout << "Prechod stromom inorder:" << endl;
  382.     inorder(tree);
  383.     cout << endl << endl;
  384.  
  385.     // postorder prechod stromom
  386.     cout << "Prechod stromom postorder:" << endl;
  387.     postorder(tree);
  388.     cout << endl << endl;
  389.  
  390.     // level order
  391.     cout << "Prechod stromom levelorder:" << endl;
  392.     levelorder(tree);
  393.     cout << endl << endl;
  394.  
  395.     // hlbka uzla
  396.     cout << "Hlbka uzla:" << endl << endl;
  397.     for(const int i: {8,3,6,4,-1}){
  398.         try {
  399.             cout << "Uzol " << i <<" ma hlbku: " << depthNode(tree, i) << endl;
  400.         } catch (const string& e) {
  401.             cout << e << endl;
  402.         }
  403.     }
  404.     cout << endl;
  405.  
  406.     // hlbka stromu - hlbka najvzdialenejsieho listu
  407.     cout << "Hlbka stromu:" << endl;
  408.     cout << depthTree(tree);
  409.     cout << endl << endl;
  410. }
  411.  
  412. int main() {
  413.     cout << endl << "[ Binarny vyhladavaci strom ]" << endl;
  414.     cout << "...................................................." << endl << endl;
  415.     test_tree();
  416.     return 0;
  417. }
Advertisement
Add Comment
Please, Sign In to add comment