mirror of
https://github.com/autc04/Retro68.git
synced 2024-09-27 12:57:21 +00:00
961 lines
27 KiB
C++
961 lines
27 KiB
C++
// Splay tree utilities -*- C++ -*-
|
|
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
|
|
//
|
|
// This file is part of GCC.
|
|
//
|
|
// GCC is free software; you can redistribute it and/or modify it under
|
|
// the terms of the GNU General Public License as published by the Free
|
|
// Software Foundation; either version 3, or (at your option) any later
|
|
// version.
|
|
//
|
|
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
// for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with GCC; see the file COPYING3. If not see
|
|
// <http://www.gnu.org/licenses/>.
|
|
|
|
// INDEX is either 0 or 1. If it is 0, return NODE's left child,
|
|
// otherwise return NODE's right child.
|
|
template<typename Accessors>
|
|
inline typename base_splay_tree<Accessors>::node_type
|
|
base_splay_tree<Accessors>::get_child (node_type node, unsigned int index)
|
|
{
|
|
return Accessors::child (node, index);
|
|
}
|
|
|
|
// INDEX is either 0 or 1. If it is 0, change NODE's left child to CHILD,
|
|
// otherwise change NODE's right child to CHILD. If CHILD has a parent
|
|
// field, record that its parent is now NODE.
|
|
template<typename Accessors>
|
|
inline void
|
|
base_splay_tree<Accessors>::set_child (node_type node, unsigned int index,
|
|
node_type child)
|
|
{
|
|
Accessors::child (node, index) = child;
|
|
if (child)
|
|
set_parent (child, node);
|
|
}
|
|
|
|
// Rotate the tree to promote child number INDEX of NODE, so that that
|
|
// child becomes a parent of NODE. Return the promoted node.
|
|
//
|
|
// The caller has the responsibility of assigning a correct parent
|
|
// to the returned node.
|
|
template<typename Accessors>
|
|
inline typename base_splay_tree<Accessors>::node_type
|
|
base_splay_tree<Accessors>::promote_child (node_type node, unsigned int index)
|
|
{
|
|
node_type promoted = get_child (node, index);
|
|
set_child (node, index, get_child (promoted, 1 - index));
|
|
set_child (promoted, 1 - index, node);
|
|
return promoted;
|
|
}
|
|
|
|
// Treat child number INDEX of NODE as being CHILD and rotate the tree
|
|
// so that CHILD becomes a parent of NODE.
|
|
//
|
|
// The caller has the responsibility of assigning a correct parent to CHILD.
|
|
template<typename Accessors>
|
|
inline void
|
|
base_splay_tree<Accessors>::promote_child (node_type node, unsigned int index,
|
|
node_type child)
|
|
{
|
|
set_child (node, index, get_child (child, 1 - index));
|
|
set_child (child, 1 - index, node);
|
|
}
|
|
|
|
// Print NODE to PP, using PRINTER (PP, N) to print the contents of node N.
|
|
// Prefix each new line with INDENT_STRING. CODE is 'T' if NODE is the root
|
|
// node, 'L' if NODE is the left child of its parent, or 'R' if NODE is the
|
|
// right child of its parent.
|
|
template<typename Accessors>
|
|
template<typename Printer>
|
|
void
|
|
base_splay_tree<Accessors>::print (pretty_printer *pp, node_type node,
|
|
Printer printer, char code,
|
|
vec<char> &indent_string)
|
|
{
|
|
// In the comments below, PREFIX refers to the incoming contents
|
|
// of INDENT_STRING.
|
|
node_type left = get_child (node, 0);
|
|
node_type right = get_child (node, 1);
|
|
|
|
auto orig_indent_len = indent_string.length ();
|
|
indent_string.safe_grow (orig_indent_len + 3);
|
|
char *extra_indent = indent_string.address () + orig_indent_len;
|
|
|
|
// Print [T], [L], or [R].
|
|
extra_indent[0] = '[';
|
|
extra_indent[1] = code;
|
|
extra_indent[2] = ']';
|
|
pp_append_text (pp, extra_indent, indent_string.end ());
|
|
pp_space (pp);
|
|
|
|
// Print the node itself, using PREFIX + " | " or PREFIX + " " to indent
|
|
// new lines under the "[_]" that we just printed.
|
|
extra_indent[0] = ' ';
|
|
extra_indent[1] = (left || right ? '|' : ' ');
|
|
extra_indent[2] = ' ';
|
|
{
|
|
pretty_printer sub_pp;
|
|
printer (&sub_pp, node);
|
|
const char *text = pp_formatted_text (&sub_pp);
|
|
while (const char *end = strchr (text, '\n'))
|
|
{
|
|
pp_append_text (pp, text, end);
|
|
pp_newline_and_indent (pp, 0);
|
|
pp_append_text (pp, indent_string.begin (), indent_string.end ());
|
|
text = end + 1;
|
|
}
|
|
pp_string (pp, text);
|
|
}
|
|
|
|
if (left)
|
|
{
|
|
// Print PREFIX + " +-" for the first line of the left subtree,
|
|
// to be followed by "[L]".
|
|
extra_indent[1] = '+';
|
|
extra_indent[2] = '-';
|
|
pp_newline_and_indent (pp, 0);
|
|
pp_append_text (pp, indent_string.begin (), indent_string.end ());
|
|
|
|
// Print the left subtree, using PREFIX + " | " or PREFIX + " "
|
|
// to indent under the PREFIX + " +-" that we just printed.
|
|
extra_indent[1] = right ? '|' : ' ';
|
|
extra_indent[2] = ' ';
|
|
print (pp, left, printer, 'L', indent_string);
|
|
extra_indent = indent_string.address () + orig_indent_len;
|
|
|
|
// If LEFT is not a leaf and we also have a right subtree, use a
|
|
// PREFIX + " |" line to separate them.
|
|
if (right && (get_child (left, 0) || get_child (left, 1)))
|
|
{
|
|
pp_newline_and_indent (pp, 0);
|
|
pp_append_text (pp, indent_string.begin (), &extra_indent[2]);
|
|
}
|
|
}
|
|
if (right)
|
|
{
|
|
// Print PREFIX + " +-" for the first line of the right subtree,
|
|
// to be followed by "[R]".
|
|
extra_indent[1] = '+';
|
|
extra_indent[2] = '-';
|
|
pp_newline_and_indent (pp, 0);
|
|
pp_append_text (pp, indent_string.begin (), indent_string.end ());
|
|
|
|
// Print the right subtree, using PREFIX + " " to indent under the
|
|
// PREFIX + " +-" that we just printed.
|
|
extra_indent[1] = ' ';
|
|
extra_indent[2] = ' ';
|
|
print (pp, right, printer, 'R', indent_string);
|
|
}
|
|
indent_string.truncate (orig_indent_len);
|
|
}
|
|
|
|
// See the comment above the declaration.
|
|
template<typename Accessors>
|
|
template<typename Printer>
|
|
void
|
|
base_splay_tree<Accessors>::print (pretty_printer *pp, node_type node,
|
|
Printer printer)
|
|
{
|
|
if (!node)
|
|
{
|
|
pp_string (pp, "null");
|
|
return;
|
|
}
|
|
auto_vec<char, 64> indent_string;
|
|
print (pp, node, printer, 'T', indent_string);
|
|
}
|
|
|
|
// If N is 1, splay the last (rightmost) node reachable from START
|
|
// to the position that START current holds and return the splayed node.
|
|
// START is not itself the last node.
|
|
//
|
|
// If N is 0, splay the first (leftmost) node reachable from START
|
|
// to the position that START current holds and return the splayed node.
|
|
// START is not itself the first node.
|
|
//
|
|
// The caller has the responsibility of updating the parent of the
|
|
// returned node.
|
|
template<typename Accessors>
|
|
template<unsigned int N>
|
|
typename base_splay_tree<Accessors>::node_type
|
|
base_splay_tree<Accessors>::splay_limit (node_type start)
|
|
{
|
|
// This essentially follows the simpilfied top-down method described
|
|
// in Sleator and Tarjan's "Self-adjusting Binary Search Trees", but
|
|
// specialized for the case in which the comparison result is fixed.
|
|
// The first iteration is peeled to avoid the need for stack temporaries.
|
|
//
|
|
// The comments and names reflect the behavior for N == 1, but the
|
|
// N == 0 case behaves analogously.
|
|
|
|
// Rotate the tree to promote the right child of START to the root.
|
|
node_type node = promote_child (start, N);
|
|
if (node_type right = get_child (node, N))
|
|
{
|
|
// Perform the link left step, which for this first iteration
|
|
// means making NODE the root of the left tree.
|
|
//
|
|
// NODE will become left child of the final node. For a right
|
|
// spine starting at NODE of the form:
|
|
//
|
|
// 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> ... -> N
|
|
// | | | | | | | |
|
|
// V V V V V V V V
|
|
// A B C D E F G NL
|
|
//
|
|
// the next step is to create a subtree of N whose right spine contains
|
|
// the odd-numbered nodes, as follows:
|
|
//
|
|
// N
|
|
// |
|
|
// V
|
|
// 1 ------> 3 ------> 5 ------> 7 -> .... -> NL
|
|
// | | | |
|
|
// V V V V
|
|
// A 2 -> C 4 -> E 6 -> G
|
|
// | | |
|
|
// V V V
|
|
// B D F
|
|
//
|
|
// First record 1 as the left child of the final root (N) and move
|
|
// on to node 2.
|
|
node_type final_child = node;
|
|
node_type new_spine_end = node;
|
|
node = right;
|
|
while (node_type right = get_child (node, N))
|
|
{
|
|
// Perform another rotate left step.
|
|
//
|
|
// We've built the tree rooted at 1 in the diagram above up to,
|
|
// but not including, an even-numbered node NODE on the original
|
|
// right spine. Rotate the tree at NODE to promote the following
|
|
// odd-numbered node.
|
|
promote_child (node, N, right);
|
|
node = right;
|
|
if (node_type right = get_child (node, N))
|
|
{
|
|
// Perform another link left step.
|
|
//
|
|
// Add the promoted odd-numbered node to the right spine of the
|
|
// tree rooted at 1 and move on to the next even-numbered node.
|
|
set_child (new_spine_end, N, node);
|
|
new_spine_end = node;
|
|
node = right;
|
|
}
|
|
}
|
|
// Perform the assembly step.
|
|
//
|
|
// Add NL to the new spine and make N the new root.
|
|
set_child (new_spine_end, N, get_child (node, 1 - N));
|
|
set_child (node, 1 - N, final_child);
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// Remove NODE from its position in the splay tree. If NODE has at least
|
|
// one child node, return the node that should now hold NODE's position in
|
|
// the splay tree. If NODE has no children, return null.
|
|
//
|
|
// The caller has the responsibility of updating the parent of the
|
|
// returned node.
|
|
template<typename Accessors>
|
|
inline typename base_splay_tree<Accessors>::node_type
|
|
base_splay_tree<Accessors>::remove_node_internal (node_type node)
|
|
{
|
|
node_type left = get_child (node, 0);
|
|
node_type right = get_child (node, 1);
|
|
if (!left)
|
|
return right;
|
|
|
|
if (!right)
|
|
return left;
|
|
|
|
if (get_child (left, 1))
|
|
{
|
|
left = splay_limit<1> (left);
|
|
gcc_checking_assert (!get_child (left, 1));
|
|
}
|
|
set_child (left, 1, right);
|
|
return left;
|
|
}
|
|
|
|
// See the comment above the declaration.
|
|
template<typename Accessors>
|
|
inline void
|
|
base_splay_tree<Accessors>::insert_child (node_type node, unsigned int index,
|
|
node_type child)
|
|
{
|
|
gcc_checking_assert (!get_child (child, 0) && !get_child (child, 1));
|
|
set_child (child, index, get_child (node, index));
|
|
set_child (node, index, child);
|
|
}
|
|
|
|
// Implement splay_next_node if N == 1 and splay_prev_node if N == 0.
|
|
template<typename Accessors>
|
|
template<unsigned int N>
|
|
bool
|
|
rooted_splay_tree<Accessors>::splay_neighbor ()
|
|
{
|
|
node_type node = m_root;
|
|
node_type new_root = get_child (node, N);
|
|
if (!new_root)
|
|
return false;
|
|
|
|
if (get_child (new_root, 1 - N))
|
|
{
|
|
// NEW_ROOT is not itself the required node, so splay the required
|
|
// node into its place.
|
|
new_root = parent::template splay_limit<1 - N> (new_root);
|
|
gcc_checking_assert (!get_child (new_root, 1 - N));
|
|
set_child (node, N, node_type ());
|
|
set_child (new_root, 1 - N, node);
|
|
}
|
|
else
|
|
promote_child (node, N, new_root);
|
|
set_parent (new_root, node_type ());
|
|
m_root = new_root;
|
|
return true;
|
|
}
|
|
|
|
// See the comment above the declaration.
|
|
template<typename Accessors>
|
|
template<typename Comparator>
|
|
bool
|
|
rooted_splay_tree<Accessors>::insert (node_type new_node, Comparator compare)
|
|
{
|
|
gcc_checking_assert (!get_child (new_node, 0) && !get_child (new_node, 1));
|
|
if (!m_root)
|
|
{
|
|
m_root = new_node;
|
|
return true;
|
|
}
|
|
|
|
int comparison = lookup (compare);
|
|
if (comparison == 0)
|
|
return false;
|
|
|
|
// Insert NEW_NODE before M_ROOT if COMPARISON < 0 and after M_ROOT
|
|
// otherwise.
|
|
set_child (new_node, comparison < 0, m_root);
|
|
set_child (new_node, comparison > 0, get_child (m_root, comparison > 0));
|
|
set_child (m_root, comparison > 0, nullptr);
|
|
m_root = new_node;
|
|
return true;
|
|
}
|
|
|
|
// See the comment above the declaration.
|
|
template<typename Accessors>
|
|
inline void
|
|
rooted_splay_tree<Accessors>::insert_max_node (node_type new_node)
|
|
{
|
|
gcc_checking_assert (!get_child (new_node, 0) && !get_child (new_node, 1));
|
|
set_child (new_node, 0, m_root);
|
|
m_root = new_node;
|
|
}
|
|
|
|
// See the comment above the declaration.
|
|
template<typename Accessors>
|
|
inline void
|
|
rooted_splay_tree<Accessors>::splice_next_tree (rooted_splay_tree next_tree)
|
|
{
|
|
splay_max_node ();
|
|
set_child (m_root, 1, next_tree.m_root);
|
|
}
|
|
|
|
// See the comment above the declaration.
|
|
template<typename Accessors>
|
|
inline void
|
|
rooted_splay_tree<Accessors>::replace_max_node_at_root (node_type new_node)
|
|
{
|
|
node_type old_node = m_root;
|
|
gcc_checking_assert (!get_child (new_node, 0)
|
|
&& !get_child (new_node, 1)
|
|
&& !get_child (old_node, 1));
|
|
set_child (new_node, 0, get_child (old_node, 0));
|
|
// Clear the links from OLD_NODE. Its parent and right child are
|
|
// already node_type ().
|
|
set_child (old_node, 0, node_type ());
|
|
m_root = new_node;
|
|
}
|
|
|
|
// See the comment above the declaration.
|
|
template<typename Accessors>
|
|
inline void
|
|
rooted_splay_tree<Accessors>::remove_root ()
|
|
{
|
|
node_type node = m_root;
|
|
m_root = parent::remove_node_internal (node);
|
|
if (m_root)
|
|
set_parent (m_root, node_type ());
|
|
// Clear the links from NODE. Its parent is already node_type ().
|
|
set_child (node, 0, node_type ());
|
|
set_child (node, 1, node_type ());
|
|
}
|
|
|
|
// See the comment above the declaration.
|
|
template<typename Accessors>
|
|
inline rooted_splay_tree<Accessors>
|
|
rooted_splay_tree<Accessors>::split_before_root ()
|
|
{
|
|
node_type new_root = get_child (m_root, 0);
|
|
set_child (m_root, 0, node_type ());
|
|
set_parent (new_root, node_type ());
|
|
return new_root;
|
|
}
|
|
|
|
// See the comment above the declaration.
|
|
template<typename Accessors>
|
|
inline rooted_splay_tree<Accessors>
|
|
rooted_splay_tree<Accessors>::split_after_root ()
|
|
{
|
|
node_type new_root = get_child (m_root, 1);
|
|
set_child (m_root, 1, node_type ());
|
|
set_parent (new_root, node_type ());
|
|
return new_root;
|
|
}
|
|
|
|
// See the comment above the declaration.
|
|
template<typename Accessors>
|
|
inline bool
|
|
rooted_splay_tree<Accessors>::splay_prev_node ()
|
|
{
|
|
return splay_neighbor<0> ();
|
|
}
|
|
|
|
// See the comment above the declaration.
|
|
template<typename Accessors>
|
|
inline bool
|
|
rooted_splay_tree<Accessors>::splay_next_node ()
|
|
{
|
|
return splay_neighbor<1> ();
|
|
}
|
|
|
|
// See the comment above the declaration.
|
|
template<typename Accessors>
|
|
inline void
|
|
rooted_splay_tree<Accessors>::splay_min_node ()
|
|
{
|
|
if (m_root && get_child (m_root, 0))
|
|
{
|
|
m_root = parent::template splay_limit<0> (m_root);
|
|
set_parent (m_root, node_type ());
|
|
}
|
|
}
|
|
|
|
// See the comment above the declaration.
|
|
template<typename Accessors>
|
|
inline void
|
|
rooted_splay_tree<Accessors>::splay_max_node ()
|
|
{
|
|
if (m_root && get_child (m_root, 1))
|
|
{
|
|
m_root = parent::template splay_limit<1> (m_root);
|
|
set_parent (m_root, node_type ());
|
|
}
|
|
}
|
|
|
|
// See the comment above the declaration.
|
|
template<typename Accessors>
|
|
inline typename rooted_splay_tree<Accessors>::node_type
|
|
rooted_splay_tree<Accessors>::min_node ()
|
|
{
|
|
splay_min_node ();
|
|
return m_root;
|
|
}
|
|
|
|
// See the comment above the declaration.
|
|
template<typename Accessors>
|
|
inline typename rooted_splay_tree<Accessors>::node_type
|
|
rooted_splay_tree<Accessors>::max_node ()
|
|
{
|
|
splay_max_node ();
|
|
return m_root;
|
|
}
|
|
|
|
// See the comment above the declaration.
|
|
template<typename Accessors>
|
|
template<typename Comparator>
|
|
auto
|
|
rooted_splay_tree<Accessors>::lookup (Comparator compare)
|
|
-> decltype (compare (m_root))
|
|
{
|
|
// This essentially follows the simpilfied top-down method described
|
|
// in Sleator and Tarjan's "Self-adjusting Binary Search Trees", but
|
|
// with the complication that the comparisons are done only once.
|
|
using result_type = decltype (compare (m_root));
|
|
|
|
// The roots of the left and right trees.
|
|
node_type link_left_root = node_type ();
|
|
node_type link_right_root = node_type ();
|
|
|
|
// Where to add new nodes to the left and right trees.
|
|
node_type *link_left_ptr = &link_left_root;
|
|
node_type *link_right_ptr = &link_right_root;
|
|
|
|
// The nodes that contain *LINK_LEFT_PTR and *LINK_RIGHT_PTR,
|
|
// once they no longer point to the roots above.
|
|
node_type link_left_parent = node_type ();
|
|
node_type link_right_parent = node_type ();
|
|
|
|
auto link_left = [&](node_type node)
|
|
{
|
|
*link_left_ptr = node;
|
|
link_left_ptr = &Accessors::child (node, 1);
|
|
set_parent (node, link_left_parent);
|
|
link_left_parent = node;
|
|
};
|
|
|
|
auto link_right = [&](node_type node)
|
|
{
|
|
*link_right_ptr = node;
|
|
link_right_ptr = &Accessors::child (node, 0);
|
|
set_parent (node, link_right_parent);
|
|
link_right_parent = node;
|
|
};
|
|
|
|
node_type node = m_root;
|
|
node_type parent = node_type ();
|
|
result_type result;
|
|
result_type old_result = 0;
|
|
while (1)
|
|
{
|
|
// OLD_RESULT is 0 if NODE is the root of the middle tree.
|
|
// Otherwise, PARENT is the root of the middle tree and OLD_RESULT
|
|
// is how it compared.
|
|
//
|
|
// Results are:
|
|
// < 0 if we want something smaller.
|
|
// = 0 if we found the right node.
|
|
// > 0 if we want something bigger.
|
|
result = compare (node);
|
|
if (old_result < 0)
|
|
{
|
|
if (result < 0)
|
|
{
|
|
// SEARCH < NODE < PARENT
|
|
//
|
|
// Promote NODE (rotate right).
|
|
promote_child (parent, 0, node);
|
|
node_type next = get_child (node, 0);
|
|
if (!next)
|
|
break;
|
|
|
|
link_right (node);
|
|
|
|
// NEXT is now the root of the middle tree.
|
|
node = next;
|
|
old_result = 0;
|
|
continue;
|
|
}
|
|
|
|
// SEARCH >= NODE, NODE < PARENT
|
|
link_right (parent);
|
|
}
|
|
else if (old_result > 0)
|
|
{
|
|
if (result > 0)
|
|
{
|
|
// SEARCH > NODE > PARENT
|
|
//
|
|
// Promote NODE (rotate left).
|
|
promote_child (parent, 1, node);
|
|
node_type next = get_child (node, 1);
|
|
if (!next)
|
|
break;
|
|
|
|
link_left (node);
|
|
|
|
// NEXT is now the root of the middle tree.
|
|
node = next;
|
|
old_result = 0;
|
|
continue;
|
|
}
|
|
|
|
// SEARCH <= NODE, NODE > PARENT
|
|
link_left (parent);
|
|
}
|
|
|
|
// Microoptimization to allow NODE to be read even if RESULT == 0.
|
|
node_type next = get_child (node, result >= 0);
|
|
if (result == 0 || !next)
|
|
break;
|
|
|
|
// NODE is now the root of the tree.
|
|
parent = node;
|
|
node = next;
|
|
old_result = result;
|
|
}
|
|
|
|
node_type new_left = link_left_root;
|
|
node_type new_right = link_right_root;
|
|
|
|
if (new_left)
|
|
{
|
|
node_type old_left = get_child (node, 0);
|
|
*link_left_ptr = old_left;
|
|
if (old_left)
|
|
set_parent (old_left, link_left_parent);
|
|
set_child (node, 0, new_left);
|
|
}
|
|
|
|
if (new_right)
|
|
{
|
|
node_type old_right = get_child (node, 1);
|
|
*link_right_ptr = old_right;
|
|
if (old_right)
|
|
set_parent (old_right, link_right_parent);
|
|
set_child (node, 1, new_right);
|
|
}
|
|
|
|
set_parent (node, node_type ());
|
|
m_root = node;
|
|
return result;
|
|
}
|
|
|
|
// See the comment above the declaration.
|
|
template<typename Accessors>
|
|
template<typename LeftPredicate, typename RightPredicate>
|
|
int
|
|
rooted_splay_tree<Accessors>::lookup (LeftPredicate want_something_smaller,
|
|
RightPredicate want_something_bigger)
|
|
{
|
|
// This essentially follows the simpilfied top-down method described
|
|
// in Sleator and Tarjan's "Self-adjusting Binary Search Trees"
|
|
// (and follows it more closely than the single-comparator version above).
|
|
|
|
// The roots of the left and right trees.
|
|
node_type link_left_root = node_type ();
|
|
node_type link_right_root = node_type ();
|
|
|
|
// Where to add new nodes to the left and right trees.
|
|
node_type *link_left_ptr = &link_left_root;
|
|
node_type *link_right_ptr = &link_right_root;
|
|
|
|
// The nodes that contain *LINK_LEFT_PTR and *LINK_RIGHT_PTR,
|
|
// once they no longer point to the roots above.
|
|
node_type link_left_parent = node_type ();
|
|
node_type link_right_parent = node_type ();
|
|
|
|
node_type node = m_root;
|
|
int result;
|
|
for (;;)
|
|
{
|
|
// NODE is the root of the middle tree.
|
|
if (want_something_smaller (node))
|
|
{
|
|
result = -1;
|
|
node_type next = get_child (node, 0);
|
|
if (!next)
|
|
break;
|
|
|
|
if (want_something_smaller (next))
|
|
{
|
|
// Promote NODE (rotate right).
|
|
promote_child (node, 0, next);
|
|
node = next;
|
|
next = get_child (node, 0);
|
|
if (!next)
|
|
break;
|
|
}
|
|
|
|
// Add NODE to the right tree (link right).
|
|
*link_right_ptr = node;
|
|
link_right_ptr = &Accessors::child (node, 0);
|
|
set_parent (node, link_right_parent);
|
|
link_right_parent = node;
|
|
|
|
node = next;
|
|
}
|
|
else if (want_something_bigger (node))
|
|
{
|
|
result = 1;
|
|
node_type next = get_child (node, 1);
|
|
if (!next)
|
|
break;
|
|
|
|
if (want_something_bigger (next))
|
|
{
|
|
// Promote NODE (rotate left).
|
|
promote_child (node, 1, next);
|
|
node = next;
|
|
next = get_child (node, 1);
|
|
if (!next)
|
|
break;
|
|
}
|
|
|
|
// Add NODE to the left tree (link left).
|
|
*link_left_ptr = node;
|
|
link_left_ptr = &Accessors::child (node, 1);
|
|
set_parent (node, link_left_parent);
|
|
link_left_parent = node;
|
|
|
|
node = next;
|
|
}
|
|
else
|
|
{
|
|
result = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
node_type new_left = link_left_root;
|
|
node_type new_right = link_right_root;
|
|
|
|
if (new_left)
|
|
{
|
|
node_type old_left = get_child (node, 0);
|
|
*link_left_ptr = old_left;
|
|
if (old_left)
|
|
set_parent (old_left, link_left_parent);
|
|
set_child (node, 0, new_left);
|
|
}
|
|
|
|
if (new_right)
|
|
{
|
|
node_type old_right = get_child (node, 1);
|
|
*link_right_ptr = old_right;
|
|
if (old_right)
|
|
set_parent (old_right, link_right_parent);
|
|
set_child (node, 1, new_right);
|
|
}
|
|
|
|
set_parent (node, node_type ());
|
|
m_root = node;
|
|
return result;
|
|
}
|
|
|
|
// See the comment above the declaration.
|
|
template<typename Accessors>
|
|
template<typename Printer>
|
|
inline void
|
|
rooted_splay_tree<Accessors>::print (pretty_printer *pp, Printer printer) const
|
|
{
|
|
print (pp, m_root, printer);
|
|
}
|
|
|
|
// Return NODE's current parent.
|
|
template<typename Accessors>
|
|
inline typename rootless_splay_tree<Accessors>::node_type
|
|
rootless_splay_tree<Accessors>::get_parent (node_type node)
|
|
{
|
|
return Accessors::parent (node);
|
|
}
|
|
|
|
// CHILD is known to be a child of PARENT. Return which index it has.
|
|
template<typename Accessors>
|
|
inline unsigned int
|
|
rootless_splay_tree<Accessors>::child_index (node_type parent, node_type child)
|
|
{
|
|
return get_child (parent, 1) == child;
|
|
}
|
|
|
|
// If N == 1, implement splay_known_max_node, otherwise implement
|
|
// splay_known_min_node.
|
|
template<typename Accessors>
|
|
template<unsigned int N>
|
|
inline void
|
|
rootless_splay_tree<Accessors>::splay_known_limit (node_type node)
|
|
{
|
|
node_type child = node;
|
|
node_type parent = get_parent (child);
|
|
if (!parent)
|
|
return;
|
|
|
|
do
|
|
// At this point, NODE conceptually replaces CHILD as a child of
|
|
// PARENT, but we haven't yet updated PARENT accordingly.
|
|
if (node_type grandparent = get_parent (parent))
|
|
{
|
|
node_type greatgrandparent = get_parent (grandparent);
|
|
promote_child (grandparent, N, parent);
|
|
promote_child (parent, N, node);
|
|
child = grandparent;
|
|
parent = greatgrandparent;
|
|
}
|
|
else
|
|
{
|
|
promote_child (parent, N, node);
|
|
break;
|
|
}
|
|
while (parent);
|
|
set_parent (node, node_type ());
|
|
}
|
|
|
|
// See the comment above the declaration.
|
|
template<typename Accessors>
|
|
typename rootless_splay_tree<Accessors>::node_type
|
|
rootless_splay_tree<Accessors>::remove_node (node_type node)
|
|
{
|
|
node_type replacement = parent::remove_node_internal (node);
|
|
if (node_type parent = get_parent (node))
|
|
set_child (parent, child_index (parent, node), replacement);
|
|
else if (replacement)
|
|
set_parent (replacement, node_type ());
|
|
// Clear the links from NODE.
|
|
set_parent (node, node_type ());
|
|
set_child (node, 0, node_type ());
|
|
set_child (node, 1, node_type ());
|
|
return replacement;
|
|
}
|
|
|
|
// See the comment above the declaration.
|
|
template<typename Accessors>
|
|
void
|
|
rootless_splay_tree<Accessors>::splay (node_type node)
|
|
{
|
|
node_type child = node;
|
|
node_type parent = get_parent (child);
|
|
if (!parent)
|
|
return;
|
|
|
|
do
|
|
{
|
|
// At this point, NODE conceptually replaces CHILD as a child of
|
|
// PARENT, but we haven't yet updated PARENT accordingly.
|
|
unsigned int index = child_index (parent, child);
|
|
if (node_type grandparent = get_parent (parent))
|
|
{
|
|
node_type greatgrandparent = get_parent (grandparent);
|
|
unsigned int parent_index = child_index (grandparent, parent);
|
|
if (index == parent_index)
|
|
{
|
|
promote_child (grandparent, parent_index, parent);
|
|
promote_child (parent, index, node);
|
|
}
|
|
else
|
|
{
|
|
promote_child (parent, index, node);
|
|
promote_child (grandparent, parent_index, node);
|
|
}
|
|
child = grandparent;
|
|
parent = greatgrandparent;
|
|
}
|
|
else
|
|
{
|
|
promote_child (parent, index, node);
|
|
break;
|
|
}
|
|
}
|
|
while (parent);
|
|
set_parent (node, node_type ());
|
|
}
|
|
|
|
// See the comment above the declaration.
|
|
template<typename Accessors>
|
|
inline void
|
|
rootless_splay_tree<Accessors>::splay_known_min_node (node_type node)
|
|
{
|
|
splay_known_limit<0> (node);
|
|
}
|
|
|
|
// See the comment above the declaration.
|
|
template<typename Accessors>
|
|
inline void
|
|
rootless_splay_tree<Accessors>::splay_known_max_node (node_type node)
|
|
{
|
|
splay_known_limit<1> (node);
|
|
}
|
|
|
|
// See the comment above the declaration.
|
|
template<typename Accessors>
|
|
template<typename DefaultResult, typename Predicate>
|
|
auto
|
|
rootless_splay_tree<Accessors>::
|
|
splay_and_search (node_type node, DefaultResult default_result,
|
|
Predicate predicate)
|
|
-> decltype (predicate (node, 0))
|
|
{
|
|
using Result = decltype (predicate (node, 0));
|
|
|
|
node_type child = node;
|
|
node_type parent = get_parent (child);
|
|
if (!parent)
|
|
return default_result;
|
|
|
|
do
|
|
{
|
|
// At this point, NODE conceptually replaces CHILD as a child of
|
|
// PARENT, but we haven't yet updated PARENT accordingly.
|
|
unsigned int index = child_index (parent, child);
|
|
if (Result result = predicate (parent, index))
|
|
{
|
|
set_child (parent, index, node);
|
|
return result;
|
|
}
|
|
if (node_type grandparent = get_parent (parent))
|
|
{
|
|
node_type greatgrandparent = get_parent (grandparent);
|
|
unsigned int parent_index = child_index (grandparent, parent);
|
|
if (Result result = predicate (grandparent, parent_index))
|
|
{
|
|
set_child (parent, index, node);
|
|
return result;
|
|
}
|
|
if (index == parent_index)
|
|
{
|
|
promote_child (grandparent, parent_index, parent);
|
|
promote_child (parent, index, node);
|
|
}
|
|
else
|
|
{
|
|
promote_child (parent, index, node);
|
|
promote_child (grandparent, parent_index, node);
|
|
}
|
|
child = grandparent;
|
|
parent = greatgrandparent;
|
|
}
|
|
else
|
|
{
|
|
promote_child (parent, index, node);
|
|
break;
|
|
}
|
|
}
|
|
while (parent);
|
|
set_parent (node, node_type ());
|
|
return default_result;
|
|
}
|
|
|
|
// Splay NODE1 looking to see if one of its ancestors is NODE2. If it is,
|
|
// return -1 if NODE1 comes before NODE2 or 1 if NODE1 comes after NODE2.
|
|
// Return 0 if NODE2 is not an ancestor of NODE1.
|
|
template<typename Accessors>
|
|
int
|
|
rootless_splay_tree<Accessors>::compare_nodes_one_way (node_type node1,
|
|
node_type node2)
|
|
{
|
|
auto compare = [&](node_type parent, unsigned int index) -> int
|
|
{
|
|
if (parent == node2)
|
|
return index ? 1 : -1;
|
|
return 0;
|
|
};
|
|
return splay_and_search (node1, 0, compare);
|
|
}
|
|
|
|
// See the comment above the declaration.
|
|
template<typename Accessors>
|
|
int
|
|
rootless_splay_tree<Accessors>::compare_nodes (node_type node1,
|
|
node_type node2)
|
|
{
|
|
if (node1 == node2)
|
|
return 0;
|
|
|
|
// Splay NODE1 looking for NODE2.
|
|
int cmp = compare_nodes_one_way (node1, node2);
|
|
if (cmp)
|
|
return cmp;
|
|
|
|
// That failed, but NODE1 is now the root of the tree. Splay NODE2
|
|
// to see on which side of NODE1 it falls.
|
|
cmp = compare_nodes_one_way (node2, node1);
|
|
gcc_checking_assert (cmp);
|
|
return -cmp;
|
|
}
|