Скачиваний:
17
Добавлен:
04.11.2020
Размер:
12.56 Кб
Скачать
#include<iostream>
#include "RBTree.h"

RBtree::~RBtree()   // деструктор
{
	if (root != NULL)
	{
		Destruct(root);  // потому что нельзя вызвать деструктор рекурсивно
	}
}

void RBtree::Destruct(Node *current)  // для деструктора -- рекурсивное удаление дерева
{
	if (current != nullptr) 
	{
		Destruct(current->left);
		Destruct(current->right);
		delete current;
	}
}


void RBtree::createNodeRand(RBtree &tree, int maxnum)  // генерация нового узла 
{
	for (int i = 0; i < maxnum; i++)
	{
		Node* t = new Node;
		t->left = NULL;
		t->right = NULL;
		t->parent = NULL;
		t->color = RED;
		t->data = rand() % 998 + 1;
		if (tree.searchbool(t->data))
			delete t;  // если уже есть -- удаляем
		else
			tree.insert(t);	 // если в дереве нету -- заносим
	}
}

void RBtree::createNodeFromUser(RBtree &tree)  // создание узла -- данные вводятся с клавиатуры
{
	dataType input;
	std::cin >> input;
	Node* t = new Node;
	t->data = input;
	t->left = NULL;
	t->right = NULL;
	t->color = RED;
	if (tree.searchbool(t->data))
		delete t;  // если уже есть -- удаляем
	else 
		tree.insert(t);					 // если в дереве нету -- заносим
}

void RBtree::insert(Node *t)	// t -- вставляемый в деререво узел
{
	Node* rootCopy = root, * q = NULL;
	if (root == NULL)  // если дерево не существует, то добавляемый узел становится корнем
	{
		root = t;
		t->parent = NULL;
	}
	else  // если дерево существует... находим место куда вставить узел
	{
		while (rootCopy != NULL)	// смотрим в дерево, пока не дошли до листов
		{
			q = rootCopy;
			if (rootCopy->data < t->data)		// если вставляемый больше корня/узла то ГО в правое поддерево
				rootCopy = rootCopy->right;
			else								// иначе ГО в левое поддерево
				rootCopy = rootCopy->left;
		}
		t->parent = q;						// q усонавливает t
		if (q->data < t->data)				// исходя из значения t, ставим либо правым
			q->right = t;
		else								// либо левым потомком q
			q->left = t;
	}
	insertfix(t);	// балансируем, перекрашиваем, делаем повороты...
}

void RBtree::insertfix(Node* t)
{
	Node* uncle = NULL;
	if (root == t) // если в дереве только данный узел красим в ченое и все
	{
		t->color = BLACK;
		t->parent = NULL;
		return;
	}
	// иначе
	while (t->parent != NULL && t->parent->color == RED)
	{
		Node* grandpa = t->parent->parent;	// дед
		if (grandpa->left == t->parent)		// если отец t левый потомок деда
		{
			if (grandpa->right != NULL)		// и при этом нет правого потомка
			{
				uncle = grandpa->right;		// тогда дядя правый потомок деда
				if (uncle->color == RED)	// и если красный
				{
					t->parent->color = BLACK;	// то отец t -- черный
					uncle->color = BLACK;		// дядя тоже черный
					grandpa->color = RED;		// дед красный
					t = grandpa;				
				}
			}
			else  // если оба потомка существуют...
			{
				if (t->parent->right == t)  // если t правый потомок отца, тогда левый поворот от отца
				{
					t = t->parent;
					leftrotate(t);
				}
				t->parent->color = BLACK;	// отец черный
				grandpa->color = RED;		// дед красный
				rightrotate(grandpa);		// правый поворот от деда
			}
		}
		else  // если отец t правый потомок деда, тоже самое зеркально отображенное...
		{
			if (grandpa->left != NULL)
			{
				uncle = grandpa->left;
				if (uncle->color == RED)
				{
					t->parent->color = BLACK;
					uncle->color = BLACK;
					grandpa->color = RED;
					t = grandpa;
				}
			}
			else
			{
				if (t->parent->left == t)
				{
					t = t->parent;
					rightrotate(t);
				}
				t->parent->color = BLACK;
				grandpa->color = RED;
				leftrotate(grandpa);
			}
		}
		// сохраняем свойства корня
		root->color = BLACK;
		root->parent = NULL;
	}
}

