mirror of https://github.com/xfarrow/lasd.git
389 lines
11 KiB
C++
Executable File
389 lines
11 KiB
C++
Executable File
|
|
namespace lasd {
|
|
|
|
template <typename Data>
|
|
BST<Data>::BST(const LinearContainer<Data>& lc){
|
|
for(ulong i=0 ; i<lc.Size() ; ++i){
|
|
Insert(lc[i]);
|
|
}
|
|
}
|
|
|
|
template <typename Data>
|
|
BST<Data>::BST(const BST<Data>& bst)
|
|
: BinaryTreeLnk<Data>(bst){}
|
|
|
|
template <typename Data>
|
|
BST<Data>::BST(BST<Data>&& bst) noexcept
|
|
: BinaryTreeLnk<Data>(std::move(bst)){}
|
|
|
|
template <typename Data>
|
|
BST<Data>::~BST(){
|
|
BinaryTreeLnk<Data>::Clear();
|
|
}
|
|
|
|
template <typename Data>
|
|
BST<Data>& BST<Data>::operator=(const BST<Data>& bst){
|
|
BinaryTreeLnk<Data>::operator=(bst);
|
|
return *this;
|
|
}
|
|
|
|
template <typename Data>
|
|
BST<Data>& BST<Data>::operator=(BST<Data>&& bst) noexcept{
|
|
BinaryTreeLnk<Data>::operator=(std::move(bst));
|
|
return *this;
|
|
}
|
|
|
|
template <typename Data>
|
|
bool BST<Data>::operator==(const BST<Data>& bst) const noexcept{
|
|
if(size != bst.Size()) return false;
|
|
|
|
BTInOrderIterator<Data> itr1(*this);
|
|
BTInOrderIterator<Data> itr2(bst);
|
|
|
|
for(; !itr1.Terminated() ; ++itr1, ++itr2){
|
|
if(*itr1 != *itr2) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
template <typename Data>
|
|
bool BST<Data>::operator!=(const BST<Data>& bst) const noexcept{
|
|
return !(*this == bst);
|
|
}
|
|
|
|
template <typename Data>
|
|
void BST<Data>::Insert(const Data& data) noexcept{
|
|
NodeLnk*& pointer = FindPointerTo(root, data);
|
|
if(pointer == nullptr){
|
|
pointer = BinaryTreeLnk<Data>::CreateNode(data);
|
|
size++;
|
|
}
|
|
}
|
|
|
|
template <typename Data>
|
|
void BST<Data>::Insert(Data&& data) noexcept{
|
|
NodeLnk*& pointer = FindPointerTo(root, data);
|
|
if(pointer == nullptr){
|
|
pointer = new NodeLnk();
|
|
std::swap(pointer->value, data);
|
|
size++;
|
|
}
|
|
}
|
|
|
|
template <typename Data>
|
|
void BST<Data>::Remove(const Data& data) noexcept{
|
|
delete Detach(FindPointerTo(root,data));
|
|
}
|
|
|
|
template <typename Data>
|
|
const Data& BST<Data>::Min() const{
|
|
if(root == nullptr) throw std::length_error("Empty tree!");
|
|
return FindPointerToMin(root)->Element();
|
|
}
|
|
|
|
template <typename Data>
|
|
Data BST<Data>::MinNRemove(){
|
|
if(root == nullptr) throw std::length_error("Empty tree!");
|
|
return DataNDelete(DetachMin(root));
|
|
}
|
|
|
|
template <typename Data>
|
|
void BST<Data>::RemoveMin(){
|
|
if(root == nullptr) throw std::length_error("Empty tree!");
|
|
delete DetachMin(root);
|
|
}
|
|
|
|
template <typename Data>
|
|
const Data& BST<Data>::Max() const{
|
|
if(root == nullptr) throw std::length_error("Empty tree!");
|
|
return FindPointerToMax(root)->Element();
|
|
}
|
|
|
|
template <typename Data>
|
|
Data BST<Data>::MaxNRemove(){
|
|
if(root == nullptr) throw std::length_error("Empty tree!");
|
|
return DataNDelete(DetachMax(root));
|
|
}
|
|
|
|
template <typename Data>
|
|
void BST<Data>::RemoveMax(){
|
|
if(root == nullptr) throw std::length_error("Empty tree!");
|
|
delete DetachMax(root);
|
|
}
|
|
|
|
template <typename Data>
|
|
const Data& BST<Data>::Predecessor(const Data& data) const{
|
|
NodeLnk* const* ptr = FindPointerToPredecessor(root, data);
|
|
if(ptr!=nullptr){
|
|
return (*(*ptr)).Element();
|
|
}else{
|
|
throw std::length_error("Predecessor not found!");
|
|
}
|
|
}
|
|
|
|
template <typename Data>
|
|
Data BST<Data>::PredecessorNRemove(const Data& data){
|
|
NodeLnk** ptr = FindPointerToPredecessor(root,data);
|
|
if(ptr!=nullptr){
|
|
return DataNDelete(Detach(*ptr));
|
|
}else{
|
|
throw std::length_error("Predecessor not found!");
|
|
}
|
|
}
|
|
|
|
template <typename Data>
|
|
void BST<Data>::RemovePredecessor(const Data& data){
|
|
NodeLnk** ptr = FindPointerToPredecessor(root,data);
|
|
if(ptr!=nullptr){
|
|
delete Detach(*ptr);
|
|
}else{
|
|
throw std::length_error("Predecessor not found!");
|
|
}
|
|
}
|
|
|
|
template <typename Data>
|
|
const Data& BST<Data>::Successor(const Data& data) const{
|
|
NodeLnk* const* ptr = FindPointerToSuccessor(root, data);
|
|
if(ptr!=nullptr){
|
|
return (*(*ptr)).Element();
|
|
}else{
|
|
throw std::length_error("Successor not found!");
|
|
}
|
|
}
|
|
|
|
template <typename Data>
|
|
Data BST<Data>::SuccessorNRemove(const Data& data){
|
|
NodeLnk** ptr = FindPointerToSuccessor(root,data);
|
|
if(ptr!=nullptr){
|
|
return DataNDelete(Detach(*ptr));
|
|
}else{
|
|
throw std::length_error("Successor not found!");
|
|
}
|
|
}
|
|
|
|
template <typename Data>
|
|
void BST<Data>::RemoveSuccessor(const Data& data){
|
|
NodeLnk** ptr = FindPointerToSuccessor(root,data);
|
|
if(ptr!=nullptr){
|
|
delete Detach(*ptr);
|
|
}else{
|
|
throw std::length_error("Successor not found!");
|
|
}
|
|
}
|
|
|
|
template <typename Data>
|
|
bool BST<Data>::Exists(const Data& data) const noexcept{
|
|
return (FindPointerTo(root, data) != nullptr);
|
|
}
|
|
|
|
template <typename Data>
|
|
Data BST<Data>::DataNDelete(struct BST<Data>::NodeLnk* ptr){
|
|
Data data = ptr->Element();
|
|
delete ptr;
|
|
return data;
|
|
}
|
|
|
|
template <typename Data>
|
|
typename BST<Data>::NodeLnk* BST<Data>::Detach(struct BST<Data>::NodeLnk*& ptrref) noexcept{
|
|
if(ptrref == nullptr) return nullptr;
|
|
|
|
if(ptrref->left == nullptr){
|
|
return SkipOnRight(ptrref);
|
|
}
|
|
else if(ptrref->right == nullptr){
|
|
return SkipOnLeft(ptrref);
|
|
}
|
|
else{
|
|
NodeLnk* maxNode = DetachMax(ptrref->left);
|
|
std::swap(ptrref->Element() , maxNode->Element());
|
|
return maxNode;
|
|
}
|
|
}
|
|
|
|
template <typename Data>
|
|
typename BST<Data>::NodeLnk* BST<Data>::DetachMin(struct BST<Data>::NodeLnk*& ptrref) noexcept{
|
|
return SkipOnRight(FindPointerToMin(ptrref));
|
|
}
|
|
|
|
template <typename Data>
|
|
typename BST<Data>::NodeLnk* BST<Data>::DetachMax(struct BST<Data>::NodeLnk*& ptrref) noexcept{
|
|
return SkipOnLeft(FindPointerToMax(ptrref));
|
|
}
|
|
|
|
template <typename Data>
|
|
typename BST<Data>::NodeLnk* BST<Data>::SkipOnLeft(struct BST<Data>::NodeLnk*& ptrref) noexcept{
|
|
NodeLnk* left = nullptr;
|
|
if(ptrref != nullptr){
|
|
std::swap(left, ptrref->left);
|
|
std::swap(left, ptrref);
|
|
--size;
|
|
}
|
|
return left;
|
|
}
|
|
|
|
template <typename Data>
|
|
typename BST<Data>::NodeLnk* BST<Data>::SkipOnRight(struct BST<Data>::NodeLnk*& ptrref) noexcept{
|
|
NodeLnk* right = nullptr;
|
|
if(ptrref != nullptr){
|
|
std::swap(right, ptrref->right);
|
|
std::swap(right, ptrref);
|
|
--size;
|
|
}
|
|
return right;
|
|
}
|
|
|
|
template <typename Data>
|
|
typename BST<Data>::NodeLnk* const& BST<Data>::FindPointerToMin(struct BST<Data>::NodeLnk* const& node) const noexcept{
|
|
/*
|
|
In order to return a [reference to a] const pointer, we need to
|
|
declare a variable (ptr) which points to a const pointer which points to
|
|
a NodeLnk.
|
|
This const pointer that points to a NodeLnk is the parameter of the function.
|
|
|
|
Hence, *ptr will be a const pointer.
|
|
*/
|
|
NodeLnk* const* ptr = &node;
|
|
NodeLnk* curr = node;
|
|
if(curr!=nullptr){
|
|
while(curr->left != nullptr){
|
|
ptr = &curr->left;
|
|
curr = curr->left;
|
|
}
|
|
}
|
|
return *ptr;
|
|
}
|
|
|
|
template <typename Data>
|
|
typename BST<Data>::NodeLnk*& BST<Data>::FindPointerToMin(struct BST<Data>::NodeLnk*& node) noexcept{
|
|
return const_cast<NodeLnk*&>(static_cast<const BST<Data> *>(this)->FindPointerToMin(node));
|
|
}
|
|
|
|
template <typename Data>
|
|
typename BST<Data>::NodeLnk* const& BST<Data>::FindPointerToMax(struct BST<Data>::NodeLnk* const& node) const noexcept{
|
|
NodeLnk* const* ptr = &node;
|
|
NodeLnk* curr = node;
|
|
if(curr!=nullptr){
|
|
while(curr->right != nullptr){
|
|
ptr = &curr->right;
|
|
curr = curr->right;
|
|
}
|
|
}
|
|
return *ptr;
|
|
}
|
|
|
|
template <typename Data>
|
|
typename BST<Data>::NodeLnk*& BST<Data>::FindPointerToMax(struct BST<Data>::NodeLnk*& node) noexcept{
|
|
return const_cast<NodeLnk*&>(static_cast<const BST<Data> *>(this)->FindPointerToMax(node));
|
|
}
|
|
|
|
template <typename Data>
|
|
typename BST<Data>::NodeLnk* const& BST<Data>::FindPointerTo(struct BST<Data>::NodeLnk* const& ref, Data data) const noexcept{
|
|
/*
|
|
In order to return a [reference to a] const pointer, we need to
|
|
declare a variable (pointer) which points to a const pointer which points to
|
|
a NodeLnk.
|
|
This const pointer that points to a NodeLnk is the parameter of the function.
|
|
|
|
Hence, *pointer will be a const pointer.
|
|
*/
|
|
NodeLnk* const* pointer = &ref; //a pointer to a const pointer to a NodeLnk
|
|
NodeLnk* current = ref;
|
|
|
|
while(current != nullptr && current->Element() != data){
|
|
if(current->Element() < data){
|
|
pointer = &(current->right);
|
|
current = current->right;
|
|
}else if(current->Element() > data){
|
|
pointer = &(current->left);
|
|
current = current->left;
|
|
}
|
|
}
|
|
return *pointer;
|
|
}
|
|
|
|
template <typename Data>
|
|
typename BST<Data>::NodeLnk* const* BST<Data>::FindPointerToPredecessor(struct BST<Data>::NodeLnk* const& ref, Data data) const noexcept{
|
|
|
|
/*
|
|
If the element we are looking the predecessor for is the current element,
|
|
then its predecessor resides in the max node of its left subtree (if it has
|
|
a left subtree. Return the lastRight otherwise).
|
|
|
|
If the element we are looking the predecessor for is greater than the current element,
|
|
then we have to go down right the tree, saving the current "lastRight".
|
|
|
|
If the element we are looking the predecessor for is less than the current element,
|
|
then we have to go down left the tree.
|
|
|
|
|
|
Note: I return a ** instead of *& because we deferenciate a variable that might
|
|
contain nullptr (lastRight) that, without proper handling, would result to
|
|
an invalid read. I decided to keep it simpler to understand.
|
|
*/
|
|
|
|
NodeLnk* const* pointer = &ref;
|
|
NodeLnk* current = ref;
|
|
NodeLnk* const* candidate = nullptr;
|
|
|
|
while(current != nullptr){
|
|
if(data == current->Element()){
|
|
if(current->HasLeftChild()){
|
|
return &(FindPointerToMax(current->left));
|
|
}else{
|
|
return candidate;
|
|
}
|
|
}else if(current->Element() < data){
|
|
candidate = pointer;
|
|
pointer = &(current->right);
|
|
current = current->right;
|
|
}else if(current->Element() > data){
|
|
pointer = &(current->left);
|
|
current = current->left;
|
|
}
|
|
}
|
|
return candidate;
|
|
}
|
|
|
|
template <typename Data>
|
|
typename BST<Data>::NodeLnk* const* BST<Data>::FindPointerToSuccessor(struct BST<Data>::NodeLnk* const& ref, Data data) const noexcept{
|
|
NodeLnk* const* pointer = &ref;
|
|
NodeLnk* current = ref;
|
|
NodeLnk* const* candidate = nullptr;
|
|
|
|
while( current != nullptr){
|
|
if(data == current->Element()){
|
|
if(current->HasRightChild()){
|
|
return &(FindPointerToMin(current->right));
|
|
}
|
|
else{
|
|
return candidate;
|
|
}
|
|
}else if(current->Element() > data){
|
|
candidate = pointer;
|
|
pointer = ¤t->left;
|
|
current = current->left;
|
|
}else if(current->Element() < data){
|
|
pointer = ¤t->right;
|
|
current = current->right;
|
|
}
|
|
}
|
|
return candidate;
|
|
}
|
|
|
|
template <typename Data>
|
|
typename BST<Data>::NodeLnk*& BST<Data>::FindPointerTo(struct BST<Data>::NodeLnk*& node, Data data) noexcept{
|
|
return const_cast<NodeLnk*&>(static_cast<const BST<Data> *>(this)->FindPointerTo(node, data));
|
|
}
|
|
|
|
template <typename Data>
|
|
typename BST<Data>::NodeLnk** BST<Data>::FindPointerToPredecessor(struct BST<Data>::NodeLnk*& node, Data data) noexcept{
|
|
return const_cast<NodeLnk**>(static_cast<const BST<Data> *>(this)->FindPointerToPredecessor(node, data));
|
|
}
|
|
|
|
template <typename Data>
|
|
typename BST<Data>::NodeLnk** BST<Data>::FindPointerToSuccessor(struct BST<Data>::NodeLnk*& node, Data data) noexcept{
|
|
return const_cast<NodeLnk**>(static_cast<const BST<Data> *>(this)->FindPointerToSuccessor(node, data));
|
|
}
|
|
|
|
}
|