Bnode merge(Bnode parent, int position)
        {
            Bnode left        = parent.children[position];
            Bnode right       = parent.children[position + 1];
            int   newPosition = left.insert(parent.keys[position]);

            moveParent(left, newPosition + 1, right.children[0]);
            for (int i = 0; i < right.n; i++)
            {
                newPosition = left.insert(right.keys[i]);
                moveParent(left, newPosition + 1, right.children[i + 1]);
            }
            parent.delete(position);
            return(left);
        }
        void rightRotate(Bnode parent, int position)
        {
            Bnode left        = parent.children[position];
            Bnode right       = parent.children[position + 1];
            int   newPosition = right.insert(parent.keys[position]);

            right.children[1] = right.children[0];
            moveParent(right, newPosition, left.children[left.n]);
            parent.keys[position] = left.keys[left.n - 1];
            left.n--;
        }
        void leftRotate(Bnode parent, int position)
        {
            Bnode left        = parent.children[position];
            Bnode right       = parent.children[position + 1];
            int   newPosition = left.insert(parent.keys[position]);

            moveParent(left, newPosition + 1, right.children[0]);
            parent.keys[position] = right.keys[0];
            right.children[0]     = right.children[1];
            right.delete(0);
        }
        public void insert(ref Bnode root, int key)
        {
            int currentDepth = 0;

            if (root == null)
            {
                root = new Bnode(m);//,0);
                root.insert(key);
            }
            else
            {
                Bnode current = root;
                while (true)
                {
                    if (current.children[0] == null)   //insert must be in leaf
                    {
                        int position = current.insert(key);
                        while (current.n > current.size)   //overflow
                                                           //split the node
                        {
                            Object[] result = split(ref root, current, currentDepth);
                            //try to insert middle key to parent
                            Bnode newNode = (Bnode)result[0];
                            key      = (int)result[1]; //separator
                            current  = current.parent;
                            position = current.insert(key);
                            current.children[position + 1] = newNode;
                        }
                        break;
                    }
                    current = current.children[current.findPosition(key)];

                    currentDepth++;
                }
            }
        }
        // other
        Object[] split(ref Bnode root, Bnode node, int currentDepth)
        {
            int mid = node.n / 2;

            if (node.parent == null)
            {
                root             = new Bnode(m);//, currentDepth);
                root.children[0] = node;
                node.parent      = root;
            }
            Bnode newNode = new Bnode(m);//, currentDepth);

            newNode.parent = node.parent;
            int nk = 0;

            for (int k = mid + 1; k < node.n; k++, nk++)
            {
                newNode.insert(node.keys[k]);
                moveParent(newNode, nk, node.children[k]);
            }
            moveParent(newNode, nk, node.children[node.n]);
            node.n = mid;
            return(new Object[] { newNode, node.keys[mid] });
        }