Пример #1
0
        //┴ ┐ ─ ┌ ┘ └
        static void Main(string[] args)
        {
            Random rnd = new Random();

            var tree = new LeftLeaningRedBlackTree <int>();

            Node <int>[] items;
            int[]        array = { 10, 20, 30, 40, 50, 25 };
            for (int i = 0; i < array.Length /*50*/; i++)
            {
                //tree.Add(rnd.Next(1, 10));
                tree.Add(array[i]);
                items = tree.PreOrderNode().ToArray();
                Console.Clear();
                Display(items);

                Thread.Sleep(250);
            }

            tree.Remove(50);
            items = tree.PreOrderNode().ToArray();
            Console.Clear();
            Display(items);

            Console.ReadKey();
        }
Пример #2
0
        public void TestTreeMap()
        {
            var map = new LeftLeaningRedBlackTree <int, int>();

            map[1] = 1;
            Assert.Equal(1, map[1]);
            map[2] = 2;
            Assert.Equal(2, map[2]);
            Assert.Equal(2, map.Count);

            map.Delete(2);
            Assert.Equal(1, map.Count);
            Assert.True(map.ContainsKey(1));
            Assert.False(map.ContainsKey(2));

            for (var i = 3; i < 100; ++i)
            {
                map[i] = i;
            }

            Assert.True(map.ContainsKey(1));
            for (var i = 3; i < 100; ++i)
            {
                Assert.True(map.ContainsKey(i));
            }

            Assert.Equal(98, map.Count);
        }
Пример #3
0
        /// <summary>
        /// Generates an int tree of specified size containting [0-size] in random order. (no duplicates)
        /// </summary>
        /// <param name="size">The specified size.</param>
        /// <returns>A ValueTuple containing the tree and an array of integers in the tree.</returns>
        private (LeftLeaningRedBlackTree <int> Tree, int[] Pool) RandomTree(int size)
        {
            Random random = new Random(new Guid().GetHashCode());
            LeftLeaningRedBlackTree <int> tree = new LeftLeaningRedBlackTree <int>();

            //pool setup
            List <int> pool = new List <int>();

            for (int i = 0; i < size; i++)
            {
                pool.Add(i);
            }
            int[] returnPool = pool.ToArray();

            //tree building
            while (pool.Count != 0)
            {
                int index = random.Next(0, pool.Count);
                tree.Add(pool[index]);
                AssertInvariants(tree);
                pool.RemoveAt(index);
            }

            return(tree, returnPool);
        }
Пример #4
0
        /// <summary>
        /// Asserts that tree invariants are not violated.
        /// </summary>
        /// <param name="tree">The tree in question.</param>
        private void AssertInvariants(LeftLeaningRedBlackTree <int> tree)
        {
            // Root is black
            Assert.IsTrue((null == tree._rootNode) || tree._rootNode.IsBlack, "Root is not black");
            // Every path contains the same number of black nodes
            Dictionary <Node, Node> parents = new Dictionary <Node, Node>();

            foreach (Node node in tree.Traverse(tree._rootNode, n => true, n => n))
            {
                if (null != node.Left)
                {
                    parents[node.Left] = node;
                }
                if (null != node.Right)
                {
                    parents[node.Right] = node;
                }
            }
            if (null != tree._rootNode)
            {
                parents[tree._rootNode] = null;
            }
            int treeCount = -1;

            foreach (Node node in tree.Traverse(tree._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];
                }
                Assert.IsTrue((-1 == treeCount) || (pathCount == treeCount), "Not all paths have the same number of black nodes.");
                treeCount = pathCount;
            }
            // Verify node properties...
            foreach (Node node in tree.Traverse(tree._rootNode, n => true, n => n))
            {
                // Left node is less
                if (null != node.Left)
                {
                    Assert.IsTrue(0 < node.Value.CompareTo(node.Left.Value), "Left node is greater than its parent.");
                }
                // Right node is greater
                if (null != node.Right)
                {
                    Assert.IsTrue(0 > node.Value.CompareTo(node.Right.Value), "Right node is less than its parent.");
                }
                // Both children of a red node are black
                Assert.IsTrue(!tree.IsRed(node) || (!tree.IsRed(node.Left) && !tree.IsRed(node.Right)), "Red node has a red child.");
                // Always left-leaning
                Assert.IsTrue(!tree.IsRed(node.Right) || tree.IsRed(node.Left), "Node is not left-leaning.");
            }
        }
