[C++] Nieprawidłowe przekolorowywanie drzewa  czerwono czarnego po dodaniu nowego elementu.
Ostatnio zmodyfikowano 2019-11-21 12:46
greenbanzai Temat założony przez niniejszego użytkownika  | 
[C++] Nieprawidłowe przekolorowywanie drzewa  czerwono czarnego po dodaniu nowego elementu. » 2019-11-21 00:07:59 Cześć! Implementuję drzewo czerwono-czarne i utknąłem na naprawie drzewa po dodaniu nowego elementu. Zwykle w prawych gałęziach drzewa coś nie gra. Rotacje wydają się działać w porządku, ale głowy nie dam sobie uciąć, ponieważ u mnie element 20, który wkładam jako ostatni staje się lewym dzieckiem korzenia, a w wizualizatorze online drzewa taka 20stka stanie się lewym potomkiem elementu 55 (wnukiem 17stki). Wydaje mi się, że w metodzie fixViolation(Node<T>*n) rozpatrzyłem wszystkie przypadki, więc nie wiem skąd może brać się błąd.  Poniżej mój kod: #include "pch.h" #include <iostream> #include <random> #include <string> #include <functional> using namespace std;
  enum Color { Black, Red }; template < typename T > class RBTree;
  template < typename T > class Node {     friend class RBTree < T >;     T data;     Color color;     Node * parent;     Node * leftChild;     Node * rightChild; public:     Node()     {         this->parent = nullptr;         this->leftChild = nullptr;         this->rightChild = nullptr;              }     void gibColor( Node < T >* x )     {         if( x->color == Black )              cout << "czarny";         else              cout << "czerowny";              } };
  template < typename T > class RBTree {     Node < T >* root;     int size; public:     RBTree()     {         root = nullptr;         size = 1;     }          void leftRotate( Node < T >* child, Node < T >* parent )     {         child = parent->rightChild;         parent->rightChild = child->leftChild;         if( child->leftChild != nullptr )         {             child->leftChild->parent = parent;         }                  child->parent = parent->parent;         if( parent->parent == nullptr )         {             root = child;         }         else if( parent == parent->parent->leftChild )         {             parent->parent->leftChild = child;         }         else {             parent->parent->rightChild = child;         }                  child->leftChild = parent;         parent->parent = child;     }     void rightRotate( Node < T >* child, Node < T >* parent )     {         child = parent->leftChild;         parent->leftChild = child->rightChild;         if( child->rightChild != nullptr )         {             child->rightChild->parent = parent;         }         child->parent = parent->parent;         if( parent->parent == nullptr )         {             root = child;         }         else if( parent == parent->parent->rightChild )         {             parent->parent->rightChild = child;         }         else         {             parent->parent->leftChild = child;         }                  child->rightChild = parent;         parent->parent = child;     }     void fixViolation( Node < T >* n )     {         Node < T >* grandparent;         Node < T >* parent;         Node < T >* uncle;         parent = n->parent;         while( parent != nullptr && parent->color == Red )         {             grandparent = n->parent->parent;             if( grandparent->leftChild == parent )             {                 uncle = grandparent->rightChild;                 if( uncle != nullptr && uncle->color == Red )                 {                     parent->color = Black;                     uncle->color = Black;                     grandparent->color = Red;                     n = grandparent;                     parent = n->parent;                 }                 else                 {                     if( parent->rightChild == n )                     {                         n = parent;                         leftRotate( n->parent, n );                     }                                          parent->color = Black;                     grandparent->color = Red;                     rightRotate( parent, grandparent );                 }             }             else             {                 uncle = grandparent->leftChild;                 if( uncle != nullptr && uncle->color == Red )                 {                     uncle->color = Black;                     parent->color = Black;                     grandparent->color = Red;                     n = grandparent;                     parent = n->parent;                 }                 else                 {                     if( parent->leftChild == n )                     {                         n = parent;                         rightRotate( n->parent, n );                     }                                          parent->color = Black;                     grandparent->color = Red;                     leftRotate( parent, grandparent );                 }             }                      }         root->color = Black;     }          void addElement( T el )     {         Node < T >* n = new Node < T >();         n->data = el;         n->leftChild = nullptr;         n->rightChild = nullptr;         n->color = Red;         Node < T >* temp = this->root;         Node < T >* y = nullptr;         if( root == nullptr )         {             n->color = Black;             root = n;         }         else         {             while( temp != nullptr )             {                 y = temp;                 if( temp->data < n->data )                 {                     temp = temp->rightChild;                 }                 else                 {                     temp = temp->leftChild;                 }             }             n->parent = y;             if( y->data == n->data )             {                 cout << "Duplikaty won!" << endl;                 return;             }             if( y->data < n->data )             {                 y->rightChild = n;                 size = size + 1;             }             else             {                 y->leftChild = n;                 size = size + 1;             }             fixViolation( n );         }              }     void print( Node < T >* x )     {                           if( x == nullptr )         {             return;         }         if( x->parent == nullptr )         {             cout << "(" << x->data << ")";             cout << "[" << "kolor:";             x->gibColor( x );             cout << ", rodzic: NULL," << " l.dziecko: ";             if( x->leftChild == nullptr )             {                 cout << "NIL";             }             else                  cout << x->leftChild->data;                          cout << ", p. dziecko: ";             if( x->rightChild == nullptr )             {                 cout << "NIL";             }             else                  cout << x->rightChild->data;                          cout << "]";             cout << "-korzen " << endl;                                   }         else if( x->parent->leftChild == x )         {                          cout << "(" << x->data << ")";             cout << "[" << "kolor:";             x->gibColor( x );             cout << ", rodzic: " << x->parent->data << ", l.dziecko: ";             if( x->leftChild == nullptr )             {                 cout << "NIL";             }             else                  cout << x->leftChild->data;                          cout << ", p. dziecko: ";             if( x->rightChild == nullptr )             {                 cout << "NIL" << "]" << endl;             }             else                  cout << x->rightChild->data << "]" << endl;                      }         else         {             cout << "(" << x->data << ")";             cout << "[" << "kolor:";             x->gibColor( x );             cout << ", rodzic: " << x->parent->data << ", l.dziecko: ";             if( x->leftChild == nullptr )             {                 cout << "NIL";             }             else                  cout << x->leftChild->data;                          cout << ", p. dziecko: ";             if( x->rightChild == nullptr )             {                 cout << "NIL" << "]" << endl;;             }             else                  cout << x->rightChild->data << "]" << endl;                      }         print( x->leftChild );         print( x->rightChild );              }     void printTree()     {                  if( root == nullptr )         {             cout << "Puste drzewo!" << endl;                      }         else              print( root );              } }; int randomInt() {     uniform_int_distribution < int > rozklad { 0, 11000000 };     default_random_engine generator { 11 };     function < int() > los { bind( rozklad, generator ) };     int l = los();     return l; } int main() {     RBTree < int >* d1 = new RBTree < int >();     d1->addElement( 55 );     d1->addElement( 69 );     d1->addElement( 62 );     d1->addElement( 71 );     d1->addElement( 70 );     d1->addElement( 14 );     d1->addElement( 17 );     d1->addElement( 3 );     d1->addElement( 20 );     d1->printTree(); }
   | 
 | 