void RBtree::del(dataType x)
{
	if (root == NULL)
	{
		std::cout << "\nПустое дерево, нечего удалить!";
		return;
	}
	Node* p = root;
	Node* y = NULL;
	Node* q = NULL;
	bool found = false;
	while (p != NULL && found == false)  // ищем
	{
		if (p->data == x)
			found = true;
		if (found == false)
		{
			if (p->data < x)
				p = p->right;
			else
				p = p->left;
		}
	}
	if (found == false) // не нашли
	{
		std::cout << "\nТакого элемента нет в дереве!";
		return;
	}
	else // нашли, удаляем
	{
		std::cout << "\nУдаленный элемент: " << p->data;
		std::cout << "\nЦвет: ";
		if (p->color == BLACK)
			std::cout << "Черный\n";
		else
			std::cout << "Красный\n";

		if (p->parent != NULL)
			std::cout << "\nРодитель: " << p->parent->data;
		else
			std::cout << "\nУ него нет родителя.  ";
		if (p->right != NULL)
			std::cout << "\nПравый потомок: " << p->right->data;
		else
			std::cout << "\nУ него нет правого потомка.  ";
		if (p->left != NULL)
			std::cout << "\nЛевый потомок: " << p->left->data;
		else
			std::cout << "\nУ него нет левого потомка.  ";
		
		if (p->left == NULL || p->right == NULL)  // если хотя бы один потомок лист
			y = p;
		else
			y = successor(p);
		if (y->left != NULL)		// если левый потомок существует
			q = y->left;
		else						// если нет
		{
			if (y->right != NULL)	// и при этом правый потомок тоже существует
				q = y->right;
			else					// если нет
				q = NULL;
		}
		if (q != NULL)		// после выше происходящего если q не лист то его отец это отец у тоже
			q->parent = y->parent;
		if (y->parent == NULL)			// если нет родителя, то он корень
			root = q;
		else							// иначе
		{
			if (y == y->parent->left)	// если у левый потомок отца
				y->parent->left = q;
			else						// если правый
				y->parent->right = q;
		}
		if (y != p)
		{
			p->color = y->color;
			p->data = y->data;
		}
		if (y->color == BLACK)  // если у был черным, нужно балансировать
			delfix(q);
		std::cout << "\nУзел был удален, дерево - сбалансирован!\n";
	}
	
}

void RBtree::delfix(Node* p)
{
	Node* s = NULL; // дядя
	while (p != root && p->color == BLACK)	// пока не корень и не черный одновременно
	{
		if (p->parent->left == p)	// если р левый потомок
		{
			s = p->parent->right;	// s - дядя
			if (s->color == RED)	// если дядя красный
			{
				s->color = BLACK;		// дядя черный
				p->parent->color = RED;	// отец красный
				leftrotate(p->parent);	// левый поворот от отца
				s = p->parent->right;	// дядя стал правым потомком отца
			}
			if (s->right->color == BLACK && s->left->color == BLACK)  // племянники черные одновременно
			{
				s->color = RED; // тогда дядя красный
				p = p->parent;
			}
			else
			{
				if (s->right->color == BLACK)	//если правый племянник черный
				{
					s->left->color = BLACK; // левый тоже будет
					s->color = RED;			// дядя опять красный
					rightrotate(s);			// правый поворот от дяди
					s = p->parent->right;	// дядя стал правым потомком отца
				}
				s->color = p->parent->color;
				p->parent->color = BLACK;
				s->right->color = BLACK;
				leftrotate(p->parent);
				p = root;
			}
		}
		else  // если р правый потомок, аналогично зеркально отображенно
		{
			s = p->parent->left;
			if (s->color == RED)
			{
				s->color = BLACK;
				p->parent->color = RED;
				rightrotate(p->parent);
				s = p->parent->left;
			}
			if (s->left->color == BLACK && s->right->color == BLACK)
			{
				s->color = RED;
				p = p->parent;
			}
			else
			{
				if (s->left->color == BLACK)
				{
					s->right->color = BLACK;
					s->color = RED;
					leftrotate(s);
					s = p->parent->left;
				}
				s->color = p->parent->color;
				p->parent->color = BLACK;
				s->left->color = BLACK;
				rightrotate(p->parent);
				p = root;
			}
		}
		p->color = BLACK;
		root->color = BLACK;
		root->parent = NULL;
	}
}

void RBtree::leftrotate(Node* p)	// левый поворот
{
	if (p->right == NULL)
		return;
	else
	{
		Node* y = p->right;
		if (y->left != NULL)
		{
			p->right = y->left;
			y->left->parent = p;
		}
		else
			p->right = NULL;
		if (p->parent != NULL)
			y->parent = p->parent;
		if (p->parent == NULL)
			root = y;
		else
		{
			if (p == p->parent->left)
				p->parent->left = y;
			else
				p->parent->right = y;
		}
		y->left = p;
		p->parent = y;
	}
}
void RBtree::rightrotate(Node* p)	// правый поворот
{
	if (p->left == NULL)
		return;
	else
	{
		Node* y = p->left;
		if (y->right != NULL)
		{
			p->left = y->right;
			y->right->parent = p;
		}
		else
			p->left = NULL;
		if (p->parent != NULL)
			y->parent = p->parent;
		if (p->parent == NULL)
			root = y;
		else
		{
			if (p == p->parent->left)
				p->parent->left = y;
			else
				p->parent->right = y;
		}
		y->right = p;
		p->parent = y;
	}
}

