Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8223851
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 7, 20262026-06-07T14:51:25+00:00 2026-06-07T14:51:25+00:00

It’s not easy to find red-black tree implementations on the net, especially for learning.

  • 0

It’s not easy to find red-black tree implementations on the net, especially for learning.

Where can I find a simple red-black tree implementation (C# preferred)?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-07T14:51:27+00:00Added an answer on June 7, 2026 at 2:51 pm

    Generic red-black trees aren’t “simple” by default.
    But if you put a small restriction on them and make them “left-leaning”, then they become simpler.
    Take a look at this MSDN blog post.

    I’ve copy-pasted (with slight modifications) the code from that post here (in C#):

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    
    /// <summary>Implements a left-leaning red-black tree.</summary>
    /// <remarks>
    /// Based on the research paper "Left-leaning Red-Black Trees"
    /// by Robert Sedgewick. More information available at:
    /// http://www.cs.princeton.edu/~rs/talks/LLRB/RedBlack.pdf
    /// http://www.cs.princeton.edu/~rs/talks/LLRB/08Penn.pdf
    /// </remarks>
    /// <typeparam name="TKey">Type of keys.</typeparam>
    /// <typeparam name="TValue">Type of values.</typeparam>
    public class LeftLeaningRedBlackTree<TKey, TValue>
    {
        /// <summary>Stores the key comparison function.</summary>
        private Comparison<TKey> _keyComparison;
    
        /// <summary>Stores the value comparison function.</summary>
        private Comparison<TValue> _valueComparison;
    
        /// <summary>Stores the root node of the tree.</summary>
        private Node _rootNode;
    
        /// <summary>Represents a node of the tree.</summary>
        /// <remarks>Using fields instead of properties drops execution time by about 40%.</remarks>
        [DebuggerDisplay("Key={Key}, Value={Value}, Siblings={Siblings}")]
        private class Node
        {
            /// <summary>Gets or sets the node's key.</summary>
            public TKey Key;
    
            /// <summary>Gets or sets the node's value.</summary>
            public TValue Value;
    
            /// <summary>Gets or sets the left node.</summary>
            public Node Left;
    
            /// <summary>Gets or sets the right node.</summary>
            public Node Right;
    
            /// <summary>Gets or sets the color of the node.</summary>
            public bool IsBlack;
    
            /// <summary>Gets or sets the number of "siblings" (nodes with the same key/value).</summary>
            public int Siblings;
        }
    
        /// <summary>Initializes a new instance of the LeftLeaningRedBlackTree class implementing a normal dictionary.</summary>
        /// <param name="keyComparison">The key comparison function.</param>
        public LeftLeaningRedBlackTree(Comparison<TKey> keyComparison)
        {
            if (null == keyComparison)
            {
                throw new ArgumentNullException("keyComparison");
            }
            _keyComparison = keyComparison;
        }
    
        /// <summary>Initializes a new instance of the LeftLeaningRedBlackTree class implementing an ordered multi-dictionary.</summary>
        /// <param name="keyComparison">The key comparison function.</param>
        /// <param name="valueComparison">The value comparison function.</param>
        public LeftLeaningRedBlackTree(Comparison<TKey> keyComparison, Comparison<TValue> valueComparison)
            : this(keyComparison)
        {
            if (null == valueComparison)
            {
                throw new ArgumentNullException("valueComparison");
            }
            _valueComparison = valueComparison;
        }
    
        /// <summary>Gets a value indicating whether the tree is acting as an ordered multi-dictionary.</summary>
        private bool IsMultiDictionary
        {
            get { return null != _valueComparison; }
        }
    
        /// <summary>Adds a key/value pair to the tree.</summary>
        /// <param name="key">Key to add.</param>
        /// <param name="value">Value to add.</param>
        public void Add(TKey key, TValue value)
        {
            _rootNode = Add(_rootNode, key, value);
            _rootNode.IsBlack = true;
            AssertInvariants();
        }
    
        /// <summary>Removes a key (and its associated value) from a normal (non-multi) dictionary.</summary>
        /// <param name="key">Key to remove.</param>
        /// <returns>True if key present and removed.</returns>
        public bool Remove(TKey key)
        {
            if (IsMultiDictionary)
            {
                throw new InvalidOperationException("Remove is only supported when acting as a normal (non-multi) dictionary.");
            }
            return Remove(key, default(TValue));
        }
    
        /// <summary>Removes a key/value pair from the tree.</summary>
        /// <param name="key">Key to remove.</param>
        /// <param name="value">Value to remove.</param>
        /// <returns>True if key/value present and removed.</returns>
        public bool Remove(TKey key, TValue value)
        {
            int initialCount = Count;
            if (null != _rootNode)
            {
                _rootNode = Remove(_rootNode, key, value);
                if (null != _rootNode)
                {
                    _rootNode.IsBlack = true;
                }
            }
            AssertInvariants();
            return initialCount != Count;
        }
    
        /// <summary>Removes all nodes in the tree.</summary>
        public void Clear()
        {
            _rootNode = null;
            Count = 0;
            AssertInvariants();
        }
    
        /// <summary>Gets a sorted list of keys in the tree.</summary>
        /// <returns>Sorted list of keys.</returns>
        public IEnumerable<TKey> GetKeys()
        {
            TKey lastKey = default(TKey);
            bool lastKeyValid = false;
            return Traverse(
                _rootNode,
                n => !lastKeyValid || !object.Equals(lastKey, n.Key),
                n =>
                {
                    lastKey = n.Key;
                    lastKeyValid = true;
                    return lastKey;
                });
        }
    
        /// <summary>Gets the value associated with the specified key in a normal (non-multi) dictionary.</summary>
        /// <param name="key">Specified key.</param>
        /// <returns>Value associated with the specified key.</returns>
        public TValue GetValueForKey(TKey key)
        {
            if (IsMultiDictionary)
            {
                throw new InvalidOperationException("GetValueForKey is only supported when acting as a normal (non-multi) dictionary.");
            }
            Node node = GetNodeForKey(key);
            if (null != node)
            {
                return node.Value;
            }
            else
            {
                throw new KeyNotFoundException();
            }
        }
    
        /// <summary>Gets a sequence of the values associated with the specified key.</summary>
        /// <param name="key">Specified key.</param>
        /// <returns>Sequence of values.</returns>
        public IEnumerable<TValue> GetValuesForKey(TKey key)
        {
            return Traverse(GetNodeForKey(key), n => 0 == _keyComparison(n.Key, key), n => n.Value);
        }
    
        /// <summary>Gets a sequence of all the values in the tree.</summary>
        /// <returns>Sequence of all values.</returns>
        public IEnumerable<TValue> GetValuesForAllKeys()
        {
            return Traverse(_rootNode, n => true, n => n.Value);
        }
    
        /// <summary>Gets the count of key/value pairs in the tree.</summary>
        public int Count { get; private set; }
    
        /// <summary>Gets the minimum key in the tree.</summary>
        public TKey MinimumKey
        {
            get { return GetExtreme(_rootNode, n => n.Left, n => n.Key); }
        }
    
        /// <summary>Gets the maximum key in the tree.</summary>
        public TKey MaximumKey
        {
            get { return GetExtreme(_rootNode, n => n.Right, n => n.Key); }
        }
    
        /// <summary>Returns true if the specified node is red.</summary>
        /// <param name="node">Specified node.</param>
        /// <returns>True if specified node is red.</returns>
        private static bool IsRed(Node node)
        {
            if (null == node)
            {
                // "Virtual" leaf nodes are always black
                return false;
            }
            return !node.IsBlack;
        }
    
        /// <summary>Adds the specified key/value pair below the specified root node.</summary>
        /// <param name="node">Specified node.</param>
        /// <param name="key">Key to add.</param>
        /// <param name="value">Value to add.</param>
        /// <returns>New root node.</returns>
        private Node Add(Node node, TKey key, TValue value)
        {
            if (null == node)
            {
                // Insert new node
                Count++;
                return new Node { Key = key, Value = value };
            }
    
            if (IsRed(node.Left) && IsRed(node.Right))
            {
                // Split node with two red children
                FlipColor(node);
            }
    
            // Find right place for new node
            int comparisonResult = KeyAndValueComparison(key, value, node.Key, node.Value);
            if (comparisonResult < 0)
            {
                node.Left = Add(node.Left, key, value);
            }
            else if (0 < comparisonResult)
            {
                node.Right = Add(node.Right, key, value);
            }
            else
            {
                if (IsMultiDictionary)
                {
                    // Store the presence of a "duplicate" node
                    node.Siblings++;
                    Count++;
                }
                else
                {
                    // Replace the value of the existing node
                    node.Value = value;
                }
            }
    
            if (IsRed(node.Right))
            {
                // Rotate to prevent red node on right
                node = RotateLeft(node);
            }
    
            if (IsRed(node.Left) && IsRed(node.Left.Left))
            {
                // Rotate to prevent consecutive red nodes
                node = RotateRight(node);
            }
    
            return node;
        }
    
        /// <summary>Removes the specified key/value pair from below the specified node.</summary>
        /// <param name="node">Specified node.</param>
        /// <param name="key">Key to remove.</param>
        /// <param name="value">Value to remove.</param>
        /// <returns>True if key/value present and removed.</returns>
        private Node Remove(Node node, TKey key, TValue value)
        {
            int comparisonResult = KeyAndValueComparison(key, value, node.Key, node.Value);
            if (comparisonResult < 0)
            {
                // * Continue search if left is present
                if (null != node.Left)
                {
                    if (!IsRed(node.Left) && !IsRed(node.Left.Left))
                    {
                        // Move a red node over
                        node = MoveRedLeft(node);
                    }
    
                    // Remove from left
                    node.Left = Remove(node.Left, key, value);
                }
            }
            else
            {
                if (IsRed(node.Left))
                {
                    // Flip a 3 node or unbalance a 4 node
                    node = RotateRight(node);
                }
                if ((0 == KeyAndValueComparison(key, value, node.Key, node.Value)) && (null == node.Right))
                {
                    // Remove leaf node
                    Debug.Assert(null == node.Left, "About to remove an extra node.");
                    Count--;
                    if (0 < node.Siblings)
                    {
                        // Record the removal of the "duplicate" node
                        Debug.Assert(IsMultiDictionary, "Should not have siblings if tree is not a multi-dictionary.");
                        node.Siblings--;
                        return node;
                    }
                    else
                    {
                        // Leaf node is gone
                        return null;
                    }
                }
                // * Continue search if right is present
                if (null != node.Right)
                {
                    if (!IsRed(node.Right) && !IsRed(node.Right.Left))
                    {
                        // Move a red node over
                        node = MoveRedRight(node);
                    }
                    if (0 == KeyAndValueComparison(key, value, node.Key, node.Value))
                    {
                        // Remove leaf node
                        Count--;
                        if (0 < node.Siblings)
                        {
                            // Record the removal of the "duplicate" node
                            Debug.Assert(IsMultiDictionary, "Should not have siblings if tree is not a multi-dictionary.");
                            node.Siblings--;
                        }
                        else
                        {
                            // Find the smallest node on the right, swap, and remove it
                            Node m = GetExtreme(node.Right, n => n.Left, n => n);
                            node.Key = m.Key;
                            node.Value = m.Value;
                            node.Siblings = m.Siblings;
                            node.Right = DeleteMinimum(node.Right);
                        }
                    }
                    else
                    {
                        // Remove from right
                        node.Right = Remove(node.Right, key, value);
                    }
                }
            }
    
            // Maintain invariants
            return FixUp(node);
        }
    
        /// <summary>Flip the colors of the specified node and its direct children.</summary>
        /// <param name="node">Specified node.</param>
        private static void FlipColor(Node node)
        {
            node.IsBlack = !node.IsBlack;
            node.Left.IsBlack = !node.Left.IsBlack;
            node.Right.IsBlack = !node.Right.IsBlack;
        }
    
        /// <summary>Rotate the specified node "left".</summary>
        /// <param name="node">Specified node.</param>
        /// <returns>New root node.</returns>
        private static Node RotateLeft(Node node)
        {
            Node x = node.Right;
            node.Right = x.Left;
            x.Left = node;
            x.IsBlack = node.IsBlack;
            node.IsBlack = false;
            return x;
        }
    
        /// <summary>Rotate the specified node "right".</summary>
        /// <param name="node">Specified node.</param>
        /// <returns>New root node.</returns>
        private static Node RotateRight(Node node)
        {
            Node x = node.Left;
            node.Left = x.Right;
            x.Right = node;
            x.IsBlack = node.IsBlack;
            node.IsBlack = false;
            return x;
        }
    
        /// <summary>Moves a red node from the right child to the left child.</summary>
        /// <param name="node">Parent node.</param>
        /// <returns>New root node.</returns>
        private static Node MoveRedLeft(Node node)
        {
            FlipColor(node);
            if (IsRed(node.Right.Left))
            {
                node.Right = RotateRight(node.Right);
                node = RotateLeft(node);
                FlipColor(node);
    
                // * Avoid creating right-leaning nodes
                if (IsRed(node.Right.Right))
                {
                    node.Right = RotateLeft(node.Right);
                }
            }
            return node;
        }
    
        /// <summary>Moves a red node from the left child to the right child.</summary>
        /// <param name="node">Parent node.</param>
        /// <returns>New root node.</returns>
        private static Node MoveRedRight(Node node)
        {
            FlipColor(node);
            if (IsRed(node.Left.Left))
            {
                node = RotateRight(node);
                FlipColor(node);
            }
            return node;
        }
    
        /// <summary>Deletes the minimum node under the specified node.</summary>
        /// <param name="node">Specified node.</param>
        /// <returns>New root node.</returns>
        private Node DeleteMinimum(Node node)
        {
            if (null == node.Left)
            {
                // Nothing to do
                return null;
            }
    
            if (!IsRed(node.Left) && !IsRed(node.Left.Left))
            {
                // Move red node left
                node = MoveRedLeft(node);
            }
    
            // Recursively delete
            node.Left = DeleteMinimum(node.Left);
    
            // Maintain invariants
            return FixUp(node);
        }
    
        /// <summary>Maintains invariants by adjusting the specified nodes children.</summary>
        /// <param name="node">Specified node.</param>
        /// <returns>New root node.</returns>
        private static Node FixUp(Node node)
        {
            if (IsRed(node.Right))
            {
                // Avoid right-leaning node
                node = RotateLeft(node);
            }
    
            if (IsRed(node.Left) && IsRed(node.Left.Left))
            {
                // Balance 4-node
                node = RotateRight(node);
            }
    
            if (IsRed(node.Left) && IsRed(node.Right))
            {
                // Push red up
                FlipColor(node);
            }
    
            // * Avoid leaving behind right-leaning nodes
            if ((null != node.Left) && IsRed(node.Left.Right) && !IsRed(node.Left.Left))
            {
                node.Left = RotateLeft(node.Left);
                if (IsRed(node.Left))
                {
                    // Balance 4-node
                    node = RotateRight(node);
                }
            }
    
            return node;
        }
    
        /// <summary>Gets the (first) node corresponding to the specified key.</summary>
        /// <param name="key">Key to search for.</param>
        /// <returns>Corresponding node or null if none found.</returns>
        private Node GetNodeForKey(TKey key)
        {
            // Initialize
            Node node = _rootNode;
            while (null != node)
            {
                // Compare keys and go left/right
                int comparisonResult = _keyComparison(key, node.Key);
                if (comparisonResult < 0)
                {
                    node = node.Left;
                }
                else if (0 < comparisonResult)
                {
                    node = node.Right;
                }
                else
                {
                    // Match; return node
                    return node;
                }
            }
    
            // No match found
            return null;
        }
    
        /// <summary>Gets an extreme (ex: minimum/maximum) value.</summary>
        /// <typeparam name="T">Type of value.</typeparam>
        /// <param name="node">Node to start from.</param>
        /// <param name="successor">Successor function.</param>
        /// <param name="selector">Selector function.</param>
        /// <returns>Extreme value.</returns>
        private static T GetExtreme<T>(Node node, Func<Node, Node> successor, Func<Node, T> selector)
        {
            // Initialize
            T extreme = default(T);
            Node current = node;
            while (null != current)
            {
                // Go to extreme
                extreme = selector(current);
                current = successor(current);
            }
            return extreme;
        }
    
        /// <summary>Traverses a subset of the sequence of nodes in order and selects the specified nodes.</summary>
        /// <typeparam name="T">Type of elements.</typeparam>
        /// <param name="node">Starting node.</param>
        /// <param name="condition">Condition method.</param>
        /// <param name="selector">Selector method.</param>
        /// <returns>Sequence of selected nodes.</returns>
        private IEnumerable<T> Traverse<T>(Node node, Func<Node, bool> condition, Func<Node, T> selector)
        {
            // Create a stack to avoid recursion
            Stack<Node> stack = new Stack<Node>();
            Node current = node;
            while (null != current)
            {
                if (null != current.Left)
                {
                    // Save current state and go left
                    stack.Push(current);
                    current = current.Left;
                }
                else
                {
                    do
                    {
                        for (int i = 0; i <= current.Siblings; i++)
                        {
                            // Select current node if relevant
                            if (condition(current))
                            {
                                yield return selector(current);
                            }
                        }
                        // Go right - or up if nothing to the right
                        current = current.Right;
                    }
                    while ((null == current) &&
                           (0 < stack.Count) &&
                           (null != (current = stack.Pop())));
                }
            }
        }
    
        /// <summary>Compares the specified keys (primary) and values (secondary).</summary>
        /// <param name="leftKey">The left key.</param>
        /// <param name="leftValue">The left value.</param>
        /// <param name="rightKey">The right key.</param>
        /// <param name="rightValue">The right value.</param>
        /// <returns>CompareTo-style results: -1 if left is less, 0 if equal, and 1 if greater than right.</returns>
        private int KeyAndValueComparison(TKey leftKey, TValue leftValue, TKey rightKey, TValue rightValue)
        {
            // Compare keys
            int comparisonResult = _keyComparison(leftKey, rightKey);
            if ((0 == comparisonResult) && (null != _valueComparison))
            {
                // Keys match; compare values
                comparisonResult = _valueComparison(leftValue, rightValue);
            }
            return comparisonResult;
        }
    
        /// <summary>Asserts that tree invariants are not violated.</summary>
        [Conditional("Debug")]
        private void AssertInvariants()
        {
            // Root is black
            Debug.Assert((null == _rootNode) || _rootNode.IsBlack, "Root is not black");
            // Every path contains the same number of black nodes
            Dictionary<Node, Node> parents = new Dictionary<LeftLeaningRedBlackTree<TKey, TValue>.Node, LeftLeaningRedBlackTree<TKey, TValue>.Node>();
            foreach (Node node in Traverse(_rootNode, n => true, n => n))
            {
                if (null != node.Left)
                {
                    parents[node.Left] = node;
                }
                if (null != node.Right)
                {
                    parents[node.Right] = node;
                }
            }
            if (null != _rootNode)
            {
                parents[_rootNode] = null;
            }
            int treeCount = -1;
            foreach (Node node in Traverse(_rootNode, n => (null == n.Left) || (null == n.Right), n => n))
            {
                int pathCount = 0;
                Node current = node;
                while (null != current)
                {
                    if (current.IsBlack)
                    {
                        pathCount++;
                    }
                    current = parents[current];
                }
                Debug.Assert((-1 == treeCount) || (pathCount == treeCount), "Not all paths have the same number of black nodes.");
                treeCount = pathCount;
            }
            // Verify node properties...
            foreach (Node node in Traverse(_rootNode, n => true, n => n))
            {
                // Left node is less
                if (null != node.Left)
                {
                    Debug.Assert(0 > KeyAndValueComparison(node.Left.Key, node.Left.Value, node.Key, node.Value), "Left node is greater than its parent.");
                }
                // Right node is greater
                if (null != node.Right)
                {
                    Debug.Assert(0 < KeyAndValueComparison(node.Right.Key, node.Right.Value, node.Key, node.Value), "Right node is less than its parent.");
                }
                // Both children of a red node are black
                Debug.Assert(!IsRed(node) || (!IsRed(node.Left) && !IsRed(node.Right)), "Red node has a red child.");
                // Always left-leaning
                Debug.Assert(!IsRed(node.Right) || IsRed(node.Left), "Node is not left-leaning.");
                // No consecutive reds (subset of previous rule)
                //Debug.Assert(!(IsRed(node) && IsRed(node.Left)));
            }
        }
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Seemingly simple, but I cannot find anything relevant on the web. What is the
I have just tried to save a simple *.rtf file with some websites and
link Im having trouble converting the html entites into html characters, (&# 8217;) i
I have a jquery bug and I've been looking for hours now, I can't
I have a string like this: La Torre Eiffel paragonata all&#8217;Everest What PHP function
I am doing a simple coin flipping experiment for class that involves flipping a
I'm parsing an RSS feed that has an &#8217; in it. SimpleXML turns this
I need a function that will clean a strings' special characters. I do NOT
Does anyone know how can I replace this 2 symbol below from the string
Is it possible to replace javascript w/ HTML if JavaScript is not enabled on

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.