Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

деревья код

.txt
Скачиваний:
0
Добавлен:
06.10.2025
Размер:
14.86 Кб
Скачать
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>
#include <stack>
#include <queue> 
#include <conio.h>

using namespace std;


/////////////////////////////////// обычное дерево, парсинг


struct NodeB //структура обычного двоичного дерева
{
	int data;
	NodeB* left;
	NodeB* right;
	NodeB* parent;
	NodeB(int value, NodeB* parentNode = nullptr)
		: data(value), parent(parentNode), left(nullptr), right(nullptr) {}
};

void preOrderTravers(NodeB*& root) //прямой обход в глубину
{
	if (root)
	{
		cout << root->data << " ";
		preOrderTravers(root->left);
		preOrderTravers(root->right);
	}
}

NodeB* parseTree(const std::string& str, size_t& i, NodeB* parent = nullptr)
{
	if (i >= str.size()) {
		return nullptr;
	}
	char value = str[i];
	if (value == '(') {
		i++; // Пропуск открывающей скобки
		int nodeValue = str[i++] - '0';
		while (str[i] >= '0' && str[i] <= '9') {
			nodeValue = nodeValue * 10 + (str[i++] - '0');
		}
		NodeB* newNode = new NodeB(nodeValue, parent);
		newNode->left = parseTree(str, i, newNode);
		newNode->right = parseTree(str, i, newNode);
		i++; // Пропуск закрывающей скобки
		return newNode;
	}
	return nullptr;
}

void addElement(int value, NodeB*& root) //добавление
{
	if (!root)
	{
		root = new NodeB(value);
		root->data = value;
		root->left = 0;
		root->right = 0;
		return;
	}
	if (root->data > value)
	{
		addElement(value, root->left);
	}
	else if (root->data < value)
	{
		addElement(value, root->right);
	};

}

//////////////////// вывод

struct Trunk
{
	Trunk* prev;
	string str;

	Trunk(Trunk* prev, string str)
	{
		this->prev = prev;
		this->str = str;
	}
};

void showTrunks(Trunk* p)
{
	if (p == nullptr) {
		return;
	}

	showTrunks(p->prev);
	cout << p->str;
}

void printTree(NodeB* root, Trunk* prev, bool isLeft)
{
	if (root == nullptr) {
		return;
	}

	string prev_str = "    ";
	Trunk* trunk = new Trunk(prev, prev_str);

	printTree(root->right, trunk, true);

	if (!prev) {
		trunk->str = "___";
	}
	else if (isLeft)
	{
		trunk->str = ".---";
		prev_str = "   |";
	}
	else {
		trunk->str = "`___";
		prev->str = prev_str;
	}

	showTrunks(trunk);
	cout << " " << root->data << endl;

	if (prev) {
		prev->str = prev_str;
	}
	trunk->str = "   |";

	printTree(root->left, trunk, false);
}

void printTrees(NodeB* root, int indent = 0)
{
	if (root == nullptr)
	{
		return;
	}
	printTrees(root->right, indent + 4);// Вывод правой ветки дерева
	for (int i = 0; i < indent; i++) // Вывод текущего узела
	{
		std::cout << " ";
	}
	cout << root->data << endl;
	printTrees(root->left, indent + 4);// Вывод левой ветки дерева
}

////////////////////////////////////////// авл-дерево

struct NodeAVL
{
	int height;
	int value;
	NodeAVL* left;
	NodeAVL* right;
};

NodeAVL* createAVL(int value) {
	NodeAVL* root = new NodeAVL;
	root->left = NULL;
	root->right = NULL;
	root->height = 0;
	root->value = value;
	return root;
}

// Минимальный элемент в АВЛ-дереве 
NodeAVL* getMinAVL(NodeAVL* root) {
	while (root->left)
		root = root->left;
	return root;
}

// Поиск в АВЛ-дереве значения
NodeAVL* searchAVL(int value, NodeAVL* root) {
	if (root != nullptr) {
		if (value == root->value)
			return root;
		if (value < root->value)
			return searchAVL(value, root->left);
		else
			return searchAVL(value, root->right);
	}
	else return NULL;
}

