//┴ ┐ ─ ┌ ┘ └ 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(); }
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); }
/// <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); }
/// <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."); } }
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"); }
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); }
/// <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); } }
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"); }
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); }
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); }
public void GetValueForKeyMultiple() { LeftLeaningRedBlackTree <int, int> binaryTree = new LeftLeaningRedBlackTree <int, int>(IntComparison, IntComparison); binaryTree.GetValueForKey(-1); }
public void RemoveKeyMultiple() { LeftLeaningRedBlackTree <int, int> binaryTree = new LeftLeaningRedBlackTree <int, int>(IntComparison, IntComparison); binaryTree.Remove(-1); }
/// <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); } }