Advertisement
Guest User

Untitled

a guest
Dec 10th, 2017
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.85 KB | None | 0 0
  1. #include <iostream>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <time.h>
  5.  
  6. /*
  7.  Zacznę od tego, że zadanie jest zrobione w C++, według wymagań zadania jest to dozwolone.
  8.  Jest to spowodowane tym, że jednym z wymogów strukturalnego C jest brak globalnej zmiennej na roota.
  9.  Generalnie przekazywanie za każdym razem korzenia jest problematyczne, więc wolałem to zrobić obiektowo w C++. Sorry
  10. */
  11.  
  12. using namespace std; // określenie przestrzeni nazwy
  13.  
  14. class Tree;
  15.  
  16. // klasa węzła drzewa, na podstawie której tworzone są obiekty węzła
  17. class TreeNode
  18. {
  19.     int key; // klucz węzla
  20.     char tab[10]; // tablica znaków
  21.    
  22.     TreeNode* left; // wskaźnik na lewego potomka
  23.     TreeNode* right; // wskaźnik na prawego potomka
  24.    
  25.     TreeNode(int); // konstruktor, czyli funkcja, na podstawie której jest tworzony obiekt
  26.    
  27.     friend class Tree; // to jest po to, żeby klasa Tree mogła korzystać ze składników tej klasy
  28. };
  29.  
  30. class Tree
  31. {
  32.     int count; // zmienna przechowująca ilość elementów w drzewie
  33.     TreeNode* root; // wskaźnik na korzeń drzewa
  34.  
  35. public:
  36.     Tree(); // konstruktor drzewa, czyli jego inicjalizacja
  37.     ~Tree(); // destruktor drzewa, który wypierdala z pamięci wszystkie
  38.    
  39.     void addNode(int); // dodawanie elementu do drzewa
  40.     void fillTree(int); // zapełnianie drzewa losowymi elementami
  41.    
  42.     TreeNode* search(int); // szukanie elementu po kluczu podanym w parametrze
  43.     TreeNode* findParent(TreeNode*); // szukanie rodzica elementu
  44.     TreeNode* findSuccessor(TreeNode*); // szukanie nastepnika elementu
  45.    
  46.     void deleteNode(int); // wypierdalanie elementu z drzewa
  47.     void clearTree(); // wypierdolenie wszystkich elementów z drzewa
  48.    
  49.     void preOrder(TreeNode*); // wyświetlanie w trybie preorder
  50.     void inOrder(TreeNode*); // wyświetlanie w trybie inorder
  51.     void postOrder(TreeNode*); // domyśl się
  52.    
  53.     void printPreOrder();
  54.     void printInOrder();
  55.     void printPostOrder();
  56. };
  57.  
  58. int main()
  59. {
  60.     srand((unsigned int) time(NULL)); // inicjalizacja generatora pseudolosowości
  61.    
  62.     FILE* file = fopen("inlab03.txt", "r"); // to już było
  63.    
  64.     // to też
  65.     if (!file)
  66.     {
  67.         cerr << "Niepowodzenie przy otwarciu pliku!" << endl << endl;
  68.         exit(EXIT_FAILURE);
  69.     }
  70.    
  71.     // tu również bez niespodzianek
  72.     int X, k1, k2, k3, k4;
  73.    
  74.     fscanf(file, "%d %d %d %d %d", &X, &k1, &k2, &k3, &k4);
  75.     fclose(file);
  76.    
  77.     clock_t start = clock();
  78.    
  79.     Tree* tree = new Tree(); // tu jest inicjalizacja
  80.    
  81.     tree->deleteNode(k1);
  82.     tree->deleteNode(k1);
  83.     tree->fillTree(X);
  84.     tree->printInOrder();
  85.     tree->printPreOrder();
  86.     tree->addNode(k2);
  87.     tree->printInOrder();
  88.     tree->addNode(k3);
  89.     tree->addNode(k4);
  90.     tree->deleteNode(k1);
  91.     tree->printPreOrder();
  92.     tree->search(k1);
  93.     tree->deleteNode(k2);
  94.     tree->printInOrder();
  95.     tree->deleteNode(k3);
  96.     tree->deleteNode(k4);
  97.    
  98.     clock_t stop = clock();
  99.     cout << fixed << "Time spent: " << (double) (stop - start) / CLOCKS_PER_SEC << endl << endl;
  100.  
  101.     delete tree; // porządki
  102. }
  103.  
  104. // konstruktor, który jest wywoływany przy tworzeniu nowego elementu drzewa
  105. TreeNode::TreeNode(int key)
  106. {
  107.     this->key = key;
  108.    
  109.     sprintf(this->tab, "%d", key); // ta funkcja tworzy do tablicy znaków ciąg znaków na podstawie keya
  110.    
  111.     // każdy nowy element nie ma dzieci
  112.     this->left = NULL;
  113.     this->right = NULL;
  114. }
  115.  
  116. // konstruktor drzewa
  117. Tree::Tree()
  118. {
  119.     root = NULL;
  120. }
  121.  
  122. void Tree::addNode(int key)
  123. {
  124.    
  125.     // jeżeli w drzewie nic nie ma, to root jest nowym elementem
  126.     if (!root)
  127.     {
  128.         root = new TreeNode(key); // tak tworzy się nowy element
  129.         return; // kończymy zabawę w tej funkcji
  130.     }
  131.    
  132.     TreeNode* temp = root; // ustawiamy się na rootcie
  133.    
  134.     // szukanie miejsca na nowy element
  135.     while (temp)
  136.     {
  137.         // jeżeli klucz jest już w drzewie, to kończymy się bawić tą funkcją
  138.         if (temp->key == key)
  139.             return;
  140.        
  141.         // jeżeli klucz jest mniejszy od klucza tempa, to idziemy na lewo, jak nie, to na prawo
  142.         if (key < temp->key)
  143.             // jeżeli nie ma lewego potomka, to znaleźliśmy miejsce na nowy element
  144.             if (temp->left)
  145.                 temp = temp->left;
  146.             else
  147.                 break;
  148.         else
  149.             // analogicznie w przypadku prawego potomka
  150.             if (temp->right)
  151.                 temp = temp->right;
  152.             else
  153.                 break;
  154.     }
  155.    
  156.     TreeNode* newNode = new TreeNode(key); // tworzymy nowy węzeł
  157.    
  158.     // wkładamy element do drzewa w taki sposób
  159.     if (key < temp->key)
  160.         temp->left = newNode;
  161.     else
  162.         temp->right = newNode;
  163. }
  164.  
  165. void Tree::fillTree(int X)
  166. {
  167.     // tu bez niespodzianek
  168.     for (int i = 0; i < X; i++)
  169.         addNode(-10000 + rand()%20001); // zakres podałem własny, ponieważ w dokumencie był podany od 10000 do 10000. Uznałem to za błąd, więc jak się ktoś przyczepi, zamień zakres tutaj
  170. }
  171.  
  172. TreeNode* Tree::search(int key)
  173. {
  174.     if (!root)
  175.         return NULL;
  176.    
  177.     TreeNode* temp = root; // ustawiamy się standardowo na rootcie
  178.    
  179.     // szukamy elementu, jeżeli znajdziemy, to zwracamy wskaźnik, jeśli nie, to zwracamy nulla
  180.     while (temp)
  181.     {
  182.         if (temp->key == key)
  183.             return temp;
  184.        
  185.         if (key < temp->key)
  186.             temp = temp->left;
  187.         else
  188.             temp = temp->right;
  189.     }
  190.    
  191.     return NULL;
  192. }
  193.  
  194. TreeNode* Tree::findParent(TreeNode* child)
  195. {
  196.     //chyba nie muszę tłumaczyć
  197.     if (!root)
  198.         return NULL;
  199.    
  200.     if (!child)
  201.         return NULL;
  202.    
  203.     if (child == root)
  204.         return NULL;
  205.    
  206.     TreeNode* temp = root;
  207.    
  208.     /// jeżeli lewy potomek, lub prawy jest jest naszym childem, to zwracamy ten wskaźnik
  209.     while (temp)
  210.     {
  211.         if (temp->left == child || temp->right == child)
  212.             return temp;
  213.    
  214.         if (child->key < temp->key)
  215.             temp = temp->left;
  216.         else
  217.             temp = temp->right;
  218.     }
  219.    
  220.     return NULL; // to się wykona, jeżeli nie znajdziemy rodzica, czyli roota
  221. }
  222.  
  223. TreeNode* Tree::findSuccessor(TreeNode* target)
  224. {
  225.     if (!root)
  226.         return NULL;
  227.    
  228.     // żeby znaleźć następnika, trzeba iść na prawo, potem do oporu w lewo
  229.     TreeNode* temp = target->right;
  230.    
  231.     while (temp->left)
  232.         temp = temp->left;
  233.    
  234.     return temp;
  235. }
  236.  
  237. void Tree::deleteNode(int key)
  238. {
  239.     if (!root)
  240.     {
  241.         cout << "Drzewo jest puste" << endl;
  242.         return;
  243.     }
  244.    
  245.     // szukamy węzła docelowego oraz jego rodzica
  246.     TreeNode* temp = search(key);
  247.     TreeNode* parent = findParent(temp);
  248.    
  249.     // jeżeli parent jest nullem, to znaczy, że musimy usunąć roota
  250.     if (!parent)
  251.     {
  252.         // jeżeli root nie ma potomków, to po prostu kasujemy roota i wyjebane
  253.         if (!root->left && !root->right)
  254.         {
  255.             delete root;
  256.             root = NULL;
  257.            
  258.             return;
  259.         }
  260.        
  261.         // jeżeli root ma tylko lewego potomka, to kasujemy roota i podciągamy jego lewego potomka na miejsce roota
  262.         if (root->left && !root->right)
  263.         {
  264.             TreeNode* left = root->left;
  265.             delete root;
  266.             root = left;
  267.            
  268.             return;
  269.         }
  270.        
  271.         // analogicznie, jeżeli root ma tylko prawego potomka
  272.         if (!root->left && root->right)
  273.         {
  274.             TreeNode* right = root->right;
  275.             delete root;
  276.             root = right;
  277.            
  278.             return;
  279.         }
  280.        
  281.         // pobieramy sobie następnika i rodzica następnika
  282.         TreeNode* successor = findSuccessor(root);
  283.         TreeNode* parentSuccessor = findParent(successor);
  284.        
  285.         // jeżeli rodzic następnika jest rootem, to znaczy, że wystarczy tylko wstawić następnika na miejsce roota i podpiąć lewe poddrzewo roota do lewego wskaźnika successora
  286.         if (parentSuccessor == root)
  287.         {
  288.             TreeNode* rootLeft = successor->left;
  289.            
  290.             delete root;
  291.             root = successor;
  292.            
  293.             root->left = rootLeft;
  294.         }
  295.         else // w przeciwnym wypadku pod następnika podpinamy lewe i prawe poddrzewo roota, a prawe podrzewo nastepnika podpinamy pod lewy wskaźnik rodzica następnika
  296.         {
  297.             TreeNode* successorRight = successor->right;
  298.        
  299.             successor->left = root->left;
  300.             successor->right = root->right;
  301.            
  302.             delete root;
  303.             root = successor;
  304.            
  305.             parentSuccessor->left = successorRight;
  306.         }
  307.        
  308.         return;
  309.     }
  310.    
  311.    
  312.     // w przypadku innego węzła, niż roota, musimy też następnik podpiąć pod lewe lub prawe poddrzewo rodzica usuwanego węzła w zależności od sytuacji. Reszta jest taka sama
  313.     if (!temp->left && !temp->right)
  314.     {
  315.        
  316.         // tutaj następuje sprawdzenie
  317.         if (parent->left == temp)
  318.             parent->left = NULL;
  319.         else
  320.             parent->right = NULL;
  321.    
  322.         delete temp;
  323.        
  324.         return;
  325.     }
  326.    
  327.     if (temp->left && !temp->right)
  328.     {
  329.         TreeNode* child;
  330.        
  331.         child = temp->left;
  332.         delete temp;
  333.        
  334.         if (parent->left == temp)
  335.             parent->left = child;
  336.         else
  337.             parent->right = child;
  338.        
  339.         return;
  340.     }
  341.    
  342.     if (!temp->left && temp->right)
  343.     {
  344.         TreeNode* child;
  345.        
  346.         child = temp->right;
  347.         delete temp;
  348.        
  349.         if (parent->left == temp)
  350.             parent->left = child;
  351.         else
  352.             parent->right = child;
  353.        
  354.         return;
  355.     }
  356.    
  357.     TreeNode* successor = findSuccessor(temp);
  358.     TreeNode* parentSuccessor = findParent(successor);
  359.    
  360.     if (parentSuccessor == temp)
  361.     {
  362.         successor->left = temp->left;
  363.        
  364.         if (parent->left == temp)
  365.             parent->left = successor;
  366.         else
  367.             parent->right = successor;
  368.     }
  369.     else
  370.     {
  371.         TreeNode* successorRight = successor->right;
  372.        
  373.         successor->left = temp->left;
  374.         successor->right = temp->right;
  375.        
  376.         parentSuccessor->left = successorRight;
  377.        
  378.         if (parent->left == temp)
  379.             parent->left = successor;
  380.         else
  381.             parent->right = successor;
  382.     }
  383.    
  384.     delete temp;
  385. }
  386.  
  387. void Tree::preOrder(TreeNode* node)
  388. {
  389.     if (node)
  390.     {
  391.         count++;
  392.         cout << node->key << endl;
  393.         preOrder(node->left);
  394.         preOrder(node->right);
  395.     }
  396. }
  397.  
  398. void Tree::inOrder(TreeNode* node)
  399. {
  400.     if (node)
  401.     {
  402.         inOrder(node->left);
  403.         count++;
  404.         cout << node->key << endl;
  405.         inOrder(node->right);
  406.     }
  407. }
  408.  
  409. void Tree::postOrder(TreeNode* node)
  410. {
  411.     if (node)
  412.     {
  413.         postOrder(node->left);
  414.         postOrder(node->right);
  415.         count++;
  416.         cout << node->key << endl;
  417.     }
  418. }
  419.  
  420. void Tree::printPreOrder()
  421. {
  422.     cout << "Wyświetlanie preorder: " << endl << endl;
  423.  
  424.     preOrder(root);
  425.     cout << endl << "Total elements: " << count << endl;
  426.     count = 0;
  427. }
  428.  
  429. void Tree::printInOrder()
  430. {
  431.     cout << "Wyswietlanie inorder: " << endl << endl;
  432.  
  433.     inOrder(root);
  434.     cout << endl << "Total elements: " << count << endl;
  435.     count = 0;
  436. }
  437.  
  438. void Tree::printPostOrder()
  439. {
  440.     cout << "Wyświetlanie postorder: " << endl << endl;
  441.  
  442.     postOrder(root);
  443.     cout << endl << "Total elements: " << count << endl;
  444.     count = 0;
  445. }
  446.  
  447. void Tree::clearTree()
  448. {
  449.     if (!root)
  450.     cout << "Drzewo jest puste!" << endl;    
  451.  
  452.     while (root)
  453.         deleteNode(root->key);
  454. }
  455.  
  456. Tree::~Tree()
  457. {
  458.     clearTree();
  459. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement