redblacktree_quantile.hpp

Back to Red-black tree

pastel/sys/redblacktree/

#ifndef PASTELSYS_REDBLACKTREE_QUANTILE_HPP
#define PASTELSYS_REDBLACKTREE_QUANTILE_HPP

#include "pastel/sys/redblacktree/redblacktree_quantile.h"

namespace Pastel
{

    template <typename Settings, template <typename> class Customization>
    typename RedBlackTree<Settings, Customization>::ConstIterator
    quantile(
        const RedBlackTree<Settings, Customization>& tree,
        real alpha)
    {
        /*
       Let n = tree.size(), and

       f : ZZ --> RR: f(i) = (i + 0.5) / n.

       Then

       f(i) = alpha
       <=>
       f(i) n = alpha n
       <=>
       i + 0.5 = alpha n
       <=>
       i = alpha n - 0.5

       Since i is an integer, this equation may not have
       a solution. Therefore, we use the closest integer
       instead:

       i = round(alpha n - 0.5) = floor(alpha n)
       */

        integer searchIndex = std::floor(alpha * tree.size());
        if (searchIndex <= 0)
        {
            return tree.cbegin();
        }
        if (searchIndex >= tree.size() - 1)
        {
            return tree.clast();
        }

        using ConstIterator = 
            typename RedBlackTree<Settings, Customization>::ConstIterator;

        ConstIterator node = tree.croot();

        integer i = node.left().size();
        while (i != searchIndex)
        {
            ASSERT(!node.isSentinel());

            bool right = i < searchIndex;
            node = node.child(right);

            if (right)
            {
                i += node.left().size() + 1;
            }
            else
            {
                i -= node.right().size() + 1;
            }
        }

        return node;
    }

}

#endif