Пример #5
0
        public void InsertionTest()
        {
            //Tree Setup
            Random random = new Random(new Guid().GetHashCode());
            int    count  = random.Next(1, 1000);
            LeftLeaningRedBlackTree <int> tree = RandomTree(count).Tree;

            //Counts are equal
            Assert.AreEqual(count, tree.Count, "Counts are not equal");
        }
Пример #6
0
        static LeftLeaningRedBlackTree <char, char> GetLeftLeaningRedBlackTree()
        {
            var tree  = new LeftLeaningRedBlackTree <char, char>();
            var elems = "MJRELPXCHSA";

            foreach (var c in elems)
            {
                tree.Put(c, c);
            }
            return(tree);
        }
Пример #7
0
        /// <summary>
        /// Checks all properties of the specified tree for correctness.
        /// </summary>
        /// <typeparam name="TKey">Type of keys.</typeparam>
        /// <typeparam name="TValue">Type of values.</typeparam>
        /// <param name="tree">Specified tree.</param>
        /// <param name="elements">Expected elements in the tree.</param>
        /// <param name="isMulti">True if testing the multi-dictionary scenario.</param>
        private static void CheckTree <TKey, TValue>(LeftLeaningRedBlackTree <TKey, TValue> tree, List <KeyValuePair <TKey, TValue> > elements, bool isMulti) where TKey : IComparable
        {
            // Check count and keys
            Assert.AreEqual(elements.Count, tree.Count);
            List <TKey> sortedKeys     = elements.Select(e => e.Key).Distinct().OrderBy(k => k).ToList();
            List <TKey> binaryTreeKeys = tree.GetKeys().ToList();

            Assert.AreEqual(sortedKeys.Count, binaryTreeKeys.Count);

            // Check key values
            for (int i = 0; i < sortedKeys.Count; i++)
            {
                Assert.AreEqual(sortedKeys[i], binaryTreeKeys[i]);
                List <TValue> sortedKeyValues     = elements.Where(e => 0 == e.Key.CompareTo(sortedKeys[i])).Select(e => e.Value).OrderBy(v => v).ToList();
                List <TValue> binaryTreeKeyValues = tree.GetValuesForKey(sortedKeys[i]).ToList();
                Assert.AreEqual(sortedKeyValues.Count, binaryTreeKeyValues.Count);
                for (int j = 0; j < sortedKeyValues.Count; j++)
                {
                    Assert.AreEqual(sortedKeyValues[j], binaryTreeKeyValues[j]);
                }
                if (!isMulti)
                {
                    Assert.AreEqual(tree.GetValueForKey(sortedKeys[i]), binaryTreeKeyValues.Single());
                }
            }

            // Check values
            List <TValue> sortedValues     = sortedKeys.SelectMany(k => elements.Where(e => 0 == e.Key.CompareTo(k)).Select(e => e.Value).OrderBy(v => v)).ToList();
            List <TValue> binaryTreeValues = tree.GetValuesForAllKeys().ToList();

            Assert.AreEqual(sortedValues.Count, binaryTreeValues.Count);
            for (int i = 0; i < sortedValues.Count; i++)
            {
                Assert.AreEqual(sortedValues[i], binaryTreeValues[i]);
            }

            // Check additional properties
            if (0 < elements.Count)
            {
                Assert.AreEqual(sortedKeys[0], tree.MinimumKey);
                Assert.AreEqual(sortedKeys[sortedKeys.Count - 1], tree.MaximumKey);
                Assert.AreEqual(sortedValues[0], tree.MinimumValue);
                Assert.AreEqual(sortedValues[sortedValues.Count - 1], tree.MaximumValue);
            }
        }
Пример #8
0
        public void DeletionTest()
        {
            // Setup tree and pool
            Random random = new Random(new Guid().GetHashCode());
            int    count  = random.Next(1, 1000);
            var    tuple  = RandomTree(count);
            LeftLeaningRedBlackTree <int> tree = tuple.Tree;
            List <int> pool = new List <int>(tuple.Pool);

            // Remove from tree
            while (pool.Count != 0)
            {
                int index = random.Next(0, pool.Count);
                tree.Remove(pool[index]);
                AssertInvariants(tree);
                pool.RemoveAt(index);
            }

            // Check tree is empty
            Assert.AreEqual(0, tree.Count, "Tree not empty");
        }