// Получить высоту АВЛ-узла (если узел == null, высота равна 0)
int heightAVL(NodeAVL* node) {
	return node == NULL ? 0 : node->height;
}

// Получить фактор сбалансированности АВЛ-узла (если узел == null, фактор равен 0)
int bfactorAVL(NodeAVL* node) {
	return node == NULL ? 0 : (heightAVL(node->right) - heightAVL(node->left));
}

// Пересчитать высоту АВЛ-узла и записать в node->height
void recalcHeightAVL(NodeAVL* node) {
	int hl = heightAVL(node->left);
	int hr = heightAVL(node->right);
	node->height = (hl > hr ? hl : hr) + 1;
}

// Малое правое вращение
NodeAVL* rotrightAVL(NodeAVL* node)
{
	NodeAVL* ltree = node->left;
	NodeAVL* subtree = ltree->right;

	ltree->right = node;
	node->left = subtree;

	recalcHeightAVL(node);
	recalcHeightAVL(ltree);

	return ltree;
}

// Малое левое вращение
NodeAVL* rotleftAVL(NodeAVL* node)
{
	NodeAVL* rtree = node->right;
	NodeAVL* subtree = rtree->left;

	rtree->left = node;
	node->right = subtree;

	recalcHeightAVL(node);
	recalcHeightAVL(rtree);

	return rtree;
}

// Сбалансировать узел
NodeAVL* balanceAVL(NodeAVL* node) {
	recalcHeightAVL(node);

	if (bfactorAVL(node) == 2) {
		if (bfactorAVL(node->right) < 0)
			node->right = rotrightAVL(node->right);
		return rotleftAVL(node);
	}
	if (bfactorAVL(node) == -2) {
		if (bfactorAVL(node->left) > 0)
			node->left = rotleftAVL(node->left);
		return rotrightAVL(node);
	}

	return node;
}

// Удаление элемента из АВЛ-дерева
NodeAVL* deleteAVL(int value, NodeAVL* root) {
	if (root == NULL)
		return NULL;

	if (value < root->value)
		root->left = deleteAVL(value, root->left);
	else if (value > root->value)
		root->right = deleteAVL(value, root->right);
	else {
		if (root->left == NULL && root->right == NULL)
			root = NULL;
		else if (root->left == NULL || root->right == NULL)
			root = root->left ? root->left : root->right;
		else {
			NodeAVL* minnode = getMinAVL(root->right);
			root->value = minnode->value;
			root->right = deleteAVL(minnode->value, root->right);
		}
	}

	return root ? balanceAVL(root) : NULL;
}


// Добавить значение в АВЛ-дерево (root != null)
NodeAVL* insertAVL(int value, NodeAVL* root) {
	if (!root) {
		root = new NodeAVL;
		root->value = value;
		root->height = 1;
		root->left = NULL;
		root->right = NULL;
		return root;
	}
	if (value < root->value)
		root->left = insertAVL(value, root->left);
	else if (value > root->value)
		root->right = insertAVL(value, root->right);
	return balanceAVL(root);
}

// Добавить значение в АВЛ-дерево
void addAVL(int value, NodeAVL*& root) {
	if (root == NULL)
		root = createAVL(value);
	else
		root = insertAVL(value, root);
}

// Straight-walk: Прямой обход АВЛ-дерева
void strwAVL(NodeAVL* root) {
	if (root) {
		std::cout << root->value << ' ';
		strwAVL(root->left);
		strwAVL(root->right);
	}
}

// Reverse-walk: Обратный обход АВЛ-дерева
void revwAVL(NodeAVL* root) {
	if (root) {
		revwAVL(root->left);
		revwAVL(root->right);
		std::cout << root->value << ' ';
	}
}

// Symmetrical-walk: Симметричный обход АВЛ-дерева
void symwAVL(NodeAVL* root) {
	if (root) {
		symwAVL(root->left);
		std::cout << root->value << ' ';
		symwAVL(root->right);
	}
}




