Beispiel #1
0
        public void Delete()
        {
            // The constructed AVL Tree would be
            //     30
            //    /  \ 
            //   20   40
            //  /  \   \ 
            // 10  25   50

            var tree = new AvlTree <int>();

            tree.Insert(10);
            tree.Insert(20);
            tree.Insert(30);
            tree.Insert(40);
            tree.Insert(50);
            tree.Insert(25);

            tree.Delete(10);
            tree.Delete(50);

            tree.TraversalMode = TraversalMode.InOrder;
            var actual = tree;

            CollectionAssert.AreEqual(new[] { 20, 25, 30, 40 }, actual);
        }
Beispiel #2
0
        public PathNode Remove(PathNode pathNode)
        {
            PathNode node = posTree.Delete(pathNode.Position);

            fTree.Delete(node.f, node);
            --size;
            return(node);
        }
Beispiel #3
0
        static void Main(string[] args)
        {
            AvlTree <int, int> tree = new AvlTree <int, int>();

            for (int i = 0; i < 150; i++)
            {
                tree.Insert(i, 0);
            }
            Console.Clear();
            tree.Delete(5);
            //tree.Delete(4);
            //tree.Delete(3);

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

            void action(Node <int, int> a)
            {
                if (a.LeftChildNode == a.RightChildNode && a.LeftChildNode != null)
                {
                    error.Add(a.Key);
                }
            }

            tree.LeftTraversal(action);
            error.ForEach(n => Console.Write($"{n} "));
            Console.Read();
        }
        public static int RemoveTimeSubset <T>(this AvlTree <MappedInterval <T> > tree, long from, long to)
        {
            var removedNodesCount             = 0;
            INode <MappedInterval <T> > first = null;
            INode <MappedInterval <T> > last  = null;

            // TODO Remove .ToArray()
            foreach (var node in tree.FirstOrderedSubsequence(node => AcceptNode(node.Key, from, to)).ToArray())
            {
                if (first == null)
                {
                    first = node;
                }

                last = node;

                tree.Delete(node.Key);
                removedNodesCount++;
            }

            if (first != null && first.Key.IntervalStart < from)
            {
                tree.Insert(new MappedInterval <T>(first.Key.IntervalStart, from, first.Key.Payload));
            }

            if (last != null && to < last.Key.IntervalEnd)
            {
                tree.Insert(new MappedInterval <T>(to, last.Key.IntervalEnd, last.Key.Payload));
            }

            return(removedNodesCount);
        }
Beispiel #5
0
        private static void Main()
        {
            var avlTree = new AvlTree <int>();
            var rnd     = new Random();
            //Generate 20 random integer
            var nits = new int[100000];

            for (var i = 0; i < 100000; i++)
            {
                nits[i] = rnd.Next(-2000000, 2000000);
            }
            foreach (var e in nits)
            {
                avlTree.Insert(e);
            }
            foreach (var e in nits)
            {
                var res = avlTree.TryFind(e);
                Console.WriteLine($"number: {e}, found: {res.Found}");
            }

            foreach (var e in nits)
            {
                avlTree.Delete(e);
            }
        }
Beispiel #6
0
        public void Leaf()
        {
            var tree = new AvlTree();

            tree.Insert(1);
            tree.Insert(2);
            tree.Insert(3);

            tree.Delete(3);

            #region Root

            Assert.IsNotNull(tree.Root);
            Assert.AreEqual(2, tree.Root.Key);
            Assert.AreEqual(-1, tree.Root.Balance);

            #endregion

            #region 1. level

            Assert.IsNotNull(tree.Root.Left);
            Assert.AreEqual(1, tree.Root.Left.Key);
            Assert.AreEqual(0, tree.Root.Left.Balance);

            Assert.IsNull(tree.Root.Right);

            #endregion
        }
Beispiel #7
0
        public void StressTest()
        {
            Console.WriteLine("AVLTree Stress Test is running...");
            var avlTree = new AvlTree <int>();
            var rnd     = new Random();
            //Generate 20 random integer
            var testData = new int[9999999];

            for (var i = 0; i < 9999999; i++)
            {
                testData[i] = rnd.Next(-2000000, 2000000);
            }
            foreach (var e in testData)
            {
                avlTree.Insert(e);
            }
            foreach (var e in testData)
            {
                var res = avlTree.TryFind(e);
                Assert.IsTrue(res.Found);
                Assert.AreEqual(res.Data, e);
            }

            foreach (var e in testData)
            {
                avlTree.Delete(e);
            }
            Console.WriteLine("AVLTree Stress Test has finished running...");
        }
