Удаление (замена) узла в дереве
Помогите найти ошибку. Программа позволяет создать небинарное дерево, число сыновей узла и его ключ вводятся пользователем, степень дерева = 4(это значит, что уровней в иерархии дерева не более 4?), а также удалить узел по ключу. Метод удаления узла:
- если узел имеет 0 потомков, он просто удаляется.
- Если узел имеет 1 потомка, он заменяется своим сыном, остальные узлы под его сыном тоже сдвигаются вверх.
- Если узел имеет 2 и более потомков, он заменяется своим самым левым сыном, все дочерние узлы, кроме того самого левого потомка, удаляются.
В дереве удаляется нужный узел, вот только заменяется он на соседний, а должен на левый дочерний, т.е node->son[0]. В чем может быть причина? Неверный указатель на отца удаляемого узла?
Буду рад любому вашему замечанию, так как программа далека от идеала.
#include <iostream>
using namespace std;
struct Node
{
int key = 0; //ключ
int id = 0; //индекс
int level = 0; //уровень в иерархии
Node* parent = nullptr; //указатель на родителя
Node** son = nullptr; //массив указателей на сыновей
int count_son = 0; //количество сыновей
};
Node* createTree(Node* node, int id, int level)
{
if (node->level <= 4)
{
node->id = id;
node->level = level;
cout << "Текущая позиция: " << node->level << "-" << node->id << "\n" << "Введите степень узла и его ключ: ";
cin >> node->count_son >> node->key;
node->son = new Node * [node->count_son];
level++;
for (int i = 0; i < node->count_son; i++)
{
node->son[i] = new Node;
node->son[i]->parent = node;
node->son[i]->id = id + i;
node->son[i]->level = level;
}
for (int i = 0; i < node->count_son; i++)
createTree(node->son[i], id + i, level);
}
return node;
}
void printTree(Node* node)
{
if (node->id >= 0)
{
for (int i = 0; i < node->level; i++) cout << "| ";
if (node->son != NULL) cout << "[+]";
cout << "(" << node->level << "-" << node->id << ") = " << node->key << endl;
if (node->count_son > 0)
for (int i = 0; i < node->count_son; i++)
printTree(node->son[i]);
}
else return;
}
Node* Find(Node* root, int key) // Ищет узел с указанным ключом
{
if (root->key == key)
return root;
Node* cur = root;
for (int i = 0; i < cur->count_son; i++)
{
if (cur->key == key)
return cur;
cur = cur->son[i];
Node* r = Find(cur, key);
if (r)
return r;
}
return NULL;
}
void nodeKill(Node* root, int key)
{
Node* DelNode = Find(root, key); Node* ParentNode = DelNode->parent; Node* NewNode = DelNode->son[0];
//0-ой случай, когда дерево пустое
if (DelNode == NULL)
return;
if (DelNode->count_son == 0)
{
delete DelNode;
return;
}
//1-ый случай, если сын один
if (DelNode->count_son == 1)
{
ParentNode = DelNode->parent;
NewNode = DelNode->son[0];
delete DelNode;
return;
}
//2-ой случай, когда дерево имеет несколько потомков
if (DelNode->count_son > 1)
{
for (int i = 0; i < ParentNode->count_son; i++)
{
ParentNode->son[i] = NewNode;
break;
}
NewNode->parent = ParentNode;// указателю родителя дочернего узла присваиваем адрес родительского узла удаляемого элемента теперь удаляемый элемент исключен из дерева и как бы висит в воздухе вместе с потомками, кроме самого левого
// нужно оставшихся потомков перепривязать к новому узлу
Node** tmp = new Node * [NewNode->count_son + DelNode->count_son - 1];
for (int j = 0; j < NewNode->count_son; j++)
tmp[j] = NewNode->son[j];
for (int j = 1; j < DelNode->count_son; j++) // копируем все указатели на потомков из удаляемого узла в новый массив нового узла
tmp[NewNode->count_son + j - 1] = DelNode->son[j];
delete[] NewNode->son; // удаляем старый массив указателей на потомков
NewNode->son = tmp; // запоминаем новый массив указателей
NewNode->count_son = NewNode->count_son + DelNode->count_son - 1; // сохраняем новое количество потомков
// Теперь удаляем старый узел
delete[] DelNode->son; // сначала удаляем массив указателей на потомков
delete DelNode;
}
return;
}
int main()
{
int key; Node* root;
setlocale(LC_ALL, "RUS");
root = new Node; root->parent = nullptr;
root = createTree(root, 0, 0);
cout << "\n-----Получившееся дерево-----\n";
printTree(root);
cout << "Введите ключ узла, который хотите удалить: ";
cin >> key;
Node* DelNode = Find(root, key);
cout << "\n" << DelNode->count_son << " " << DelNode->id << " " << DelNode->key << "\n";
nodeKill(DelNode, key);
printTree(root);
system("pause");
return 0;
}