Example #1
0
        public void CanConstructKeyCollections()
        {
            RedBlackTree <int, string> redBlackTree = new RedBlackTree <int, string>
            {
                { 1, "1" },
                { 2, "2" },
                { 3, "3" },
                { 4, "4" },
                { 5, "5" },
            };

            ICollection <int> keys = redBlackTree.Keys;

            Assert.That(keys, Is.Not.Null);
            Assert.That(keys.Count, Is.EqualTo(5));

            WeightedRedBlackTree <int, string> redBlackTree2 = new WeightedRedBlackTree <int, string>
            {
                { 1, "1" },
                { 2, "2" },
                { 3, "3" },
                { 4, "4" },
                { 5, "5" },
            };

            keys = redBlackTree2.Keys;
            Assert.That(keys, Is.Not.Null);
            Assert.That(keys.Count, Is.EqualTo(5));
        }
        public void CanReadThroughAsDictionaryWeighted()
        {
            WeightedRedBlackTree <int, string> tree = new WeightedRedBlackTree <int, string>
            {
                { 1, "1" },
                { 2, "2" },
                { 3, "3" },
                { 4, "4" },
                { 5, "5" },
            };

            IDictionary <int, string> dictionary = tree.AsDictionary();

            Assert.That(dictionary[2], Is.EqualTo("2"));
            Assert.That(dictionary.Count, Is.EqualTo(5));
            Assert.That(dictionary.Contains(new KeyValuePair <int, string>(2, "2")), Is.True);
            Assert.That(dictionary.Contains(new KeyValuePair <int, string>(2, "6")), Is.False);
            Assert.That(dictionary.Contains(new KeyValuePair <int, string>(6, "2")), Is.False);
            Assert.That(dictionary.Contains(new KeyValuePair <int, string>(6, "6")), Is.False);
            Assert.That(dictionary.Contains(new KeyValuePair <int, string>(2, null)), Is.False);
            Assert.That(dictionary.ContainsKey(2), Is.True);
            Assert.That(dictionary.ContainsKey(6), Is.False);
            Assert.That(dictionary.IsReadOnly, Is.False);

            Assert.That(dictionary.TryGetValue(2, out string value), Is.True);
            Assert.That(value, Is.EqualTo("2"));

            Assert.That(dictionary.TryGetValue(6, out value), Is.False);
        }
        public void PreviousShouldBeAbleToWalkTheTreeBackward()
        {
            int seed = 12345;

            int RandomNext()
            {
                seed = (seed * 69069) + 12345;
                return((seed >> 16) & 0x7FFF);
            }

            WeightedRedBlackTree <int, int> tree = new WeightedRedBlackTree <int, int>();

            List <int> keys = new List <int>();

            for (int i = 0; i < 500; i++)
            {
                int key = RandomNext();
                keys.Add(key);

                tree.Add(key, i);

                if (IsFibonacci(i))
                {
                    List <WeightedRedBlackTreeNode <int, int> > actualNodes = new List <WeightedRedBlackTreeNode <int, int> >();
                    for (WeightedRedBlackTreeNode <int, int> node = tree.MaximumNode; node != null; node = node.Previous())
                    {
                        actualNodes.Add(node);
                    }
                    int[] actualKeys   = actualNodes.Select(n => n.Key).ToArray();
                    int[] expectedKeys = keys.OrderByDescending(k => k).ToArray();

                    CollectionAssert.AreEqual(actualKeys, expectedKeys);
                }
            }
        }
        public void TreeShouldBeValidAfterManyRandomDeletions()
        {
            int seed = 12345;

            int RandomNext()
            {
                seed = (seed * 69069) + 12345;
                return((seed >> 16) & 0x7FFF);
            }

            WeightedRedBlackTree <int, int> tree = new WeightedRedBlackTree <int, int>();

            List <Tuple <int, int> > insertions = new List <Tuple <int, int> >();

            for (int i = 0; i < 500; i++)
            {
                int key = RandomNext();
                insertions.Add(new Tuple <int, int>(key, i));

                Assert.That(tree.Count, Is.EqualTo(i));
                Assert.That(tree.TryGetValue(key, out int oldValue), Is.False);
                Assert.That(tree.ContainsKey(key), Is.False);

                tree.Add(key, i);

                if (IsFibonacci(i))
                {
                    tree.Validate();
                }

                Assert.That(tree.ContainsKey(key), Is.True);
                Assert.That(tree[key], Is.EqualTo(i));
                Assert.That(tree.TryGetValue(key, out int newValue), Is.True);
                Assert.That(newValue, Is.EqualTo(i));
                Assert.That(tree.Count, Is.EqualTo(i + 1));
            }

            for (int i = 0; i < 500; i++)
            {
                int key   = insertions[i].Item1;
                int value = insertions[i].Item2;

                Assert.That(tree.ContainsKey(key), Is.True);
                Assert.That(tree[key], Is.EqualTo(value));
                Assert.That(tree.TryGetValue(key, out int newValue), Is.True);
                Assert.That(newValue, Is.EqualTo(value));
                Assert.That(tree.Count, Is.EqualTo(500 - i));

                Assert.That(tree.Remove(key), Is.True);

                if (IsFibonacci(i))
                {
                    tree.Validate();
                }

                Assert.That(tree.ContainsKey(key), Is.False);
                Assert.That(tree.TryGetValue(key, out int oldValue), Is.False);
                Assert.That(tree.Count, Is.EqualTo(500 - i - 1));
            }
        }
        public void CanUseTheIndexerToReplaceOrInsertValues()
        {
            WeightedRedBlackTree <int, int> tree = new WeightedRedBlackTree <int, int>
            {
                { 1, 10 },
                { 3, 20 },
                { 5, 30 },
                { 7, 40 },
                { 9, 50 },
            };

            tree[5]  = 35;
            tree[7]  = 45;
            tree[9]  = 55;
            tree[10] = 60;

            tree[int.MinValue] = -1;
            tree[0]            = 12345;
            tree[int.MaxValue] = 999;

            CollectionAssert.AreEqual(tree.KeyValuePairs, new[]
            {
                new KeyValuePair <int, int>(int.MinValue, -1),
                new KeyValuePair <int, int>(0, 12345),
                new KeyValuePair <int, int>(1, 10),
                new KeyValuePair <int, int>(3, 20),
                new KeyValuePair <int, int>(5, 35),
                new KeyValuePair <int, int>(7, 45),
                new KeyValuePair <int, int>(9, 55),
                new KeyValuePair <int, int>(10, 60),
                new KeyValuePair <int, int>(int.MaxValue, 999),
            });
        }
        public void CanConstructValueCollections()
        {
            RedBlackTree <int, string> redBlackTree = new RedBlackTree <int, string>
            {
                { 1, "1" },
                { 2, "2" },
                { 3, "3" },
                { 4, "4" },
                { 5, "5" },
            };

            ICollection <string> values = redBlackTree.Values;

            Assert.That(values, Is.Not.Null);
            Assert.That(values.Count, Is.EqualTo(5));

            WeightedRedBlackTree <int, string> redBlackTree2 = new WeightedRedBlackTree <int, string>
            {
                { 1, "1" },
                { 2, "2" },
                { 3, "3" },
                { 4, "4" },
                { 5, "5" },
            };

            values = redBlackTree2.Values;
            Assert.That(values, Is.Not.Null);
            Assert.That(values.Count, Is.EqualTo(5));
        }
        public void CanConstructPairCollections()
        {
            RedBlackTree <int, string> redBlackTree = new RedBlackTree <int, string>
            {
                { 1, "1" },
                { 2, "2" },
                { 3, "3" },
                { 4, "4" },
                { 5, "5" },
            };

            ICollection <KeyValuePair <int, string> > pairs = redBlackTree.KeyValuePairs;

            Assert.That(pairs, Is.Not.Null);
            Assert.That(pairs.Count, Is.EqualTo(5));

            WeightedRedBlackTree <int, string> redBlackTree2 = new WeightedRedBlackTree <int, string>
            {
                { 1, "1" },
                { 2, "2" },
                { 3, "3" },
                { 4, "4" },
                { 5, "5" },
            };

            pairs = redBlackTree2.KeyValuePairs;
            Assert.That(pairs, Is.Not.Null);
            Assert.That(pairs.Count, Is.EqualTo(5));
        }
        public void NewTreeShouldBeEmpty()
        {
            WeightedRedBlackTree <int, int> tree = new WeightedRedBlackTree <int, int>();

            Assert.That(tree.Root, Is.Null);
            Assert.That(tree.Count, Is.Zero);

            tree.Validate();
        }
        public void CanMutateThroughAsDictionaryWeighted()
        {
            WeightedRedBlackTree <int, string> tree = new WeightedRedBlackTree <int, string>
            {
                { 1, "1" },
                { 2, "2" },
                { 3, "3" },
                { 4, "4" },
                { 5, "5" },
            };

            IDictionary <int, string> dictionary = tree.AsDictionary();

            dictionary[3] = "foo";
            Assert.That(tree.Find(3).Value, Is.EqualTo("foo"));

            dictionary.Add(6, "6");
            Assert.That(tree.Find(6).Value, Is.EqualTo("6"));

            dictionary.Add(new KeyValuePair <int, string>(7, "7"));
            Assert.That(tree.Find(7).Value, Is.EqualTo("7"));

            Assert.That(dictionary.Remove(3), Is.True);
            Assert.That(tree.Find(3), Is.Null);

            Assert.That(dictionary.Remove(new KeyValuePair <int, string>(8, "8")), Is.False);
            dictionary.Add(8, null);
            Assert.That(dictionary.Remove(new KeyValuePair <int, string>(2, null)), Is.False);
            Assert.That(dictionary.Remove(new KeyValuePair <int, string>(2, "2")), Is.True);
            Assert.That(tree.Find(2), Is.Null);
            Assert.That(dictionary.Remove(new KeyValuePair <int, string>(8, "8")), Is.False);
            Assert.That(dictionary.Remove(new KeyValuePair <int, string>(8, null)), Is.True);
            Assert.That(tree.Find(8), Is.Null);

            CollectionAssert.AreEqual(tree.KeyValuePairs, new[]
            {
                new KeyValuePair <int, string>(1, "1"),
                new KeyValuePair <int, string>(4, "4"),
                new KeyValuePair <int, string>(5, "5"),
                new KeyValuePair <int, string>(6, "6"),
                new KeyValuePair <int, string>(7, "7"),
            });

            dictionary.Clear();
            Assert.That(tree.Root, Is.Null);
            Assert.That(tree.Count, Is.Zero);
        }
        public void ForeachShouldWalkTheTreeForward()
        {
            int seed = 12345;

            int RandomNext()
            {
                seed = (seed * 69069) + 12345;
                return((seed >> 16) & 0x7FFF);
            }

            WeightedRedBlackTree <int, int> tree = new WeightedRedBlackTree <int, int>();

            {
                List <WeightedRedBlackTreeNode <int, int> > actualNodes = new List <WeightedRedBlackTreeNode <int, int> >();
                foreach (WeightedRedBlackTreeNode <int, int> node in tree)
                {
                    actualNodes.Add(node);
                }
                int[] actualKeys = actualNodes.Select(n => n.Key).ToArray();

                CollectionAssert.AreEqual(actualKeys, new int[0]);
            }

            List <int> keys = new List <int>();

            for (int i = 0; i < 500; i++)
            {
                int key = RandomNext();
                keys.Add(key);

                tree.Add(key, i);

                if (IsFibonacci(i))
                {
                    List <WeightedRedBlackTreeNode <int, int> > actualNodes = new List <WeightedRedBlackTreeNode <int, int> >();
                    foreach (WeightedRedBlackTreeNode <int, int> node in tree)
                    {
                        actualNodes.Add(node);
                    }
                    int[] actualKeys   = actualNodes.Select(n => n.Key).ToArray();
                    int[] expectedKeys = keys.OrderBy(k => k).ToArray();

                    CollectionAssert.AreEqual(actualKeys, expectedKeys);
                }
            }
        }
        public void CanConstructAReadOnlyWeightedRedBlackTreeWrapper()
        {
            WeightedRedBlackTree <int, string> tree = new WeightedRedBlackTree <int, string>
            {
                { 1, "1" },
                { 2, "2" },
                { 3, "3" },
                { 4, "4" },
                { 5, "5" },
            };

            ReadOnlyWeightedRedBlackTree <int, string> wrapper = new ReadOnlyWeightedRedBlackTree <int, string>(tree);

            Assert.That(wrapper, Is.Not.Null);
            Assert.That(wrapper.Compare, Is.EqualTo(tree.Compare));
            Assert.That(wrapper.Root, Is.EqualTo(tree.Root));
            Assert.That(wrapper.Count, Is.EqualTo(5));
            Assert.That(wrapper.MinimumNode.Key, Is.EqualTo(1));
            Assert.That(wrapper.MaximumNode.Key, Is.EqualTo(5));
        }
        public void CanReadAsCollectionThroughAsDictionaryWeighted()
        {
            WeightedRedBlackTree <int, string> tree = new WeightedRedBlackTree <int, string>
            {
                { 1, "1" },
                { 2, "2" },
                { 3, "3" },
                { 4, "4" },
                { 5, "5" },
            };

            IDictionary <int, string> dictionary = tree.AsDictionary();

            KeyValuePair <int, string>[] array = new KeyValuePair <int, string> [5];
            dictionary.CopyTo(array, 0);
            CollectionAssert.AreEquivalent(array, new[] {
                new KeyValuePair <int, string>(1, "1"),
                new KeyValuePair <int, string>(2, "2"),
                new KeyValuePair <int, string>(3, "3"),
                new KeyValuePair <int, string>(4, "4"),
                new KeyValuePair <int, string>(5, "5"),
            });

            CollectionAssert.AreEquivalent(dictionary.Keys, new[] { 1, 2, 3, 4, 5 });
            CollectionAssert.AreEquivalent(dictionary.Values, new[] { "1", "2", "3", "4", "5" });

            int index = 0;

            array = new KeyValuePair <int, string> [5];
            foreach (KeyValuePair <int, string> pair in dictionary)
            {
                array[index++] = pair;
            }
            CollectionAssert.AreEquivalent(array, new[] {
                new KeyValuePair <int, string>(1, "1"),
                new KeyValuePair <int, string>(2, "2"),
                new KeyValuePair <int, string>(3, "3"),
                new KeyValuePair <int, string>(4, "4"),
                new KeyValuePair <int, string>(5, "5"),
            });
        }
        public void ShouldBeAbleToFindMinimaAndMaxima()
        {
            int seed = 12345;

            int RandomNext()
            {
                seed = (seed * 69069) + 12345;
                return((seed >> 16) & 0x7FFF);
            }

            WeightedRedBlackTree <int, int> tree = new WeightedRedBlackTree <int, int>();

            Assert.That(tree.MinimumKey, Is.EqualTo(default(int)));
            Assert.That(tree.MaximumKey, Is.EqualTo(default(int)));
            Assert.That(tree.MinimumNode, Is.Null);
            Assert.That(tree.MaximumNode, Is.Null);

            List <int> keys = new List <int>();

            for (int i = 0; i < 500; i++)
            {
                int key = RandomNext();
                keys.Add(key);

                tree.Add(key, i);

                int expectedMinimum = keys.Min();
                int actualMinimum   = tree.MinimumKey;
                Assert.That(expectedMinimum, Is.EqualTo(actualMinimum));

                WeightedRedBlackTreeNode <int, int> actualMinimumNode = tree.MinimumNode;
                Assert.That(expectedMinimum, Is.EqualTo(actualMinimumNode.Key));

                int expectedMaximum = keys.Max();
                int actualMaximum   = tree.MaximumKey;
                Assert.That(expectedMaximum, Is.EqualTo(actualMaximum));

                WeightedRedBlackTreeNode <int, int> actualMaximumNode = tree.MaximumNode;
                Assert.That(expectedMaximum, Is.EqualTo(actualMaximumNode.Key));
            }
        }
        public void CanUseAnExplicitComparisonFunction()
        {
            int CompareFoos(Foo a, Foo b)
            {
                return(a.Value.CompareTo(b.Value));
            }

            WeightedRedBlackTree <Foo, int> tree = new WeightedRedBlackTree <Foo, int>(CompareFoos)
            {
                { new Foo(1), 10 },
                { new Foo(3), 20 },
                { new Foo(5), 30 },
                { new Foo(7), 40 },
                { new Foo(9), 50 },
            };

            tree[new Foo(5)]  = 35;
            tree[new Foo(7)]  = 45;
            tree[new Foo(9)]  = 55;
            tree[new Foo(10)] = 60;

            tree[new Foo(int.MinValue)] = -1;
            tree[new Foo(0)]            = 12345;
            tree[new Foo(int.MaxValue)] = 999;

            CollectionAssert.AreEqual(tree.KeyValuePairs, new[]
            {
                new KeyValuePair <Foo, int>(new Foo(int.MinValue), -1),
                new KeyValuePair <Foo, int>(new Foo(0), 12345),
                new KeyValuePair <Foo, int>(new Foo(1), 10),
                new KeyValuePair <Foo, int>(new Foo(3), 20),
                new KeyValuePair <Foo, int>(new Foo(5), 35),
                new KeyValuePair <Foo, int>(new Foo(7), 45),
                new KeyValuePair <Foo, int>(new Foo(9), 55),
                new KeyValuePair <Foo, int>(new Foo(10), 60),
                new KeyValuePair <Foo, int>(new Foo(int.MaxValue), 999),
            });
        }
        public void ToDictionaryShouldGenerateAnEquivalentDictionary()
        {
            int seed = 12345;

            int RandomNext()
            {
                seed = (seed * 69069) + 12345;
                return((seed >> 16) & 0x7FFF);
            }

            WeightedRedBlackTree <int, int> tree = new WeightedRedBlackTree <int, int>();

            {
                Dictionary <int, int> dictionary = tree.ToDictionary();
                Assert.That(dictionary.Count, Is.Zero);
            }

            List <int> keys = new List <int>();

            for (int i = 0; i < 500; i++)
            {
                int key = RandomNext();
                keys.Add(key);

                tree.Add(key, i);

                if (IsFibonacci(i))
                {
                    Dictionary <int, int> dictionary = tree.ToDictionary();

                    List <KeyValuePair <int, int> > expectedPairs = tree.Select(n => n.ToKeyValuePair()).ToList();
                    List <KeyValuePair <int, int> > actualPairs   = dictionary.OrderBy(p => p.Key).ToList();

                    CollectionAssert.AreEqual(actualPairs, expectedPairs);
                }
            }
        }
        public void CanCopyToSpecialCaseTrees()
        {
            {
                WeightedRedBlackTree <int, int> tree = new WeightedRedBlackTree <int, int>();

                Assert.That(tree.Root, Is.Null);

                // CopyTo should safely bail if the root is null.
                WeightedRedBlackTreeNode <int, int>[] actualNodes = new WeightedRedBlackTreeNode <int, int> [0];
                tree.CopyTo(actualNodes, 0);
                int[] actualKeys = actualNodes.Select(n => n.Key).ToArray();
                CollectionAssert.AreEqual(actualKeys, new int[0]);
            }
            {
                WeightedRedBlackTree <int, int> tree = new WeightedRedBlackTree <int, int>
                {
                    { 1, 10 },
                };

                // The above is a valid red-black tree with only one node.
                Assert.That(tree.Root.Key, Is.EqualTo(1));

                // CopyTo performs an inorder walk using Next(), starting at
                // Root's minimum subnode.
                List <WeightedRedBlackTreeNode <int, int> > actualNodes = tree.ToList();
                int[] actualKeys = actualNodes.Select(n => n.Key).ToArray();
                CollectionAssert.AreEqual(actualKeys, new[] { 1 });
            }
            {
                WeightedRedBlackTree <int, int> tree = new WeightedRedBlackTree <int, int>
                {
                    { 2, 20 },
                    { 1, 10 },
                };

                // The above is a valid red-black tree in which the root is 2
                // and it has a left child of 1.  Let's check that to be sure...
                Assert.That(tree.Root.Key, Is.EqualTo(2));
                Assert.That(tree.Root.Left.Key, Is.EqualTo(1));

                // CopyTo performs an inorder walk using Next(), starting at
                // Root's minimum subnode.  In this case, we ensure that
                // Root is non-null and has a minimum subnode to start at.
                List <WeightedRedBlackTreeNode <int, int> > actualNodes = tree.ToList();
                int[] actualKeys = actualNodes.Select(n => n.Key).ToArray();
                CollectionAssert.AreEqual(actualKeys, new[] { 1, 2 });
            }
            {
                WeightedRedBlackTree <int, int> tree = new WeightedRedBlackTree <int, int>
                {
                    { 1, 10 },
                    { 2, 20 },
                };

                // The above is a valid red-black tree in which the root is 1
                // and it has a right child of 2.  Let's check that to be sure...
                Assert.That(tree.Root.Key, Is.EqualTo(1));
                Assert.That(tree.Root.Right.Key, Is.EqualTo(2));

                // CopyTo performs an inorder walk using Next(), starting at
                // Root's minimum subnode.  In this case, we ensure that
                // Root is non-null but has no minimum subnode to start at.
                List <WeightedRedBlackTreeNode <int, int> > actualNodes = tree.ToList();
                int[] actualKeys = actualNodes.Select(n => n.Key).ToArray();
                CollectionAssert.AreEqual(actualKeys, new[] { 1, 2 });
            }
        }
        public void CannotRemoveKeysThatDontExist()
        {
            WeightedRedBlackTree <int, int> tree = new WeightedRedBlackTree <int, int>
            {
                { 1, 10 },
                { 3, 20 },
                { 5, 30 },
                { 7, 40 },
                { 9, 50 },
            };

            Assert.That(tree.Remove(4), Is.False);

            CollectionAssert.AreEqual(tree.KeyValuePairs, new[]
            {
                new KeyValuePair <int, int>(1, 10),
                new KeyValuePair <int, int>(3, 20),
                new KeyValuePair <int, int>(5, 30),
                new KeyValuePair <int, int>(7, 40),
                new KeyValuePair <int, int>(9, 50),
            });

            Assert.That(tree.Remove(3), Is.True);

            CollectionAssert.AreEqual(tree.KeyValuePairs, new[]
            {
                new KeyValuePair <int, int>(1, 10),
                new KeyValuePair <int, int>(5, 30),
                new KeyValuePair <int, int>(7, 40),
                new KeyValuePair <int, int>(9, 50),
            });

            Assert.That(tree.Remove(1), Is.True);

            CollectionAssert.AreEqual(tree.KeyValuePairs, new[]
            {
                new KeyValuePair <int, int>(5, 30),
                new KeyValuePair <int, int>(7, 40),
                new KeyValuePair <int, int>(9, 50),
            });

            Assert.That(tree.Remove(7), Is.True);

            CollectionAssert.AreEqual(tree.KeyValuePairs, new[]
            {
                new KeyValuePair <int, int>(5, 30),
                new KeyValuePair <int, int>(9, 50),
            });

            Assert.That(tree.Remove(9), Is.True);

            CollectionAssert.AreEqual(tree.KeyValuePairs, new[]
            {
                new KeyValuePair <int, int>(5, 30),
            });

            WeightedRedBlackTreeNode <int, int> fiveNode = tree.Find(5);

            Assert.That(tree.Remove(5), Is.True);
            tree.DeleteNode(null);                      // Make this is always a no-op.

            CollectionAssert.AreEqual(tree.KeyValuePairs, new KeyValuePair <int, int> [0]);

            Assert.That(tree.Remove(3), Is.False);

            Assert.That(tree.Count, Is.Zero);
            Assert.That(tree.Root, Is.Null);
            tree.DeleteNode(fiveNode);                  // Make sure nothing bad happens with an empty tree.
        }