Beispiel #8
0
        public void NonExistentInEmptyTree()
        {
            var tree = new AvlTree();

            tree.Delete(5);

            Assert.AreEqual(null, tree.Root);
        }
Beispiel #9
0
        public void DeleteWithRebalance()
        {
            var tree = new AvlTree <int>();

            tree.Insert(10);
            tree.Insert(20);
            tree.Insert(30);
            tree.Insert(40);
            tree.Insert(50);
            tree.Insert(25);

            tree.Delete(10);
            tree.Delete(30);

            tree.TraversalMode = TraversalMode.InOrder;
            var actual = tree;

            CollectionAssert.AreEqual(new[] { 20, 25, 40, 50 }, actual);
        }
Beispiel #10
0
        public void Root()
        {
            var tree = new AvlTree();

            tree.Insert(5);

            tree.Delete(5);

            Assert.IsNull(tree.Root);
        }
Beispiel #11
0
        public void RightLeft()
        {
            var tree = new AvlTree();

            tree.Insert(2);
            tree.Insert(1);
            tree.Insert(10);
            tree.Insert(0);
            tree.Insert(8);
            tree.Insert(12);
            tree.Insert(6);
            tree.Insert(9);

            tree.Delete(0);

            #region Root

            Assert.IsNotNull(tree.Root);
            Assert.AreEqual(8, tree.Root.Key);
            Assert.AreEqual(0, tree.Root.Balance);

            #endregion

            #region 1. level

            Assert.IsNotNull(tree.Root.Left);
            Assert.AreEqual(2, tree.Root.Left.Key);
            Assert.AreEqual(0, tree.Root.Left.Balance);

            Assert.IsNotNull(tree.Root.Right);
            Assert.AreEqual(10, tree.Root.Right.Key);
            Assert.AreEqual(0, tree.Root.Right.Balance);

            #endregion

            #region 2. level

            Assert.IsNotNull(tree.Root.Left.Left);
            Assert.AreEqual(1, tree.Root.Left.Left.Key);
            Assert.AreEqual(0, tree.Root.Left.Left.Balance);

            Assert.IsNotNull(tree.Root.Left.Right);
            Assert.AreEqual(6, tree.Root.Left.Right.Key);
            Assert.AreEqual(0, tree.Root.Left.Right.Balance);

            Assert.IsNotNull(tree.Root.Right.Left);
            Assert.AreEqual(9, tree.Root.Right.Left.Key);
            Assert.AreEqual(0, tree.Root.Right.Left.Balance);

            Assert.IsNotNull(tree.Root.Right.Right);
            Assert.AreEqual(12, tree.Root.Right.Right.Key);
            Assert.AreEqual(0, tree.Root.Right.Right.Balance);

            #endregion
        }
Beispiel #12
0
        public void LeftLeft()
        {
            var tree = new AvlTree();

            tree.Insert(6);
            tree.Insert(4);
            tree.Insert(7);
            tree.Insert(2);
            tree.Insert(5);
            tree.Insert(8);
            tree.Insert(1);
            tree.Insert(3);

            tree.Delete(8);

            #region Root

            Assert.IsNotNull(tree.Root);
            Assert.AreEqual(4, tree.Root.Key);
            Assert.AreEqual(0, tree.Root.Balance);

            #endregion

            #region 1. level

            Assert.IsNotNull(tree.Root.Left);
            Assert.AreEqual(2, tree.Root.Left.Key);
            Assert.AreEqual(0, tree.Root.Left.Balance);

            Assert.IsNotNull(tree.Root.Right);
            Assert.AreEqual(6, tree.Root.Right.Key);
            Assert.AreEqual(0, tree.Root.Right.Balance);

            #endregion

            #region 2. level

            Assert.IsNotNull(tree.Root.Left.Left);
            Assert.AreEqual(1, tree.Root.Left.Left.Key);
            Assert.AreEqual(0, tree.Root.Left.Left.Balance);

            Assert.IsNotNull(tree.Root.Left.Right);
            Assert.AreEqual(3, tree.Root.Left.Right.Key);
            Assert.AreEqual(0, tree.Root.Left.Right.Balance);

            Assert.IsNotNull(tree.Root.Right.Left);
            Assert.AreEqual(5, tree.Root.Right.Left.Key);
            Assert.AreEqual(0, tree.Root.Right.Left.Balance);

            Assert.IsNotNull(tree.Root.Right.Right);
            Assert.AreEqual(7, tree.Root.Right.Right.Key);
            Assert.AreEqual(0, tree.Root.Right.Right.Balance);

            #endregion
        }
