Two children delete is still broken. Single / no child delete works fine.
parent
89f77e3aa9
commit
4b89ec2ee1
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/bash
|
||||||
|
cd cmake-build-debug
|
||||||
|
cmake -DBUILD_TESTS=ON -G Ninja ../ && ninja -j 16 && ./BLT_TESTS
|
||||||
|
cd ..
|
|
@ -134,7 +134,6 @@ namespace blt {
|
||||||
}
|
}
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
node_binary_search_tree() = default;
|
node_binary_search_tree() = default;
|
||||||
|
|
||||||
|
@ -153,58 +152,56 @@ namespace blt {
|
||||||
void remove(const T& element) {
|
void remove(const T& element) {
|
||||||
BST_node* parent = nullptr;
|
BST_node* parent = nullptr;
|
||||||
BST_node* elementNode = search(&parent, element);
|
BST_node* elementNode = search(&parent, element);
|
||||||
|
if (parent == elementNode)
|
||||||
BST_node*& parentChildSide = parent->left;
|
parent = nullptr;
|
||||||
if (parent->right == elementNode)
|
|
||||||
parentChildSide = parent->right;
|
|
||||||
|
|
||||||
if (elementNode->left != nullptr && elementNode->right != nullptr) {
|
if (elementNode->left != nullptr && elementNode->right != nullptr) {
|
||||||
// root node special case: TODO: better way of doing this.
|
BST_node* inOrderSuccessor = elementNode->left != nullptr ? elementNode->left : elementNode->right;
|
||||||
/*auto& leastNodeGreater = findMin(elementNode->right);
|
BST_node* inOrderSuccessorParent = nullptr;
|
||||||
if (parent != elementNode) {
|
// go all the way to the left subtree
|
||||||
// move up the node and delete the old one.
|
while (inOrderSuccessor->left != nullptr) {
|
||||||
parentChildSide->payload = leastNodeGreater->payload;
|
inOrderSuccessorParent = inOrderSuccessor;
|
||||||
if (leastNodeGreater->parent->left == leastNodeGreater)
|
inOrderSuccessor = inOrderSuccessor->left;
|
||||||
leastNodeGreater->parent->left = nullptr;
|
}
|
||||||
|
// make sure we maintain the tree structure if our moving node has a subtree
|
||||||
|
BST_node* inOrderSuccessorReplacement = inOrderSuccessor->right != nullptr ? inOrderSuccessor->right : nullptr;
|
||||||
|
|
||||||
|
if (parent != nullptr) {
|
||||||
|
if (parent->right == elementNode)
|
||||||
|
parent->right = inOrderSuccessor;
|
||||||
|
else if (parent->left == elementNode)
|
||||||
|
parent->left = inOrderSuccessor;
|
||||||
else
|
else
|
||||||
leastNodeGreater->parent->right = nullptr;
|
throw binary_search_tree_error("Parent node doesn't own child!\n");
|
||||||
delete(leastNodeGreater);
|
} else
|
||||||
} else {
|
m_root = inOrderSuccessor;
|
||||||
leastNodeGreater->left =
|
// reconstruct the node's children
|
||||||
}*/
|
inOrderSuccessor->left = elementNode->left;
|
||||||
/* delete(m_root);
|
inOrderSuccessor->right = elementNode->right;
|
||||||
m_root = nullptr;
|
// delete the parent's reference to the moved node
|
||||||
// reconstruct subtree. More efficient way of doing this... TODO
|
if (inOrderSuccessorParent != nullptr){
|
||||||
std::vector<BST_node*> subNodes = inOrderTraverse(elementNode);
|
if (inOrderSuccessorParent->left == inOrderSuccessor)
|
||||||
for (auto* node : subNodes) {
|
inOrderSuccessorParent->left = inOrderSuccessorReplacement;
|
||||||
// insert will create a new node, we must delete old one to prevent memory leaks
|
else if (inOrderSuccessorParent->right == inOrderSuccessor)
|
||||||
if (node != elementNode) {
|
inOrderSuccessorParent->right = inOrderSuccessorReplacement;
|
||||||
insert(node->payload);
|
else
|
||||||
delete (node);
|
throw binary_search_tree_error("Parent does not contain child!\n");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// reconstruct subtree. More efficient way of doing this... TODO
|
|
||||||
std::vector<BST_node*> subNodes = inOrderTraverse(elementNode);
|
|
||||||
for (auto* node : subNodes) {
|
|
||||||
// insert will create a new node, we must delete old one to prevent memory leaks
|
|
||||||
if (node != elementNode) {
|
|
||||||
insert(parent, node->payload);
|
|
||||||
delete (node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
} else {
|
} else {
|
||||||
parentChildSide = elementNode->left != nullptr ? elementNode->left : elementNode->right;
|
auto replacementNode = elementNode->left != nullptr ? elementNode->left : elementNode->right;
|
||||||
|
if (parent == nullptr)
|
||||||
|
m_root = replacementNode;
|
||||||
|
else {
|
||||||
|
if (parent->right == elementNode)
|
||||||
|
parent->right = replacementNode;
|
||||||
|
else if (parent->left == elementNode)
|
||||||
|
parent->left = replacementNode;
|
||||||
|
else
|
||||||
|
throw binary_search_tree_error("Parent node doesn't contain element of search!\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
std::cout << elementNode << "\n";
|
delete (elementNode);
|
||||||
//delete (elementNode);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
/*void remove(const T& element) {
|
|
||||||
remove(m_root, element);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
inline std::vector<BST_node*> inOrderTraverse() {
|
inline std::vector<BST_node*> inOrderTraverse() {
|
||||||
return inOrderTraverse(m_root);
|
return inOrderTraverse(m_root);
|
||||||
|
|
|
@ -32,9 +32,12 @@ void binaryTreeTest(){
|
||||||
auto searchedNode = dataTree.search(10);
|
auto searchedNode = dataTree.search(10);
|
||||||
std::cout << "10's children: "<< searchedNode->left->payload << ", " << searchedNode->right->payload << "\n";
|
std::cout << "10's children: "<< searchedNode->left->payload << ", " << searchedNode->right->payload << "\n";
|
||||||
|
|
||||||
dataTree.remove(4);
|
dataTree.remove(10);
|
||||||
|
|
||||||
printBinaryTree(dataTree);
|
printBinaryTree(dataTree);
|
||||||
|
|
||||||
|
//searchedNode = dataTree.search(8);
|
||||||
|
//std::cout << "8's children: "<< searchedNode->left->payload << ", " << searchedNode->right->payload << "\n";
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue