---
# System prepended metadata

title: 12793 - Rolling Balls

---

# 12793 - Rolling Balls
> author: CCL
problem: http://140.114.86.238/problem/12793/


- need to take care of less_large's left child
- special case: deleting root node's left child
- recursively freetree is necessary, else would make MLE&RE!

```cpp
#include <iostream>
#include <cstdbool>
#include"function.h"
// CCL

bool Color::operator < (const Color& other) const
{
    // compare r->g->b
    if(r < other.r) return true;
    else if(r > other.r) return false;
    else{
        // now r == other.r
        if(g < other.g) return true;
        else if(g > other.g) return false;
        else{
            // now g == other.g
            if(b < other.b) return true;
            else return false;
        }
    }

}

bool Color::operator > (const Color& other) const
{
    if(r > other.r) return true;
    else if(r < other.r) return false;
    else{
        if(g > other.g) return true;
        else if(g < other.g) return false;
        else{
            if(b > other.b) return true;
            else return false;
        }
    }
}

bool Color::operator == (const Color& other) const
{
    if(r != other.r || g != other.g || b != other.b)
        return false;
    else return true;
}

Color& Color::operator = (const Color& other)
{
    this->r = other.r;
    this->g = other.g;
    this->b = other.b;
    return *this;
}

Node::Node()
{
    key = Color();
    value = 1;
    left = right = nullptr;
}

Node::~Node()
{
}

MultiSet_Tree::MultiSet_Tree()
{
    root = nullptr;
}

void freetree(Node* root)
{
    if(root == NULL)
        return;
    freetree(root->left);
    freetree(root->right);
    free(root);
}

MultiSet_Tree::~MultiSet_Tree()
{
    freetree(root);
}

void MultiSet_Tree::Insert(const Color& input)
{
    if(root == nullptr){
        root = new Node();
        root->key = input;
    }
    else{
        Node* ptr = root;
        Node* par = root;
        
        while(ptr != nullptr){
            if(input == ptr->key){
                ptr->value++;
                return;
            }
            else if(input < ptr->key){
                par = ptr;
                ptr = ptr->left;
            }
            else{
                par = ptr;
                ptr = ptr->right;
            }
        }
        
        if(input < par->key){
            par->left = new Node();
            par->left->key = input;
        }
        else{
            par->right = new Node();
            par->right->key = input;
        }
        
    }
}

void MultiSet_Tree::Delete(const Color& input)
{
    /*
    Case 1 - x not exist: do nothing
    Case 2 - x exists with amount    > 1: find x and decrease its amount by one
    Case 3 - x exists with amount  == 1: remove x from the tree 
        1.Node x has 2 children: replace x by the Node with the largest key among the keys less than x.
        2.Node x has 1 child: replace x by its child Node
        3.Node x has no child: replace x by NULL.
    */
    // first, get the node
    Node* ptr = root;
    Node* par = root;
    while(ptr != nullptr){
        if(ptr->key == input)
            break;
        else if(input < ptr->key){
            par = ptr;
            ptr = ptr->left;
        }
        else {
            par = ptr;
            ptr = ptr->right;
        }
    }

    // case1
    if(ptr == nullptr)  
        return;
    // case2
    else if(ptr->value > 1)
        ptr->value --;
    // case3
    else{
        Node* child;
        // 非雙子
        if(ptr->left == nullptr || ptr->right == nullptr){
            if(ptr->left == nullptr)
                child = ptr->right;
            else child = ptr->left;

            if(ptr == root)
                root = child;
            else if(ptr == par->left)
                par->left = child;
            else par->right = child;
            
            delete ptr;
        }
        // 雙子
        else{
            // need to take care of less_large's left child
            Node* less_large_par = ptr; 
            Node* less_large = ptr->left;
            while(less_large->right != nullptr){
                less_large_par = less_large;
                less_large = less_large->right;
            }
            ptr->key = less_large->key;
            ptr->value = less_large->value;
            
            // special case!!
            if(less_large_par->left == less_large) less_large_par->left = less_large->left;
            else less_large_par->right = less_large->left; 
            
            delete less_large;
        }
    }
}

const int MultiSet_Tree::Search(const Color& input) const
{
    // return the value(num) of this Color
    if(root == nullptr)
        return 0;
    Node* ptr = root;
    while( ptr != nullptr ){
        if(input == ptr->key)
            return ptr->value;
        else if(input < ptr->key)
            ptr = ptr->left;
        else ptr = ptr->right;
    }
    return 0;
}
```