Beispiel #13
0
        private bool TestDelete(int count)
        {
            Console.WriteLine("Starting delete test...");
            var random = new Random(50);

            HelpList.Sort((i1, i2) => i1 - i2);
            for (int i = 0; i < count; i++)
            {
                var index = random.Next(0, HelpList.Count - 1);
                var value = HelpList[index];
                HelpList.Remove(value);
                if (!AvlTree.Contains(value))
                {
                    Console.WriteLine($"Tree does not contain that value {value}");
                    return(false);
                }
                var deletedValue = AvlTree.Delete(value);
                if (value != deletedValue)
                {
                    Console.WriteLine($"Wrong data deleted... should: {value}, was: {deletedValue}");
                    return(false);
                }

                if (AvlTree.Contains(value))
                {
                    Console.WriteLine($"Tree still contains removed value {value}");
                    return(false);
                }

                if (i % 100 == 0)
                {
                    if (!InOrderTest(false))
                    {
                        Console.WriteLine("In order test failed during deletion");
                        return(false);
                    }
                }
            }

            if (!CountTest(true))
            {
                Console.WriteLine("Count test failed right after deletion");
                return(false);
            }

            if (!InOrderTest(true))
            {
                Console.WriteLine("In order test failed right after deletion");
                return(false);
            }

            Console.WriteLine("delete test successful");
            return(true);
        }
Beispiel #14
0
        public void Delete_Single()
        {
            const int insertValue = 1;

            IBinarySearchTree<int> tree = new AvlTree<int>();
            tree.Insert(insertValue);

            Assert.IsTrue(tree.Find(insertValue));
            Assert.IsTrue(tree.Delete(insertValue));
            Assert.IsFalse(tree.Find(insertValue));
        }
Beispiel #15
0
 public void RemoveTablet(ReadOnlySpan <byte> partitionKeyStart)
 {
     _lock.EnterWriteLock();
     try
     {
         _cache.Delete(partitionKeyStart);
     }
     finally
     {
         _lock.ExitWriteLock();
     }
 }
Beispiel #16
0
        public void DeleteTest()
        {
            AvlTree <int> tree = new AvlTree <int>();

            tree.Append(20);
            tree.Append(30);
            tree.Append(40);
            tree.Append(0);
            tree.Append(10);
            tree.Delete(40);
            Assert.AreEqual(10, tree.GetRoot().GetValue());
            Assert.AreEqual(30, tree.GetRoot().GetRight().GetValue());
            Assert.DoesNotThrow(delegate
            {
                tree.Delete(40);
            });
            tree.Delete(0);
            Assert.AreEqual(20, tree.GetRoot().GetValue());
            Assert.AreEqual(30, tree.GetRoot().GetRight().GetValue());
            Assert.AreEqual(10, tree.GetRoot().GetLeft().GetValue());
        }
Beispiel #17
0
        public void Delete_EntireArray()
        {
            int[] data = { 5, 2, 6, 3, 1, 4 };
            int[] expected = { 1, 2, 3, 4, 5, 6 };
            IBinarySearchTree<int> tree = new AvlTree<int>();

            foreach (int value in data)
                tree.Insert(value);

            int[] actualArray = tree.ToArray();
            CollectionAssert.AreEqual(expected, actualArray);
            Assert.AreEqual(expected.Length, tree.Size);
            Assert.IsTrue(tree.Delete(1));
            Assert.IsFalse(tree.Find(1));
            Assert.IsTrue(tree.Delete(2));
            Assert.IsFalse(tree.Find(2));
            Assert.IsTrue(tree.Delete(3));
            Assert.IsFalse(tree.Find(3));
            Assert.IsTrue(tree.Delete(4));
            Assert.IsFalse(tree.Find(4));
            Assert.IsTrue(tree.Delete(5));
            Assert.IsFalse(tree.Find(5));
            Assert.IsTrue(tree.Delete(6));
            Assert.IsFalse(tree.Find(6));
            Assert.AreEqual(0, tree.Size);
        }
