mirror of
https://github.com/tiennm99/CTDL-GT.git
synced 2026-06-09 18:13:38 +00:00
274 lines
5.6 KiB
C++
274 lines
5.6 KiB
C++
//use "balance" varialbe as "height"
|
|
|
|
#include "TreeSet.h"
|
|
|
|
static bool isSuccess;
|
|
|
|
TreeSet::TreeSet()
|
|
{
|
|
root = nullptr;
|
|
count = 0;
|
|
}
|
|
|
|
TreeSet::~TreeSet()
|
|
{
|
|
clear();
|
|
}
|
|
|
|
void TreeSet::clearRec(AVLNode *root)
|
|
{
|
|
if (root != nullptr) {
|
|
clearRec(root->left);
|
|
clearRec(root->right);
|
|
delete root;
|
|
}
|
|
}
|
|
|
|
void TreeSet::clear()
|
|
{
|
|
clearRec(root);
|
|
root = nullptr;
|
|
count = 0;
|
|
}
|
|
|
|
int TreeSet::add(int val)
|
|
{
|
|
isSuccess = false;
|
|
root = recursiveAdd(root, val);
|
|
if (isSuccess) {
|
|
++count;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool TreeSet::contains(int val)
|
|
{
|
|
AVLNode *temp = root;
|
|
while (temp != nullptr) {
|
|
if (temp->key > val)
|
|
temp = temp->left;
|
|
else if (temp->key < val)
|
|
temp = temp->right;
|
|
else
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void TreeSet::copy(const TreeSet &set)
|
|
{
|
|
clear();
|
|
root = recursiveCopy(set.root);
|
|
count = set.count;
|
|
}
|
|
|
|
int TreeSet::first()
|
|
{
|
|
if (root == nullptr) {
|
|
throw "NoSuchElementException";
|
|
}
|
|
AVLNode *temp = root;
|
|
while (temp->left != nullptr)
|
|
temp = temp->left;
|
|
return temp->key;
|
|
}
|
|
|
|
int TreeSet::last()
|
|
{
|
|
if (root == nullptr) {
|
|
throw "NoSuchElementException";
|
|
}
|
|
AVLNode *temp = root;
|
|
while (temp->right != nullptr)
|
|
temp = temp->right;
|
|
return temp->key;
|
|
}
|
|
|
|
int TreeSet::higher(int val)
|
|
{
|
|
if (root == nullptr)
|
|
return -1;
|
|
int higher = last();
|
|
if (val >= higher)
|
|
return -1;
|
|
AVLNode *temp = root;
|
|
while (temp != nullptr) {
|
|
if (temp->key > val) {
|
|
if (temp->key < higher)
|
|
higher = temp->key;
|
|
temp = temp->left;
|
|
} else {
|
|
temp = temp->right;
|
|
}
|
|
}
|
|
return higher;
|
|
}
|
|
|
|
int TreeSet::lower(int val)
|
|
{
|
|
if (root == nullptr)
|
|
return -1;
|
|
int lower = first();
|
|
if (val <= lower)
|
|
return -1;
|
|
AVLNode *temp = root;
|
|
while (temp != nullptr) {
|
|
if (temp->key < val) {
|
|
if (temp->key > lower)
|
|
lower = temp->key;
|
|
temp = temp->right;
|
|
} else {
|
|
temp = temp->left;
|
|
}
|
|
}
|
|
return lower;
|
|
}
|
|
|
|
int TreeSet::remove(int val)
|
|
{
|
|
isSuccess = false;
|
|
root = recursiveRemove(root, val);
|
|
if (isSuccess) {
|
|
--count;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
TreeSet *TreeSet::subSet(int fromVal, int toVal)
|
|
{
|
|
TreeSet *subSet = new TreeSet;
|
|
recursiveSubSet(subSet, root, fromVal, toVal);
|
|
return subSet;
|
|
}
|
|
|
|
int TreeSet::size()
|
|
{
|
|
return count;
|
|
}
|
|
|
|
int TreeSet::getHeight(AVLNode *node)
|
|
{
|
|
if (node == nullptr)
|
|
return 0;
|
|
return node->balance;
|
|
}
|
|
|
|
void TreeSet::setHeight(AVLNode *&node)
|
|
{
|
|
node->balance = max(getHeight(node->left), getHeight(node->right)) + 1;
|
|
}
|
|
|
|
int TreeSet::getBalance(AVLNode *node)
|
|
{
|
|
if (node == nullptr)
|
|
return 0;
|
|
return getHeight(node->left) - getHeight(node->right);
|
|
}
|
|
|
|
void TreeSet::recursiveSubSet(TreeSet *&subSet, AVLNode *node, int fromVal, int toVal)
|
|
{
|
|
if (node == nullptr)
|
|
return;
|
|
if (node->key < fromVal) {
|
|
recursiveSubSet(subSet, node->right, fromVal, toVal);
|
|
} else if (node->key < toVal) {
|
|
subSet->add(node->key);
|
|
recursiveSubSet(subSet, node->left, fromVal, toVal);
|
|
recursiveSubSet(subSet, node->right, fromVal, toVal);
|
|
} else {
|
|
recursiveSubSet(subSet, node->left, fromVal, toVal);
|
|
}
|
|
}
|
|
|
|
AVLNode *TreeSet::recursiveAdd(AVLNode *&node, int val)
|
|
{
|
|
if (node == nullptr) {
|
|
isSuccess = true;
|
|
return new AVLNode(val, 1);
|
|
}
|
|
if (node->key == val)
|
|
return node;
|
|
if (node->key > val)
|
|
node->left = recursiveAdd(node->left, val);
|
|
else
|
|
node->right = recursiveAdd(node->right, val);
|
|
setHeight(node);
|
|
return rebalance(node);
|
|
}
|
|
|
|
AVLNode *TreeSet::recursiveRemove(AVLNode *&node, int val)
|
|
{
|
|
if (node == nullptr)
|
|
return node;
|
|
if (node->key > val) {
|
|
node->left = recursiveRemove(node->left, val);
|
|
} else if (node->key < val) {
|
|
node->right = recursiveRemove(node->right, val);
|
|
} else {
|
|
if (node->left == nullptr) {
|
|
AVLNode *temp = node->right;
|
|
delete node;
|
|
isSuccess = true;
|
|
return temp;
|
|
}
|
|
AVLNode *delNode = node->left;
|
|
while (delNode->right != nullptr)
|
|
delNode = delNode->right;
|
|
node->key = delNode->key;
|
|
node->left = recursiveRemove(node->left, node->key);
|
|
}
|
|
return rebalance(node);
|
|
}
|
|
|
|
AVLNode *TreeSet::recursiveCopy(AVLNode *node)
|
|
{
|
|
if (node == nullptr)
|
|
return node;
|
|
AVLNode *temp = new AVLNode(node->key, node->balance);
|
|
temp->left = recursiveCopy(node->left);
|
|
temp->right = recursiveCopy(node->right);
|
|
return temp;
|
|
}
|
|
|
|
AVLNode *TreeSet::rotateLeft(AVLNode *&node)
|
|
{
|
|
AVLNode *temp = node->right;
|
|
AVLNode *tmp = temp->left;
|
|
node->right = tmp;
|
|
temp->left = node;
|
|
setHeight(node);
|
|
setHeight(temp);
|
|
return temp;
|
|
}
|
|
|
|
AVLNode *TreeSet::rotateRight(AVLNode *&node)
|
|
{
|
|
AVLNode *temp = node->left;
|
|
AVLNode *tmp = temp->right;
|
|
node->left = tmp;
|
|
temp->right = node;
|
|
setHeight(node);
|
|
setHeight(temp);
|
|
return temp;
|
|
}
|
|
|
|
AVLNode *TreeSet::rebalance(AVLNode *&node)
|
|
{
|
|
if (node == nullptr)
|
|
return nullptr;
|
|
int balance = getBalance(node);
|
|
if (balance > 1) {
|
|
if (getBalance(node->left) < -1)
|
|
node->left = rotateLeft(node->left);
|
|
node = rotateRight(node);
|
|
} else if (balance < -1) {
|
|
if (getBalance(node->right) > 1)
|
|
node->right = rotateRight(node->right);
|
|
node = rotateLeft(node);
|
|
}
|
|
return node;
|
|
}
|