// Конструктор с параметром
 public PointTwo(Place place)
 {
     position = 0;
     data     = place;
     next     = null;
     pred     = null;
 }
        // Метод для поиска элемента по значению
        public int IndexOf(Place place)
        {
            int  index = 0;
            bool check = false;

            PointTwo point = (PointTwo)this.Clone();

            while (point.pred != null)
            {
                point = point.pred;
            }

            while (point.next != null && !check)
            {
                if (point.data == place)
                {
                    check = true;
                }

                index++;
                point = point.next;
            }

            if (!check)
            {
                return(-1);
            }

            return(index);
        }
        // УДаление элементов с четными номерами
        public static PointTwo RemoveEvenElems(PointTwo beg)
        {
            if (beg == null) // Пустой список
            {
                Console.WriteLine("Error! The List is empty");
                return(null);
            }

            while (beg.pred != null)
            {
                beg = beg.pred;
            }

            int count = 1;

            while (beg.next != null)
            {
                beg = beg.next;
                count++;
            }

            if (count % 2 == 1)
            {
                beg      = beg.pred;
                beg.next = null;
                count--;
            }

            PointTwo p = beg;

            for (int i = 0; i < count / 2 - 1; i++)
            {
                p      = p.pred.pred;
                p.next = p.next.next;
            }

            p.pred = null;
            return(p);
        }
        static void Main(string[] args)
        {
            Console.WriteLine("Часть 1");

            Console.WriteLine("Работа с одноправленным списоком");
            PointOne one = new PointOne();

            one = PointOne.MakeList(10);
            Console.WriteLine("Одноправленный список");
            PointOne.ShowList(one);
            Console.WriteLine("Добавление в конец");
            one = PointOne.MakeListToEnd(7);
            Console.WriteLine("Одноправленный список");
            PointOne.ShowList(one);

            Console.WriteLine();

            Console.WriteLine("Работа с двунаправленным списоком");
            PointTwo two = new PointTwo();

            two = PointTwo.MakeList(10);
            Console.WriteLine("Двунаправленный список");
            PointTwo.ShowList(two);
            Console.WriteLine("Удаление четных элементов");
            two = PointTwo.RemoveEvenElems(two);
            Console.WriteLine("Двунаправленный список");
            PointTwo.ShowList(two);

            Console.WriteLine();

            Console.WriteLine("Работа с деревоом");
            PointTree tree = new PointTree();

            Console.WriteLine("Создание сбалансированного дерева");
            tree = PointTree.IdealTree(10, tree);
            Console.WriteLine("Дерево");
            PointTree.ShowTree(tree, 200);
        }
        // Печать двунаправленного списка
        public static void ShowList(PointTwo beg)
        {
            // проверка наличия элементов в списке
            if (beg == null)
            {
                Console.WriteLine("The List is empty");
                return;
            }
            PointTwo p = beg;

            // Идем к левому краю списка
            while (p.pred != null)
            {
                p = p.pred;
            }

            while (p != null)
            {
                Console.Write(p.ToString());
                p = p.next; //переход к следующему элементу
            }
            Console.WriteLine();
        }
 // Конструктор без параметров
 public PointTwo()
 {
     data = null;
     next = null;
     pred = null;
 }
        // Добавление элементов в начало двунаправленного списка
        public static PointTwo MakeList(int size) //добавление в начало
        {
            int typeclass = random.Next(1, 4);

            PointTwo beg = new PointTwo();

            switch (typeclass)
            {
            case 1:
            {
                Place place = new Place();
                place.RandomCreate();
                Console.WriteLine("The element {0} is adding...", place.ToString());
                beg = MakePoint(place);
            }
            break;

            case 2:
            {
                Region region = new Region();
                region.RandomCreate();
                Console.WriteLine("The element {0} is adding...", region.ToString());
                beg = MakePoint(region);
            }
            break;

            case 3:
            {
                City city = new City();
                city.RandomCreate();
                Console.WriteLine("The element {0} is adding...", city.ToString());
                beg = MakePoint(city);
            }
            break;

            case 4:
            {
                Megapolis megapolis = new Megapolis();
                megapolis.RandomCreate();
                Console.WriteLine("The element {0} is adding...", megapolis.ToString());
                beg = MakePoint(megapolis);
            }
            break;
            }

            for (int i = 1; i < size; i++)
            {
                typeclass = random.Next(1, 4);
                PointTwo point = new PointTwo();

                switch (typeclass)
                {
                case 1:
                {
                    Place place = new Place();
                    place.RandomCreate();
                    Console.WriteLine("The element {0} is adding...", place.ToString());
                    point = MakePoint(place);
                }
                break;

                case 2:
                {
                    Region region = new Region();
                    region.RandomCreate();
                    Console.WriteLine("The element {0} is adding...", region.ToString());
                    point = MakePoint(region);
                }
                break;

                case 3:
                {
                    City city = new City();
                    city.RandomCreate();
                    Console.WriteLine("The element {0} is adding...", city.ToString());
                    point = MakePoint(city);
                }
                break;

                case 4:
                {
                    Megapolis megapolis = new Megapolis();
                    megapolis.RandomCreate();
                    Console.WriteLine("The element {0} is adding...", megapolis.ToString());
                    point = MakePoint(megapolis);
                }
                break;
                }
                point.next = beg;
                beg.pred   = point;
                beg        = point;
            }
            return(beg);
        }
        // Создание элемента двунаправленного списка
        public static PointTwo MakePoint(Place place)
        {
            PointTwo point = new PointTwo(place);

            return(point);
        }
 // Полное удаление коллекции
 public void Clear()
 {
     data = null;
     next = null;
     pred = null;
 }