Beispiel #18
0
        public void InsertAndDelete()
        {
            var tree = new AvlTree <int>();

            tree.Insert(10);
            Assert.IsTrue(tree.ContainsKey(10));

            tree.Insert(20);
            Assert.IsTrue(tree.ContainsKey(20));

            tree.Insert(30);
            Assert.IsTrue(tree.ContainsKey(30));

            tree.Delete(30);
            Assert.IsFalse(tree.ContainsKey(30));
        }
Beispiel #19
0
        public void DeletionTest()
        {
            Console.WriteLine("AVLTree Deletion Test is running...");
            var avlTree = new AvlTree <int>();
            var rnd     = new Random();
            //Generate 20 random integer
            var testData = new int[20000];

            for (var i = 0; i < 20000; i++)
            {
                testData[i] = rnd.Next(-20000, 20000);
            }
            var counter     = testData.Select(e => avlTree.Insert(e)).Count(res => res);
            var inOrderList = avlTree.InOrderTraverse().ToList();

            Assert.AreEqual(inOrderList.Count, counter);
            CallTreeValidation(avlTree.Root);
            _ = TreeHeightVerification(avlTree.Root);
            BalancingFactorVerification(avlTree.Root);
            //Now attempt to delete one node at a time
            //and verify tree validity after each deletion
            foreach (var e in testData)
            {
                var res = avlTree.Delete(e);
                if (res)
                {
                    counter--;
                    Assert.AreEqual(counter, avlTree.TreeSize);
                    Assert.AreEqual(avlTree.InOrderTraverse().Count(), avlTree.TreeSize);
                    Assert.IsFalse(avlTree.TryFind(e).Found);
                }

                if (avlTree.Root == null)
                {
                    continue;
                }
                CallTreeValidation(avlTree.Root);
                _ = TreeHeightVerification(avlTree.Root);
                BalancingFactorVerification(avlTree.Root);
            }

            Assert.IsNull(avlTree.Root);
            Assert.AreEqual(0, avlTree.TreeSize);
            Console.WriteLine("AVLTree Deletion Test has finished running...");
        }
Beispiel #20
0
        static void Main(string[] args)
        {
            AvlTree AVL = new AvlTree();

            AVL.Insert(5);
            AVL.Insert(4);
            AVL.Insert(3);
            AVL.Insert(2);
            AVL.Insert(1);
            AVL.PreOrder();

            AVL.Delete(3);
            AVL.Delete(1);
            AVL.PreOrder();

            AVL.Clear();

            AVL.Insert(1);
            AVL.Insert(2);
            AVL.Insert(3);
            AVL.Insert(4);
            AVL.Insert(5);
            AVL.PreOrder();

            AVL.Delete(5);
            AVL.Delete(1);
            AVL.Delete(3);
            AVL.PreOrder();

            AVL.Clear();

            AVL.Insert(1);
            AVL.Insert(4);
            AVL.Insert(2);
            AVL.Insert(3);
            AVL.Insert(9999);
            AVL.Insert(5);
            AVL.Insert(12);
            AVL.Insert(654);
            AVL.Insert(21);
            AVL.Insert(63);
            AVL.PreOrder();

            AVL.Delete(5);
            AVL.Delete(1);
            AVL.Delete(654);
            AVL.Insert(111);
            AVL.Delete(63);
            AVL.Delete(4);
            AVL.PreOrder();
            AVL.Delete(21);
            AVL.Insert(435);
            AVL.PreOrder();
            AVL.Delete(12);
            AVL.Delete(41);
            AVL.PreOrder();

            Console.ReadKey();
            AVL.Clear();
        }
Beispiel #21
0
        public void Delete_Unsorted_Check()
        {
            int[] data = { 5, 2, 6, 3, 1, 4 };
            int[] expected_sorted = {1, 2, 3, 4, 5, 6};
            int[] expected_delete3 = {1, 2, 4, 5, 6};
            int[] expected_delete2 = {1, 4, 5, 6};
            int[] expected_delete6 = {1, 4, 5};
            int[] expected_delete1 = {4, 5};

            IBinarySearchTree<int> tree = new AvlTree<int>();

            foreach (int value in data)
                tree.Insert(value);

            int[] actualArray = tree.ToArray();

            CollectionAssert.AreEqual(expected_sorted, actualArray);

            Assert.IsTrue(tree.Delete(3));
            CollectionAssert.AreEqual(expected_delete3, tree.ToArray());

            Assert.IsTrue(tree.Delete(2));
            CollectionAssert.AreEqual(expected_delete2, tree.ToArray());

            Assert.IsTrue(tree.Delete(6));
            CollectionAssert.AreEqual(expected_delete6, tree.ToArray());

            Assert.IsTrue(tree.Delete(1));
            CollectionAssert.AreEqual(expected_delete1, tree.ToArray());
        }
