#include "nodes.h" BasicInfo::~BasicInfo(){} // This method searches a Node in the tree by comparing its data with the // data in the existing nodes. // Parameters: The data to search. // Return value: A pointer to the found node, if found, NULL pointer otherwise. NodePtr Node::Find(const BasicInfo& toFind) { if((*data) == toFind) return this; if(toFind > (*data)){ if(right == NULL) return NULL; return right->Find(toFind); } if(left == NULL) return NULL; return left->Find(toFind); } // This method inserts a new node into the tree after making sure it's not // already there. // Parameters: The information to insert. // Return value: A pointer to the new node, or NULL if it exists / a failure // occured. NodePtr Node::Insert(BasicInfo& toInsert, NodePtr& Root) { if((*data) == toInsert) return NULL; NodePtr* nextSon = NULL; if(toInsert > (*data)) nextSon = &right; else nextSon = &left; if(*nextSon == NULL){ if((*nextSon = new Node(&toInsert)) == NULL) return NULL; (*nextSon)->daddy = this; if((*nextSon) == right) hRight++; else hLeft++; weight++; return *nextSon; } NodePtr returnVal = (*nextSon)->Insert(toInsert, Root); if(returnVal != NULL){ if((*nextSon) == right) hRight = max(right->hRight, right->hLeft)+1; else hLeft = max(left->hRight, left->hLeft)+1; weight++; checkBF(Root); } return returnVal; } //remove leaf detaches the leaf-node from the tree //parameters - none //return value - none void Node::removeLeaf(NodePtr& Root) { if(daddy == NULL){ Root = NULL; return; } if(IsRightSon()){ daddy->right = NULL; daddy->hRight = 0; }else{ daddy->left = NULL; daddy->hLeft = 0; } daddy->weight--; daddy = NULL; return; } //this function updates hights and checks if rolls are necessary recursively //until it reaches the root. //parameters: the root, as a reference to its pointer //return value: none void Node::chBF(NodePtr& Root) { calcWeight(); if(left) hLeft = max(left->hLeft, left->hRight)+1; else hLeft = 0; if(right) hRight = max(right->hLeft, right->hRight)+1; else hRight = 0; int balanceFactor = hLeft - hRight; if(balanceFactor > -2 && balanceFactor < 2){ if(daddy) daddy->chBF(Root); return; } if(balanceFactor == -2){ int RbalanceFactor = right->hLeft - right->hRight; if(RbalanceFactor <= 0) rollRR(Root); else rollRL(Root); if(daddy) daddy->chBF(Root); return; } int LbalanceFactor = left->hLeft - left->hRight; if(LbalanceFactor >= 0) rollLL(Root); else rollLR(Root); if(daddy) daddy->chBF(Root); return; } // this function finds a nodes replacer using the following algorithm: // 1. if the node has a right son, than go all the way left from it and return // this node. // 2. if the node has a right son with no left sons, return the right son. // 3. if the node only has a left son, return it. // otherwise it's a leaf and being taken care of earlier. // parameters: none. It's a node's function. // return value: the node that will replace "this". NodePtr Node::getReplacer() { NodePtr tRight = NULL; NodePtr tLeft = NULL; tRight = right; tLeft = left; if(right == NULL) return left; NodePtr retVal = right; while(retVal->left) retVal = retVal->left; return retVal; } // The next 4 functions replace a-soon-to-be-deleted node with its replacer, // that is given to it (as well as the tree's root pointer, so it can be // updated if needed. // The first function determines what replacement we need, since there're // differences between replacing a node with its right or left son, or // with some other node. // parameters: the node to be removed, the tree's root pointer. // return value: a pointer to the node from which the tree will check its // correctness. NodePtr Node::Replace(NodePtr toKill, NodePtr& Root) { hRight = toKill->hRight; hLeft = toKill->hLeft; NodePtr retVal = NULL; // replacer is the right son of the replaced if(toKill->right == this) retVal = replaceRightSon(toKill, Root); // replacer is the left son of the replaced else if(toKill->left == this) retVal = replaceleftSon(toKill, Root); //the replacer is not any son of the replaced else retVal = replaceNotASon(toKill, Root); toKill->right = NULL; toKill->left = NULL; delete toKill; return retVal; } NodePtr Node::replaceRightSon(NodePtr toKill, NodePtr& Root) { weight = toKill->weight-1; if(toKill->daddy == NULL){ Root = this; daddy = NULL; left = toKill->left; }else{ if(toKill->IsRightSon()) toKill->daddy->right = this; else toKill->daddy->left = this; daddy = toKill->daddy; left = toKill->left; toKill->daddy = NULL; } if(left) left->daddy = this; return this; } NodePtr Node::replaceleftSon(NodePtr toKill, NodePtr& Root) { weight = toKill->weight-1; if(toKill->daddy == NULL){ Root = this; daddy = NULL; }else{ if(toKill->IsRightSon()) toKill->daddy->right = this; else toKill->daddy->left = this; daddy = toKill->daddy; toKill->daddy = NULL; } return this; } NodePtr Node::replaceNotASon(NodePtr toKill, NodePtr& Root) { daddy->weight --; NodePtr retVal = daddy; if(right){ daddy->left = right; right->daddy = daddy; }else daddy->left = NULL; left = toKill->left; right = toKill->right; right->daddy = this; left->daddy = this; if(toKill->daddy == NULL){ Root = this; daddy = NULL; }else{ if(toKill->IsRightSon()) toKill->daddy->right = this; else toKill->daddy->left = this; daddy = toKill->daddy; toKill->daddy = NULL; } return retVal; } int max(int a, int b) { return (a > b) ? a : b; } float max(float a, float b) { return (a > b) ? a : b; } // This function checks for "this" if it's a balanced node (heights-wise) and // if not, it determines what sort of "roll" should be done in order to balance // the tree again. // parameters: the tree's root, if needs to be updated. // return value: none. void Node::checkBF(NodePtr& Root) { int balanceFactor = hLeft - hRight; if(balanceFactor > -2 && balanceFactor < 2) return; if(balanceFactor == -2){ int RbalanceFactor = right->hLeft - right->hRight; if(RbalanceFactor <= 0) rollRR(Root); else rollRL(Root); return; } int LbalanceFactor = left->hLeft - left->hRight; if(LbalanceFactor >= 0) rollLL(Root); else rollLR(Root); return; } // The next 4 functions are the 4 different rolls that the tree can perform // in order to make itself balanced again. // parameters: the tree's root, if needs to be updated. // return value: none. void Node::rollRR(NodePtr& Root) { right->daddy = daddy; if(daddy == NULL) Root = right; else{ if(this == daddy->left) daddy->left = right; else daddy->right = right; } daddy = right; right = daddy->left; daddy->left = this; if(right != NULL) right->daddy = this; hRight = daddy->hLeft; daddy->hLeft = max(hLeft, hRight) + 1; calcWeight(); daddy->calcWeight(); return; } void Node::rollLL(NodePtr& Root) { left->daddy = daddy; if(daddy == NULL) Root = left; else{ if(this == daddy->left) daddy->left = left; else daddy->right = left; } daddy = left; left = daddy->right; daddy->right = this; if(left != NULL) left->daddy = this; hLeft = daddy->hRight; daddy->hRight = max(hLeft, hRight) + 1; calcWeight(); daddy->calcWeight(); return; } void Node::rollRL(NodePtr& Root) { right->left->daddy = daddy; if(daddy == NULL) Root = right->left; else{ if(this == daddy->left) daddy->left = right->left; else daddy->right = right->left; } daddy = right->left; right->left = daddy->right; if(right->left != NULL) right->left->daddy = right; daddy->right = right; right->daddy = daddy; right = daddy->left; daddy->left = this; if(right != NULL) right->daddy = this; hRight = daddy->hLeft; daddy->right->hLeft = daddy->hRight; daddy->hRight = max(daddy->right->hLeft, daddy->right->hRight) + 1; daddy->hLeft = max(hLeft, hRight) + 1; calcWeight(); daddy->right->calcWeight(); daddy->calcWeight(); return; } void Node::rollLR(NodePtr& Root) { left->right->daddy = daddy; if(daddy == NULL) Root = left->right; else{ if(this == daddy->left) daddy->left = left->right; else daddy->right = left->right; } daddy = left->right; left->right = left->right->left; if(left->right != NULL) left->right->daddy = left; daddy->left = left; left->daddy = daddy; left = daddy->right; if(left != NULL) left->daddy = this; daddy->right = this; hLeft = daddy->hRight; daddy->left->hRight = daddy->hLeft; daddy->hRight = max(hLeft, hRight) + 1; daddy->hLeft = max(daddy->left->hLeft, daddy->left->hRight) + 1; calcWeight(); daddy->left->calcWeight(); daddy->calcWeight(); return; } // This function finds the median node according to its weight and returns its // salary as the median salary. // parameters: the index to be searched (which represents the number of nodes // that need to be in the median's subtree). // return value: the medain salary. float Node::calcMedian(int medIndex) { int leftWeight = (left == NULL) ? (0) : left->weight; if(medIndex == (leftWeight+1)) return static_cast(getData())->getSal(); if(medIndex <= leftWeight) return left->calcMedian(medIndex); return right->calcMedian(medIndex-leftWeight-1); } // This function's going all the way "right" in the tree - to its biggest // value. // parameters: none. // return value: the node which contains the biggest value. NodePtr Node::goRight() { if(right) return right->goRight(); return this; }