void breadthFirstUtil(NodeAVL* head) //в ширину
{
	if (!head) return;

	std::queue<NodeAVL*> q;
	q.push(head);
	while (!q.empty()) {
		NodeAVL* curr = q.front();
		q.pop();

		std::cout << curr->value << ' ';

		if (curr->left) q.push(curr->left);
		if (curr->right) q.push(curr->right);
	}
}

void printTreeAVL(NodeAVL* root, Trunk* prev, bool isLeft)
{
	if (root == nullptr) {
		return;
	}

	string prev_str = "    ";
	Trunk* trunk = new Trunk(prev, prev_str);

	printTreeAVL(root->right, trunk, true);

	if (!prev) {
		trunk->str = "___";
	}
	else if (isLeft)
	{
		trunk->str = ".---";
		prev_str = "   |";
	}
	else {
		trunk->str = "`___";
		prev->str = prev_str;
	}

	showTrunks(trunk);
	cout << " " << root->value << endl;

	if (prev) {
		prev->str = prev_str;
	}
	trunk->str = "   |";

	printTreeAVL(root->left, trunk, false);
}


vector<int> convertToVector(NodeB* root) {
	vector<int> arr;
	stack<NodeB*> nodes;
	NodeB* current = root;

	while (current != NULL || !nodes.empty()) {
		while (current != NULL) {
			nodes.push(current);
			current = current->left;
		}

		current = nodes.top();
		nodes.pop();
		arr.push_back(current->data);

		current = current->right;
	}
	return arr;
}