Node* RBtree::successor(Node* p)	// от переданного узла возвращает возвращает 
{
	Node* y = NULL;					// 1. на NULL если нет потомков; 
	if (p->left != NULL)			// 2. на правый последний элемент левого поддерева
	{
		y = p->left;
		while (y->right != NULL)
			y = y->right;
	}
	else							// 2. на левый последний элемент правого поддерева
	{
		y = p->right;
		while (y->left != NULL)
			y = y->left;
	}
	return y;
}

void RBtree::disp()
{
	display(root);
}

void RBtree::display(Node* p)
{
	if (root == NULL)
	{
		std::cout << "\nДерево пуста!.";
		return;
	}
	if (p != NULL)
	{
		if (p == root)
			std::cout << "\n Корень: ";
		else
			std::cout << " Узел: ";
		std::cout << "\n\tДанные:\t\t" << p->data;
		std::cout << "\n\tЦвет:\t";
		if (p->color == BLACK)
			std::cout << "\tЧерный";
		else
			std::cout << "\tКрасный";
		if (p->parent != NULL)  // && p != root
			std::cout << "\n\tРодитель:\t" << p->parent->data;
		else
			std::cout << "\n\tУ него нет родителя.";
		if (p->right != NULL)
			std::cout << "\n\tПравый потомок:\t" << p->right->data;
		else
			std::cout << "\n\tУ него нет правого потомка.";
		if (p->left != NULL)
			std::cout << "\n\tЛевый потомок:\t" << p->left->data;
		else
			std::cout << "\n\tУ него нет левого потомка.";

		if (p->left)
		{
			std::cout << "\n Левый";
			display(p->left);
		}
		else
			std::cout<<"\n\tНет левого потомка.";
		if (p->right)
		{
			std::cout << "\n Правый";
			display(p->right);
		}
		else
			std::cout << "\n\tНет правого потомка.";
	}
}

bool RBtree::searchbool(dataType x)		// дополнение для поиска
{
	if (root == NULL)  //Дерево пуста!
		return false;
	Node* p = root;
	bool found = false;
	while (p != NULL && found == false)
	{
		if (p->data == x)
			found = true;
		if (found == false)
		{
			if (p->data < x)
				p = p->right;
			else
				p = p->left;
		}
	}
	if (found == false)
		return false;	// не нашел 
	else
		return true;	// нашел 
}


void RBtree::search(dataType x) 
{
	if (root == NULL)
	{
		std::cout << "\nПустое дерево\n";
		return;
	}
	Node* p = root;
	bool found = false;
	while (p != NULL && found == false)
	{
		if (p->data == x)
			found = true;
		if (found == false)
		{
			if (p->data < x)
				p = p->right;
			else
				p = p->left;
		}
	}
	if (found == false)
	{
		std::cout << "\nЭлемент не найден!";
		return;
	}
	else
	{
		std::cout << "\n Найденный элемент: ";
		std::cout << "\n\tДанные:\t\t" << p->data;
		std::cout << "\n\tЦвет:\t";
		if (p->color == BLACK)
			std::cout << "\tЧерный";
		else
			std::cout << "\tКрасный";
		if (p->parent != NULL)
			std::cout << "\n\tРодитель:\t" << p->parent->data;
		else
			std::cout << "\n\tУ него нет родителя.";
		if (p->right != NULL)
			std::cout << "\n\tПравый потомок:\t" << p->right->data;
		else
			std::cout << "\n\tУ него нет правого потомка.";
		if (p->left != NULL)
			std::cout << "\n\tЛевый потомок:\t" << p->left->data;
		else
			std::cout << "\n\tУ него нет левого потомка.";
		std::cout << std::endl;
	}
}


void RBtree::displayroot()
{
	if (root == NULL)
	{
		std::cout << "\nДерево пуста!.";
		return;
	}
	else
	{
		std::cout << "\n Корень: ";
		std::cout << "\n\tДанные:\t\t" << root->data;
		std::cout << "\n\tЦвет:\t";
		if (root->color == BLACK)
			std::cout << "\tЧерный";
		else
			std::cout << "\tКрасный";
		if (root->parent != NULL)
			std::cout << "\n\tРодитель:\t" << root->parent->data;
		else
			std::cout << "\n\tУ него нет родителя.";
		if (root->right != NULL)
			std::cout << "\n\tПравый потомок:\t" << root->right->data;
		else
			std::cout << "\n\tУ него нет правого потомка.";
		if (root->left != NULL)
			std::cout << "\n\tЛевый потомок:\t" << root->left->data;
		else
			std::cout << "\n\tУ него нет левого потомка.";
	}
}
Соседние файлы в папке ЛАБА 3 Красно-Черное дерево