Beispiel #22
0
        private bool RandomRemoveInsertTest(int rounds)
        {
            Console.WriteLine("Starting random test...");
            var randomSeed         = new Random();
            var randomCount        = new Random(randomSeed.Next());
            var randomInsOrDel     = new Random(randomSeed.Next());
            var randomInsertNumber = new Random(randomSeed.Next());
            var randomDeleteNumber = new Random(randomSeed.Next());
            //zistit kolko krat ideme robit mazanie/vkladanie
            var help = 0;

            while (help < rounds)
            {
                var count    = randomCount.Next(100, 500);
                var insOrDel = randomInsOrDel.NextDouble(); //0 insert, 1 delete
                for (var i = 0; i < count; i++)
                {
                    if (AvlTree.IsEmpty)
                    {
                        insOrDel = 0.2; //ak je prazdny nech radsej insertuje
                    }
                    if (insOrDel < 0.5)
                    {
                        var number = randomInsertNumber.Next();
                        if (number == 0 || AvlTree.Contains(number))
                        {
                            continue;
                        }
                        AvlTree.Insert(number);
                        HelpList.Add(number);
                    }
                    else
                    {
                        var index = randomDeleteNumber.Next(0, HelpList.Count - 1);
                        var value = HelpList[index];
                        HelpList.Remove(value);
                        if (!AvlTree.Contains(value))
                        {
                            Console.WriteLine($"Tree does not contain that value {value}");
                            return(false);
                        }
                        var deletedValue = AvlTree.Delete(value);
                        if (value != deletedValue)
                        {
                            Console.WriteLine($"Wrong data deleted... should: {value}, was: {deletedValue}");
                            return(false);
                        }

                        if (AvlTree.Contains(value))
                        {
                            Console.WriteLine($"Tree still contains removed value {value}");
                            return(false);
                        }
                    }
                }
                if (!CountTest(false))
                {
                    Console.WriteLine("Count test failed during random test");
                    return(false);
                }

                if (!InOrderTest(false))
                {
                    Console.WriteLine("In order test failed during random test");
                    return(false);
                }

                help++;
            }


            if (!CountTest(true))
            {
                Console.WriteLine("Count test failed right after random test");
                return(false);
            }
            if (!InOrderTest(true))
            {
                Console.WriteLine("In order test failed right after random test");
                return(false);
            }

            Console.WriteLine("Random test successful");
            return(true);
        }