int main()
{
	bool flag = false;
	bool work = false;

	while (!flag)
	{
		setlocale(LC_ALL, "Russian");

		///////обычное дерево 

		char strTree[1000];
		string str;
		ifstream f1;
		int open = 0, close = 0;
		f1.open("file.txt");
		if (!f1.is_open())
		{
			cout << "Ошибка чтения файла" << endl;
			return 0;
		}
		else
		{
			f1.getline(strTree, 1000);
			int i = 0, j = 0;
			while (strTree[i] != '\0')
			{
				if (strTree[i] != ' ')
				{
					if (strTree[i] == '(')
					{
						open++;
					}
					else if (strTree[i] == ')')
					{
						close++;
					}
					if (open < close)
					{
						cout << "Неверная запись в файле" << endl;
						return 0;
					}
					str += strTree[i];
					if (str[j] != '-' && str[j] != '(' && str[j] != ')')
					{

						if (str[j] < '0' || str[j] > '9')
						{
							cout << "Неверная запись в файле" << endl;
							return 0;
						}
					}
					j++;
				}
				i++;
			}
			if (open != close)
			{
				cout << "Неверная запись в файле" << endl;
				return 0;
			}
			f1.close();
		}

		size_t index = 0;
		NodeB* root2 = parseTree(str, index);

		////////////// авл


		NodeB* root = 0;
		ifstream inputFile("file.txt");
		if (!inputFile) {
			cout << "Не удалось открыть файл!" << std::endl;
			return 1;
		}

		string line;
		getline(inputFile, line);
		string numberString;
		int i = 0;
		bool bruh = true;
		while (i < line.length()) {
			if (isdigit(line[i])) {
				numberString += line[i];
			}
			else if (!numberString.empty()) {
				addElement(stoi(numberString), root);
				numberString.clear();
			}
			else if (line[i] != '(' && line[i] != ')' && line[i] != ' ') {
				bruh = false;
				break;
			}
			i++;
		}
		if (!bruh)
		{
			cout << "Ваш файл содержит запрещённые символы!\n";
			system("pause");
			break;
		}

		NodeAVL* avl = 0;
		vector<int> arr = convertToVector(root);
		for (int num : arr)
		{
			addAVL(num, avl);
		}
		///////////////////////////////


		char key{};
		int a = 0;

		system("cls");
		work = false;
		int strel = 1;
		while (!work)
		{

			system("cls");
			cout << "3 лаба";
			cout << "\n\n\n";
			cout << "Ваше введённое дерево (из файла):\n\n";
			printTree(root2, nullptr, false);
			//printTrees(root2);
			cout << "\n";
			cout << "Ваше дерево, преобразованное в АВЛ:\n\n";
			printTreeAVL(avl, nullptr, false);
			cout << "\n\n";
			cout << "Выберите действие стрелкой и нажмите enter";
			cout << "\n\n";
			cout << "Добавить элемент в дерево";
			if (strel == 1) cout << " <--";
			cout << "\n";
			cout << "Удалить элемент из дерева";
			if (strel == 2) cout << " <--";
			cout << "\n";
			cout << "Найти элемент в дереве";
			if (strel == 3) cout << " <--";
			cout << "\n";
			cout << "Прямой обход дерева";
			if (strel == 4) cout << " <--";
			cout << "\n";
			cout << "Обратный обход дерева";
			if (strel == 5) cout << " <--";
			cout << "\n";
			cout << "Симметричный обход дерева";
			if (strel == 6) cout << " <--";
			cout << "\n";
			cout << "Обход дерева в ширину";
			if (strel == 7) cout << " <--";
			cout << "\n";
			cout << "Выход";
			if (strel == 8) cout << " <--";
			cout << "\n";

			key = _getch();

			if (int(key) == -32)
			{
				rewind(stdin);
				key = _getch();
				system("cls");
			}


			if (key == 'P')
			{
				strel += 1;
				if (strel > 8) strel = 1;
				continue;
				system("cls");
			}

			if (key == 'H')
			{
				strel -= 1;
				if (strel < 1) strel = 8;
				continue;
				system("cls");
			}

			//system("cls");

			if (strel == 1 and key == '\r')
			{
				cout << "\n";
				int i = 0;
				while (!(cin >> i) || (cin.peek() != '\n'))
				{
					cout << "Неверный формат данных. Пожалуйста, повторите попытку\n";
					printf("Введите число которое Вы хотите ввести\t");
					cin.clear();
					rewind(stdin);
				}
				addAVL(i, avl);
			}

			if (strel == 2 and key == '\r')
			{
				cout << "\n";
				int i = 0;
				while (!(cin >> i) || (cin.peek() != '\n'))
				{
					cout << "Неверный формат данных. Пожалуйста, повторите попытку\n";
					printf("Введите число которое Вы хотите удалить\t");
					cin.clear();
					rewind(stdin);
				}
				avl = deleteAVL(i, avl);
			}

			if (strel == 3 and key == '\r')
			{
				cout << "\n";
				int i = 0;
				while (!(cin >> i) || (cin.peek() != '\n'))
				{
					cout << "Неверный формат данных. Пожалуйста, повторите попытку\n";
					printf("Введите число которое Вы хотите найти\t");
					cin.clear();
					rewind(stdin);
				}
				NodeAVL* node = searchAVL(i, avl); //поиск
				if (node != NULL)
					cout << "Элемент найден: " << node->value << endl;
				else
					cout << "Элемент не найден!" << endl;
				cout << "\n";
				system("pause");

			}

			if (strel == 4 and key == '\r')
			{
				cout << "\n";
				strwAVL(avl);
				cout << "\n";
				system("pause");
			}

			if (strel == 5 and key == '\r')
			{
				cout << "\n";
				revwAVL(avl);
				cout << "\n";
				system("pause");
			}

			if (strel == 6 and key == '\r')
			{
				cout << "\n";
				symwAVL(avl);
				cout << "\n";
				system("pause");
			}

			if (strel == 7 and key == '\r')
			{
				cout << "\n";
				breadthFirstUtil(avl);
				cout << "\n";
				system("pause");
			}

			if ((strel == 8 and key == '\r') or (key == '\x1B'))
			{
				flag = true;
				break;
			}
		}
	}

	return 0;
}



Соседние файлы в предмете Алгоритмы и системы данных