darko202  | 
» 2019-11-21 12:39:34 użyj debuggera c++ odpowiedniego do twojego kompilatora
  dzięki niemu szybko odszukasz miejsce kazdego błędu ponieważ wiesz co chciałeś osiągnąć w danym miejscu programu  | 
 | 
TemplateEntity  | 
» 2019-11-21 12:46:53 Porównaj sobie z tą częściową implementacją drzewa RB. #include <iostream> #include <string> #include <iomanip> #include <ios>
  using namespace std;
  enum class Color { Black, Red };
  template < typename T > struct Node {     T data;     Color color;     Node < T > * parent, * left, * right;          Node < T >( T data )         : data     { data }, color { Color::Red }, parent { nullptr }, left { nullptr }, right { nullptr } { } };
  template < typename T > ostream & operator <<( ostream & os, const Node < T >& node ) {     os << left << setw( 12 ) <<( node.color == Color::Red ? "Red"         : "Black" );     os << left << setw( 12 ) << node.data;     os << left << setw( 12 ) <<( node.parent == nullptr ? "null"         : to_string( node.parent->data ) );     os << left << setw( 12 ) <<( node.left == nullptr ? "null"         : to_string( node.left->data ) );     os << left << setw( 12 ) <<( node.right == nullptr ? "null"         : to_string( node.right->data ) ) << "\n";          if( node.left != nullptr ) os << * node.left;          if( node.right != nullptr ) os << * node.right;          return os; }
  template < typename T > class RBTree {      public:          void insertValue( T n )     {         auto node = new Node < T >( n );         root = insertBST( root, node );         fixInsertRBTree( node );     }          void printTree()     {         cout << left << setw( 12 ) << "Node color";         cout << left << setw( 12 ) << "Node data";         cout << left << setw( 12 ) << "Parent";         cout << left << setw( 12 ) << "LChild";         cout << left << setw( 12 ) << "RChild" << "\n";         cout << "------------------------------------------------------\n";         cout << * root;     }      private:          Color getColor( Node < T >* node )     {         return( node == nullptr ) ? Color::Black             : node->color;     }          void setColor( Node < T >* node, Color color )     {         if( node == nullptr ) return;                  node->color = color;     }          Node < T >* insertBST( Node < T >* root, Node < T >* ptr )     {         if( root == nullptr ) return ptr;                  if( ptr->data < root->data )         {             root->left = insertBST( root->left, ptr );             root->left->parent = root;         }         else if( ptr->data > root->data )         {             root->right = insertBST( root->right, ptr );             root->right->parent = root;         }                  return root;     }          void fixInsertRBTree( Node < T >* ptr )     {         Node < T >* parent { nullptr };         Node < T >* grandparent { nullptr };                  while( ptr != root && getColor( ptr ) == Color::Red && getColor( ptr->parent ) == Color::Red )         {             parent = ptr->parent;             grandparent = parent->parent;             if( parent == grandparent->left )             {                 Node < T >* uncle = grandparent->right;                 if( getColor( uncle ) == Color::Red )                 {                     setColor( uncle, Color::Black );                     setColor( parent, Color::Black );                     setColor( grandparent, Color::Red );                     ptr = grandparent;                 }                 else                 {                     if( ptr == parent->right )                     {                         rotateLeft( parent );                         ptr = parent;                         parent = ptr->parent;                     }                     rotateRight( grandparent );                     swap( parent->color, grandparent->color );                     ptr = parent;                 }             }             else             {                 Node < T >* uncle = grandparent->left;                 if( getColor( uncle ) == Color::Red )                 {                     setColor( uncle, Color::Black );                     setColor( parent, Color::Black );                     setColor( grandparent, Color::Red );                     ptr = grandparent;                 }                 else                 {                     if( ptr == parent->left )                     {                         rotateRight( parent );                         ptr = parent;                         parent = ptr->parent;                     }                     rotateLeft( grandparent );                     swap( parent->color, grandparent->color );                     ptr = parent;                 }             }         }         setColor( root, Color::Black );     }          void rotateLeft( Node < T >* ptr )     {         Node < T >* right_child = ptr->right;         ptr->right = right_child->left;                  if( ptr->right != nullptr ) ptr->right->parent = ptr;                  right_child->parent = ptr->parent;                  if( ptr->parent == nullptr ) root = right_child;         else if( ptr == ptr->parent->left ) ptr->parent->left = right_child;         else ptr->parent->right = right_child;                  right_child->left = ptr;         ptr->parent = right_child;     }          void rotateRight( Node < T >* ptr )     {         Node < T >* left_child = ptr->left;         ptr->left = left_child->right;                  if( ptr->left != nullptr ) ptr->left->parent = ptr;                  left_child->parent = ptr->parent;                  if( ptr->parent == nullptr ) root = left_child;         else if( ptr == ptr->parent->left ) ptr->parent->left = left_child;         else ptr->parent->right = left_child;                  left_child->right = ptr;         ptr->parent = left_child;     }          Node < T >* root { nullptr };      };
  int main() {     RBTree < int > tree;     for( int index = 0; index < 15; ++index )     {         tree.insertValue( rand() % 1000 );     }     tree.printTree(); }
   | 
 | 
|  « 1 »  |