Beispiel #23
0
        public static IEnumerable <Double2[]> PartitionToMonotone(Double2[][] contours)
        {
            // Sort all vertices using their default comparison
            var vertexSet = new SortedSet <Vertex>();

            // Add the vertices to the list
            foreach (var poly in contours)
            {
                // Skip "line" contours
                if (poly.Length < 3)
                {
                    continue;
                }

                // To make the circular list
                Vertex first = null, last = null;

                for (int i = 0; i < poly.Length; i++)
                {
                    var prev = poly[(i == 0 ? poly.Length : i) - 1];
                    var cur  = poly[i];
                    var next = poly[i == poly.Length - 1 ? 0 : i + 1];

                    var vtx = new Vertex(prev, cur, next);

                    // Build the circular list
                    if (last != null)
                    {
                        vtx.PreviousEdge = last.NextEdge;
                        vtx.IncomingEdges.Insert(vtx.PreviousEdge, vtx.PreviousEdge);

                        vtx.NextEdge.Previous = vtx.PreviousEdge;
                        vtx.PreviousEdge.Next = vtx.NextEdge;
                    }

                    // Add the vertex
                    vertexSet.Add(vtx);

                    last = vtx;
                    if (first == null)
                    {
                        first = last;
                    }
                }

                // Close the loop
                first.PreviousEdge = last.NextEdge;
                first.IncomingEdges.Insert(first.PreviousEdge, first.PreviousEdge);

                first.NextEdge.Previous = first.PreviousEdge;
                first.PreviousEdge.Next = first.NextEdge;
            }

            // Put all vertices into an array, and swipe from up to down
            var vertices = vertexSet.ToArray();

            Array.Reverse(vertices);

            // Put the edges here
            var edges = new AvlTree <Edge, Edge>();

            void SplitDiagonal(Vertex v1, Vertex v2)
            {
                var e12 = new Edge(v1.Current, v2.Current);
                var e21 = new Edge(v2.Current, v1.Current);

                v1.SearchOutgoingEdges(e12, out var e1lo, out var e1ro);
                v1.SearchIncomingEdges(e21, out var e1li, out var e1ri);

                v2.SearchOutgoingEdges(e21, out var e2lo, out var e2ro);
                v2.SearchIncomingEdges(e12, out var e2li, out var e2ri);

                e1ri.Next     = e12;
                e2lo.Previous = e12;

                e2ri.Next     = e21;
                e1lo.Previous = e21;

                e12.Next     = e2lo;
                e12.Previous = e1ri;

                e21.Next     = e1lo;
                e21.Previous = e2ri;

                v1.OutgoingEdges.Insert(e12, e12);
                v1.IncomingEdges.Insert(e21, e21);

                v2.OutgoingEdges.Insert(e21, e21);
                v2.IncomingEdges.Insert(e12, e12);

                // Sanity check
                var eds = new HashSet <Edge>(ReferenceEqualityComparer.Default);

                foreach (var e in e12.CyclicalSequence)
                {
                    if (!eds.Add(e))
                    {
                        throw new Exception("Problematic edge sequence!");
                    }
                }

                eds.Clear();
                foreach (var e in e21.CyclicalSequence)
                {
                    if (!eds.Add(e))
                    {
                        throw new Exception("Problematic edge sequence!");
                    }
                }
            }

            Edge SearchEdge(Vertex v)
            {
                edges.SearchLeftRight(new Edge(v.Current, v.Current), out var eleft, out var eright);
                return(eleft);
            }

            // Act according with the type of the vertex
            foreach (var v in vertices)
            {
                switch (v.Type)
                {
                case VertexType.Start:
                case VertexType.Split:
                    if (v.Type == VertexType.Split)
                    {
                        var edgeLeft = SearchEdge(v);
                        SplitDiagonal(v, edgeLeft.Helper);
                        edgeLeft.Helper = v;
                    }

                    v.NextEdge.Helper = v;
                    edges.Insert(v.NextEdge, v.NextEdge);
                    break;

                case VertexType.End:
                case VertexType.Merge:
                    if (v.PreviousEdge.Helper.Type == VertexType.Merge)
                    {
                        SplitDiagonal(v, v.PreviousEdge.Helper);
                    }
                    edges.Delete(v.PreviousEdge);

                    if (v.Type == VertexType.Merge)
                    {
                        var edgeLeft = SearchEdge(v);
                        if (edgeLeft.Helper.Type == VertexType.Merge)
                        {
                            SplitDiagonal(v, edgeLeft.Helper);
                        }
                        edgeLeft.Helper = v;
                    }
                    break;

                case VertexType.RegularLeft:
                    if (v.PreviousEdge.Helper.Type == VertexType.Merge)
                    {
                        SplitDiagonal(v, v.PreviousEdge.Helper);
                    }
                    edges.Delete(v.PreviousEdge);

                    v.NextEdge.Helper = v;
                    edges.Insert(v.NextEdge, v.NextEdge);
                    break;

                case VertexType.RegularRight:
                    var eleft = SearchEdge(v);
                    if (eleft.Helper.Type == VertexType.Merge)
                    {
                        SplitDiagonal(v, eleft.Helper);
                    }
                    eleft.Helper = v;
                    break;

                default:
                    break;
                }
            }

            // Collect all edges so we can pick the Y-monotone polygons
            var allEdges     = new HashSet <Edge>(ReferenceEqualityComparer.Default);
            var primaryEdges = new List <Edge>();

            foreach (var v in vertices)
            {
                var e = v.NextEdge;

                var eds = new HashSet <Edge>(ReferenceEqualityComparer.Default);
                int i   = 0;
                foreach (var u in e.CyclicalSequence)
                {
                    if (!eds.Add(u))
                    {
                        throw new Exception("Problematic edge sequence! " + i);
                    }
                    i++;
                }

                if (allEdges.Contains(e))
                {
                    continue;
                }

                primaryEdges.Add(e);
                foreach (var u in e.CyclicalSequence)
                {
                    allEdges.Add(u);
                }
            }

            // Now, collect the formed polygons
            return(primaryEdges.Select(edge => edge.CyclicalSequence.Select(e => e.A).ToArray()));
        }