// Построение идеально сбалансированного дерева
        public static PointTree IdealTree(int size, PointTree p)
        {
            PointTree r;
            int       nl, nr;

            if (size == 0)
            {
                p = null;
                return(p);
            }
            nl = size / 2;
            nr = size - nl - 1;

            r = new PointTree();

            int typeclass = random.Next(1, 4);

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

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

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

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

            r.left  = IdealTree(nl, r.left);
            r.right = IdealTree(nr, r.right);
            return(r);
        }
        // Добавление элемента d в дерево поиска
        public static PointTree Add(PointTree root, Place place)
        {
            PointTree p = root; // корень дерева
            PointTree r = null;

            // Флаг для проверки существования элемента d в дереве
            bool ok = false;

            while (p != null && !ok)
            {
                r = p;
                // элемент уже существует
                if (place == p.data)
                {
                    ok = true;
                }
                else
                {
                    if (place < p.data)
                    {
                        // Пойти в левое поддерево
                        p = p.left;
                    }
                    else
                    {
                        // Пойти в правое поддерево
                        p = p.right;
                    }
                }
            }

            // Если найдено, то не добавляем
            if (ok)
            {
                return(p);
            }

            // создаем узел с выделением памяти
            PointTree NewPoint = new PointTree(place);

            // Если place < r.key, то добавляем его в левое поддерево
            if (place < r.data)
            {
                r.left = NewPoint;
            }
            // если place >r.key, то добавляем его в правое поддерево
            else
            {
                r.right = NewPoint;
            }

            return(r);
        }
 // Рекурсивная функция для печати дерева по уровням с обходом слева направо
 public static void ShowTree(PointTree p, int l)
 {
     if (p != null)
     {
         ShowTree(p.left, l + 3); //переход к левому поддереву
                                  //формирование отступа
         for (int i = 0; i < l; i++)
         {
             Console.Write(" ");
         }
         Console.WriteLine(p.ToString()); //печать узла
         ShowTree(p.right, l + 3);        //переход к правому поддереву
     }
 }
        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 bool IndexOf(Place place)
        {
            bool index = false;

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

            if (point.data == place)
            {
                return(true);
            }

            if (point.left != null)
            {
                index = point.left.IndexOf(place);
            }

            if (!index && point.right != null)
            {
                index = point.right.IndexOf(place);
            }

            return(index);
        }
 // Конструктор с параметрам
 public PointTree(Place place)
 {
     data  = place;
     left  = null;
     right = null;
 }
 // Конструктор без параметров
 public PointTree()
 {
     data  = null;
     left  = null;
     right = null;
 }
        // Формирование первого элемента дерева
        public static PointTree first(Place place)
        {
            PointTree p = new PointTree(place);

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