### Solution 1

```cpp
#include "function.h"

void deleteTree(Node *root) {
    if (root) {
        deleteTree(root->left);
        deleteTree(root->right);
        delete root;
    }
}

bool Color::operator < (const Color& other) const {
    if (r < other.r) {
        return true;
    } else if (r == other.r) {
        if (g < other.g) {
            return true;
        } else if (g == other.g) {
            if (b < other.b) {
                return true;
            }
        }
    }
    
    return false;
}

bool Color::operator > (const Color& other) const {
    if (r > other.r) {
        return true;
    } else if (r == other.r) {
        if (g > other.g) {
            return true;
        } else if (g == other.g) {
            if (b > other.b) {
                return true;
            }
        }
    }

    
    return false;
}

bool Color::operator == (const Color& other) const {
    if (r == other.r && g == other.g && b == other.b) {
        return true;
    }
    
    return false;
}

Color& Color::operator = (const Color& other) {
    if (this != &other) {
        r = other.r;
        g = other.g;
        b = other.b;
    }
    
    return *this;
}

Node::Node() {
    value = 1;
    left = nullptr;
    right = nullptr;
}

Node::~Node() {
    
}

MultiSet_Tree::MultiSet_Tree() {
    root = nullptr;
}

MultiSet_Tree::~MultiSet_Tree() {
    deleteTree(root);
}

void MultiSet_Tree::Insert(const Color &ball) {
    Node **currentNode = &root;
    
    while (*currentNode) {
        if (ball > (*currentNode)->key) {
            currentNode = &(*currentNode)->right;
        } else if (ball < (*currentNode)->key) {
            currentNode = &(*currentNode)->left;
        } else {
            (*currentNode)->value++;
            return;
        }
    }
    
    *currentNode = new Node();
    (*currentNode)->key = ball;
}

void MultiSet_Tree::Delete(const Color &ball) {
    Node **currentNode = &root;
    
    while (*currentNode) {
        if (ball > (*currentNode)->key) {
            currentNode = &(*currentNode)->right;
        } else if (ball < (*currentNode)->key) {
            currentNode = &(*currentNode)->left;
        } else {
            if ((*currentNode)->value > 1) {
                (*currentNode)->value--;
            } else {
                if ((*currentNode)->left && (*currentNode)->right) {
                    Node **largestNode = &(*currentNode)->left;
                    while ((*largestNode)->right) {
                        largestNode = &(*largestNode)->right;
                    }
                    Node *tmp = (*largestNode)->left;
                    (*currentNode)->key =(*largestNode)->key;
                    (*currentNode)->value =(*largestNode)->value;
                    delete *largestNode;
                    *largestNode = tmp;
                } else if ((*currentNode)->left) {
                    Node *tmp = (*currentNode)->left;
                    delete *currentNode;
                    *currentNode = tmp;
                } else if ((*currentNode)->right) {
                    Node *tmp = (*currentNode)->right;
                    delete *currentNode;
                    *currentNode = tmp;
                } else {
                    delete *currentNode;
                    *currentNode = nullptr;
                }
            }
                
            return;
        }
    }
}

const int MultiSet_Tree::Search(const Color &ball) const {
    Node *currentNode = root;
    
    while (currentNode) {
        if (ball > currentNode->key) {
            currentNode = currentNode->right;
        } else if (ball < currentNode->key) {
            currentNode = currentNode->left;
        } else {
            return currentNode->value;
        }
    }
    
    return 0;
}

// By koihia
```