Advertisement
Guest User

Untitled

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