Пример #9
0
        public static ulong Solve_LLRBT(ulong[] arr, ulong m)
        {
            // 10000000 - 48545 ms

            var sumsLeft = new ulong[arr.Length];

            sumsLeft[0] = arr[0] % m;
            for (var i = 1; i < arr.Length; i++)
            {
                sumsLeft[i] = (sumsLeft[i - 1] + arr[i]) % m;
            }

            var sumsSorted = new LeftLeaningRedBlackTree <ulong, int>((x, y) => x.CompareTo(y), (x, y) => x.CompareTo(y));

            foreach (var item in sumsLeft)
            {
                sumsSorted.Add(item, 0);
            }

            var max = arr[0] % m;

            for (var i = 0; i < arr.Length; i++)
            {
                var left = i == 0 ? 0ul : sumsLeft[i - 1];

                var searchme = left == 0 ? (m - 1) : (left - 1);

                foreach (var node in sumsSorted.Search(n => n.Key == searchme ? (bool?)null : n.Key < searchme ? false : true))
                {
                    if (node.Key <= searchme)
                    {
                        max = Math.Max(max, (node.Key + m - left) % m);
                    }
                }

                sumsSorted.Remove(sumsLeft[i], 0);
            }

            return(max);
        }
Пример #10
0
        public static ulong Solve(int n, int[][] edges, ulong[] coins)
        {
            if (n == 1)
            {
                return(ulong.MaxValue);
            }

            var adj  = ToDirectedTree(edges, n + 1);
            var head = edges[0][0];

            var sumsBelow = new ulong[n + 1];

            var stack      = new Stack <int>(n + 1);
            var ignoreSums = new bool[n + 1];

            foreach (var node in Traverse_Tree_PostOrder_NonRec(head, v => adj[v]))
            {
                sumsBelow[node] = coins[node - 1] + adj[node].Select(v => sumsBelow[v]).Sum();
            }

            var total = sumsBelow[head];

            var sumsSet = new LeftLeaningRedBlackTree <ulong, int>((x, y) => x.CompareTo(y), (x, y) => x.CompareTo(y));

            for (var i = 1; i <= n; i++)
            {
                sumsSet.Add(sumsBelow[i], i);
            }

            var best = ulong.MaxValue;

            var path = new List <int>(n + 1)
            {
                head
            };
            var notInA = new bool[n + 1];

            notInA[head] = true;

            foreach (var edgeInfo in Traverse_Dfs_WithEvents(head, v => adj[v]))
            {
                var aNode = edgeInfo.Child;

                if (edgeInfo.IsDownNotUp)
                {
                    path.Add(aNode);

                    notInA[edgeInfo.Parent] = true;
                    foreach (var otherChild in adj[edgeInfo.Parent])
                    {
                        if (otherChild != edgeInfo.Child)
                        {
                            foreach (var node in Traverse_Tree_Dfs(otherChild, v => adj[v], stack))
                            {
                                notInA[node] = true;
                            }
                        }
                    }
                }
                else
                {
                    path.RemoveAt(path.Count - 1);

                    notInA[edgeInfo.Parent] = false;
                    foreach (var otherChild in adj[edgeInfo.Parent])
                    {
                        if (otherChild != edgeInfo.Child)
                        {
                            foreach (var node in Traverse_Tree_Dfs(otherChild, v => adj[v], stack))
                            {
                                notInA[node] = false;
                            }
                        }
                    }

                    continue;
                }

                var a = sumsBelow[aNode];

                if (a == total - a)
                {
                    best = Math.Min(best, a);
                }

                foreach (var pathNode in path)
                {
                    if (pathNode != aNode)
                    {
                        var sum = sumsBelow[pathNode];
                        sumsSet.Remove(sum, pathNode);
                        sumsSet.Add(sum - a, pathNode);
                    }
                }

                var searchme = new List <ulong>(3)
                {
                    a
                };
                if (total > 2 * a)
                {
                    searchme.Add(total - 2 * a);
                }
                if (total != a && (total - a) % 2 == 0)
                {
                    searchme.Add((total - a) / 2);
                }

                foreach (var sum in searchme)
                {
                    if (sumsSet.GetValuesForKey(sum).Any(i => notInA[i]))
                    {
                        best = CalcBest(best, a, sum, total - a - sum);
                    }
                }

                foreach (var pathNode in path)
                {
                    if (pathNode != aNode)
                    {
                        var sum = sumsBelow[pathNode];
                        sumsSet.Remove(sum - a, pathNode);
                        sumsSet.Add(sum, pathNode);
                    }
                }
            }

            return(best);
        }
Пример #11
0
        public void GetValueForKeyMultiple()
        {
            LeftLeaningRedBlackTree <int, int> binaryTree = new LeftLeaningRedBlackTree <int, int>(IntComparison, IntComparison);

            binaryTree.GetValueForKey(-1);
        }
Пример #12
0
        public void RemoveKeyMultiple()
        {
            LeftLeaningRedBlackTree <int, int> binaryTree = new LeftLeaningRedBlackTree <int, int>(IntComparison, IntComparison);

            binaryTree.Remove(-1);
        }
Пример #13
0
        /// <summary>
        /// Verifies all public methods with a large number of 'random' scenarios.
        /// </summary>
        /// <param name="seed">Seed for Random constructor.</param>
        /// <param name="isMultiDictionary">True if testing a multi-dictionary.</param>
        private static void RandomScenarios(int seed, bool isMultiDictionary)
        {
            // Use fixed sead for reproducability
            Random rand = new Random(seed);

            for (int scenario = 0; scenario < Scenarios; scenario++)
            {
                LeftLeaningRedBlackTree <int, int> binaryTree = isMultiDictionary ?
                                                                new LeftLeaningRedBlackTree <int, int>(IntComparison, IntComparison) :
                                                                new LeftLeaningRedBlackTree <int, int>(IntComparison);

                // Randomize parameters
                int elementBound = rand.Next(1, 100);
                int keyBound     = rand.Next(1, 50);
                int valueBound   = rand.Next(1, 50);

                // Add random elements
                List <KeyValuePair <int, int> > elements = new List <KeyValuePair <int, int> >();
                for (int i = 0; i < elementBound; i++)
                {
                    KeyValuePair <int, int> element = new KeyValuePair <int, int>(rand.Next(keyBound), rand.Next(valueBound));
                    if (!isMultiDictionary)
                    {
                        IEnumerable <KeyValuePair <int, int> > matches = elements.Where(p => p.Key == element.Key).ToList();
                        foreach (KeyValuePair <int, int> match in matches)
                        {
                            elements.Remove(match);
                        }
                    }
                    elements.Add(element);
                    binaryTree.Add(element.Key, element.Value);
                    CheckTree(binaryTree, elements, isMultiDictionary);
                }

                // Try to remove some elements that aren't present
                int removeBound = rand.Next(20);
                for (int i = 0; i < removeBound; i++)
                {
                    int key   = rand.Next(keyBound);
                    int value = rand.Next(valueBound);
                    if (!elements.Where(p => (key == p.Key) && (!isMultiDictionary || (value == p.Value))).Any())
                    {
                        if (isMultiDictionary)
                        {
                            Assert.IsFalse(binaryTree.Remove(key, value));
                        }
                        else
                        {
                            Assert.IsFalse(binaryTree.Remove(key));
                        }
                        CheckTree(binaryTree, elements, isMultiDictionary);
                    }
                }

                // Remove all elements in random order
                while (0 < elements.Count)
                {
                    int index = rand.Next(elements.Count);
                    KeyValuePair <int, int> element = elements[index];
                    elements.RemoveAt(index);
                    if (isMultiDictionary)
                    {
                        Assert.IsTrue(binaryTree.Remove(element.Key, element.Value));
                    }
                    else
                    {
                        Assert.IsTrue(binaryTree.Remove(element.Key));
                    }
                    CheckTree(binaryTree, elements, isMultiDictionary);
                }

                // Final verification
                Assert.IsFalse(binaryTree.Remove(0, 0));
                elements.Clear();
                binaryTree.Clear();
                CheckTree(binaryTree, elements, isMultiDictionary);
            }
        }