powered by simpleCommunicator - 2.0.52     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Рекурсия - возвращает неправильное значение в некоторых случаях
24 сообщений из 24, страница 1 из 1
Рекурсия - возвращает неправильное значение в некоторых случаях
    #39440480
Фотография mraklbrw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый вечер.

Есть функция
Код: c#
1.
public void FindLastRightNode(BinaryNode node, ref BinaryNode result_node)



Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
public void FindLastRightNode(BinaryNode node, ref BinaryNode result_node)
        {
            // На вход подаём вершину, для которой нужно найти самого нижнего правого потомка

            if (node.Right == null)
            {
                result_node = node;
                return;
            }
            else
                FindLastRightNode(node.Right, ref result_node);
        }




Класс BinaryNode

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
public class BinaryNode
    {
        public BinaryNode Left { get; set; } // Левое поддерево
        public BinaryNode Right { get; set; } // Правое поддеревго
        public int value { get; set; } // Числовое значение вершины
        public int level { get; set; } // Уровень дерева, на котором находится вершина

        public BinaryNode(int value)
        {
            // Констркутор вершины
            // На вход даём числовое значение вершины

            this.value = value;
            Left = null;
            Right = null;
        }

        public int GetLevel()
        {
            return level;
        }
    }





Она должна искать последний(самый нижний) правый потомок вершины.
В случаях, если потомков несколько, всё нормально.
Если потомок 1 - возвращает не его, а саму вершину, поданную на вход функции.

Функция FindNode работает правильно.
...
Рейтинг: 0 / 0
Рекурсия - возвращает неправильное значение в некоторых случаях
    #39440497
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mraklbrwФункция FindNode работает правильно.Что дает нам эта информация?

Зачем тут ref-параметр, при том, что функция возвращает void? В чем проблема сам узел возвращать?

Кроме того, кейс совершенно непонятен. Приведите простой пример, который неверно работает.
...
Рейтинг: 0 / 0
Рекурсия - возвращает неправильное значение в некоторых случаях
    #39440498
Фотография mraklbrw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
private void button1_Click(object sender, EventArgs e)
        {
            string nodes_str = textBox1.Text; // Получаем вершины из поля с вершинами

            // Проверка на правильность введённых значений
            if (!CheckString(nodes_str))
                return;

            // Парсим числа из строки в список вершин
            List<int> nodes = new List<int>();
            int[] nodes_temp = nodes_str.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).Select(x => Convert.ToInt32(x)).ToArray();
            nodes.AddRange(nodes_temp);

            BinaryNode root_bn = new BinaryNode(nodes[0]); // Определяем корневую вершину
            nodes.RemoveAt(0); // Убираем из списка вершин первую-корневую вершину
            BinaryTree bt = new BinaryTree(root_bn); // Создаём бинарное дерево

            for (int i = 0; i < nodes.Count; i++)
            {
                bt.AddElement(nodes[i]);
            }

            for (int j = 0; j < nodes.Count; j++) // Проверочный цикл
            {
                listBox1.Items.Add(Convert.ToString(nodes[j]));
            }

            listBox1.Items.Add(" ");

            

            // ПРОВЕРКА РЕКУРСИИ

            BinaryNode tempN = new BinaryNode(5555);

            bt.FindNode(root_bn, 4, ref tempN);

            BinaryNode tempN2 = new BinaryNode(5556);

            bt.FindLastRightNode(tempN, ref tempN2);

            listBox1.Items.Add(Convert.ToString(tempN2.value));

            




            }

        }




В листбокс добавляем 2 3 5 9 1 0 4 7 - т.е. это вершины нашего дерева.
При bt.FindNode(root_bn, 3, ref tempN); выдаёт 9, всё верно.
Но при bt.FindNode(root_bn, 4, ref tempN); выдаёт 4, а должно 7.
...
Рейтинг: 0 / 0
Рекурсия - возвращает неправильное значение в некоторых случаях
    #39440501
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mraklbrw,

Что мешало сделать так?

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
public class BinaryNode
    {
        public BinaryNode Left { get; set; } // Левое поддерево
        public BinaryNode Right { get; set; } // Правое поддеревго
        public int value { get; set; } // Числовое значение вершины
        public int level { get; set; } // Уровень дерева, на котором находится вершина

        public BinaryNode(int value)
        {
            // Констркутор вершины
            // На вход даём числовое значение вершины

            this.value = value;
            Left = null;
            Right = null;
        }

        public int GetLevel()
        {
            return level;
        }

        public BinaryNode GetLastRight()
        {
           return this.Right == null ? this : this.Right.GetLastRight();
        }
    }



Вариант с ref убог до самой крайной крайности, хуже уже трудно что-то придумать.

И рекурсия по сути тут тоже не к месту, так как легко словить переполнение стека.

Вот так оптимально:

Код: c#
1.
2.
3.
4.
5.
6.
        public BinaryNode GetLastRight()
        {
           var node = this;
           while(node.Right != null) node = node.Right;
           return node;
        }
...
Рейтинг: 0 / 0
Рекурсия - возвращает неправильное значение в некоторых случаях
    #39440502
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mraklbrwВ листбокс добавляем 2 3 5 9 1 0 4 7 - т.е. это вершины нашего дерева.
При bt.FindNode(root_bn, 3, ref tempN); выдаёт 9, всё верно.
Но при bt.FindNode(root_bn, 4, ref tempN); выдаёт 4, а должно 7.

Где код FindNode? И при чём тут FindNode, когда речь шла о FindLastRightNode?
...
Рейтинг: 0 / 0
Рекурсия - возвращает неправильное значение в некоторых случаях
    #39440503
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вы можете дать РАБОЧИЙ автономный пример? Который можно просто запустить и проверить. А не размышлять, что же скрывается за CheckString например и куда и в каком виде совать входные параметры.

Никто не будет смотреть ваши простыни кода, как, например, в вашем первом вопросе.

Если у вас нету опыта общения на форумах, предлагаю почитать на досуге это: 16726098
...
Рейтинг: 0 / 0
Рекурсия - возвращает неправильное значение в некоторых случаях
    #39440518
Фотография mraklbrw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Полный код BinaryTree

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace BinaryTree
{
        public class BinaryNode
    {
        public BinaryNode Left { get; set; } // Левое поддерево
        public BinaryNode Right { get; set; } // Правое поддеревго
        public int value { get; set; } // Числовое значение вершины
        public int level { get; set; } // Уровень дерева, на котором находится вершина

        public BinaryNode(int value)
        {
            // Констркутор вершины
            // На вход даём числовое значение вершины

            this.value = value;
            Left = null;
            Right = null;
        }

        public int GetLevel()
        {
            return level;
        }

        public BinaryNode GetLastRight()
        {
            return this.Right == null ? this : this.Right.GetLastRight();
        }
    }
        
    public class BinaryTree
    {
        public BinaryNode node_root;
        private int count;
        private int min_value;
        private int max_value;

        public BinaryTree(BinaryNode root_node)
        {
            // Констркутор бинарного дерева
            // На вход даём корневую вершину
            this.node_root = root_node;
            this.count = 1; // Поправка на корневую вершину
        }

        public int GetNodesCount()
        {
            return count;
        }

        public int GetMinValue()
        {
            return min_value;
        }

        public int GetMaxValue()
        {
            return max_value;
        }

        public void AddElement(int new_value)
        {
            if (new_value > max_value)
                max_value = new_value;
            else if (new_value < min_value)
                min_value = new_value;

            int level = 0;

            if (node_root == null)
            {
                node_root = new BinaryNode(new_value);
                node_root.level = level;
                count++;
                return;
            }
            else
                InsertElement(node_root, new_value, level);
        }        

        public void InsertElement(BinaryNode node, int new_value, int level)
        {
            level++;
            if (new_value > node.value) // Новый элемент > элемент
            {
                // Проверяем правую ветвь
                if (node.Right == null)
                {
                    node.Right = new BinaryNode(new_value);
                    node.Right.level = level + 1;
                    count++;
                }
                else
                    InsertElement(node.Right, new_value, level);
            }
            else // Новый элемент < элемент
            {
                // Проверяем левую ветвь
                if (node.Left == null)
                {
                    node.Left = new BinaryNode(new_value);
                    node.Left.level = level + 1;
                    count++;
                }
                else
                    InsertElement(node.Left, new_value, level);
            }
        }

        public bool FindValue(BinaryNode node, int search_value)
        {
            // На вход подаём корневую вершину

            if (search_value == node.value)
                return true;
            else if (search_value < node.value)
            {
                if (node.Left == null)
                    return false;
                else
                    return FindValue(node.Left, search_value);
            }
            else if (search_value > node.value)
            {
                if (node.Right == null)
                    return false;
                else
                    return FindValue(node.Right, search_value);
            }

            return false;
        }

        public bool FindNode(BinaryNode node, int search_value, ref BinaryNode result_node)
        {
            // На вход подаём корневую вершину

            if (search_value == node.value)
            {
                result_node = node;
                return true;
            }
            else if (search_value < node.value)
            {
                if (node.Left == null)
                    return false;
                else
                    return FindNode(node.Left, search_value, ref result_node);
            }
            else if (search_value > node.value)
            {
                if (node.Right == null)
                    return false;

                else
                    return FindNode(node.Right, search_value, ref result_node);
            }

            return false;
        }

        public bool FindNodeParent(BinaryNode node, int search_value, ref BinaryNode result_node)
        {
            // На вход подаём корневую вершину

            if (node.Left != null)
            {
                if (node.Left.value == search_value)
                {
                    result_node = node;
                    return true;
                }
                if (FindNodeParent(node.Left, search_value, ref result_node))
                    return true;
            }
            if (node.Right != null)
            {
                if (node.Right.value == search_value)
                {
                    result_node = node;
                    return true;
                }
                if (FindNodeParent(node.Right, search_value, ref result_node))
                    return true;
            }

            return false;
        }

        public void TraversePreorder(BinaryNode node) // Прямой обход дерева
        {
            // На вход подаём корневую вершину

            // Здесь можем выполнять какие-нибудь действия

            MessageBox.Show(Convert.ToString(node.value));

            if (node.Left != null)
                TraversePreorder(node.Left);
            if (node.Right != null)
                TraversePreorder(node.Right);
        }

        public void TraverseInorder(BinaryNode node) // Симметричный обход дерева
        {
            // На вход подаём корневую вершину

            if (node.Left != null)
                TraversePreorder(node.Left);

            // Здесь можем выполнять какие-нибудь действия

            MessageBox.Show(Convert.ToString(node.value));

            if (node.Right != null)
                TraversePreorder(node.Right);
        }

        public void TraversePostorder(BinaryNode node) // Обход дерева в обратном порядке
        {
            // На вход подаём корневую вершину

            if (node.Left != null)
                TraversePreorder(node.Left);
            if (node.Right != null)
                TraversePreorder(node.Right);

            // Здесь можем выполнять какие-нибудь действия

            MessageBox.Show(Convert.ToString(node.value));
        }

        public void TraverseDepth(BinaryNode node) // Обход дерева в ширину
        {
            // На вход подаём корневую вершину

            Queue<BinaryNode> children = new Queue<BinaryNode>();

            children.Enqueue(node); // Помещаем корень в очередь

            while(children.Count != 0) // Пока очередь не пуста
            {
                BinaryNode nodeT = children.Dequeue(); // Берём следующую вершину из очереди

                // Здесь можем выполнять какие-нибудь действия

                MessageBox.Show(Convert.ToString(nodeT.value));

                if (nodeT.Left != null)
                    children.Enqueue(nodeT.Left);
                if (nodeT.Right != null)
                    children.Enqueue(nodeT.Right);
            }
        }



        public bool RemoveNode(int value)
        {
            BinaryNode nodeT = new BinaryNode(6666);

            if (!FindNode(node_root, value, ref nodeT)) // Не найдена вершина для удаления
                return false;
            else
            {
                if (nodeT.Left == null && nodeT.Right == null) // Терминальная вершина
                {
                    BinaryNode nodeT2 = new BinaryNode(7777);

                    FindNodeParent(node_root, nodeT.value, ref nodeT2); // Ищем родительскую вершину для удаляемой вершины

                    if (nodeT2.Left == nodeT)
                    {
                        nodeT2.Left = null;
                        count--; // Уменьшаем счётчик количества вершин в дереве
                        return true;
                    }
                    else
                    {
                        nodeT2.Right = null;
                        count--; // Уменьшаем счётчик количества вершин в дереве
                        return true;
                    }
                }
                else if (nodeT.Left != null && nodeT.Right == null) // Имеет только левого потомка
                {
                    BinaryNode nodeT3 = new BinaryNode(8888);
                    FindNodeParent(node_root, nodeT.value, ref nodeT3); // Ищем родительскую вершину для удаляемой вершины
                    nodeT3.Left = nodeT.Left;
                    count--; // Уменьшаем счётчик количества вершин в дереве
                    return true;
                }
                else if (nodeT.Left == null && nodeT.Right != null) // Имеет только правого потомка
                {
                    BinaryNode nodeT4 = new BinaryNode(9000);
                    FindNodeParent(node_root, nodeT.value, ref nodeT4); // Ищем родительскую вершину для удаляемой вершины
                    nodeT4.Right = nodeT.Right;
                    count--; // Уменьшаем счётчик количества вершин в дереве
                    return true;
                }
                else if (nodeT.Left != null && nodeT.Right != null) // Имеет левого и правого потомка
                {
                    BinaryNode nodeT5 = new BinaryNode(9001);
                    FindNodeParent(node_root, nodeT.value, ref nodeT5); // Ищем родительскую вершину для удаляемой вершины

                    if (nodeT.Left.Right == null) // Левый потомок не имеет правого потомка
                    {
                        BinaryNode nodeTT = new BinaryNode(9002);
                        nodeTT = nodeT.Right;
                        nodeT5.Left = nodeT.Left;
                        nodeT.Left.Right = nodeTT;
                        count--; // Уменьшаем счётчик количества вершин в дереве
                        return true;
                    }
                    else if (nodeT.Left.Right != null) //Левый потомок имеет правого потомка
                    {
                        BinaryNode nodeT6 = new BinaryNode(9003);
                        FindNodeParent(node_root, nodeT.value, ref nodeT6); // Ищем родительскую вершину для удаляемой вершины

                        if (nodeT.Left.Right.Right == null) // Правый потомок левого потомка не имеет правого потомка
                        {
                            if (nodeT6.Left == nodeT) // Удаляемая вершина является левым потомком родительской вершины
                            {
                                nodeT6.Left = nodeT.Left.Right.Right;
                                
                            }
                            else
                            {
                                nodeT6.Right = nodeT.Left.Right.Right;

                            }
                        }
                    }
                }
            }

            return false;
        }
            
        public void FindLastRightNode(BinaryNode node, ref BinaryNode result_node)
        {
            // На вход подаём вершину, для которой нужно найти самого нижнего правого потомка

            if (node.Right == null)
            {
                result_node = node;
                return;
            }
            else
                FindLastRightNode(node.Right, ref result_node);
        }

        

    }
}




Полный код Form1.cs

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace BinaryTree
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            string nodes_str = textBox1.Text; // Получаем вершины из поля с вершинами

            // Проверка на правильность введённых значений
            if (!CheckString(nodes_str))
                return;

            // Парсим числа из строки в список вершин
            List<int> nodes = new List<int>();
            int[] nodes_temp = nodes_str.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).Select(x => Convert.ToInt32(x)).ToArray();
            nodes.AddRange(nodes_temp);

            BinaryNode root_bn = new BinaryNode(nodes[0]); // Определяем корневую вершину
            nodes.RemoveAt(0); // Убираем из списка вершин первую-корневую вершину
            BinaryTree bt = new BinaryTree(root_bn); // Создаём бинарное дерево

            for (int i = 0; i < nodes.Count; i++)
            {
                bt.AddElement(nodes[i]);
            }

            for (int j = 0; j < nodes.Count; j++) // Проверочный цикл
            {
                listBox1.Items.Add(Convert.ToString(nodes[j]));
            }

            listBox1.Items.Add(" ");

            /*

            // ПРОВЕРКА РЕКУРСИИ

            BinaryNode tempN = new BinaryNode(5555);

            bt.FindNode(root_bn, 4, ref tempN);

            BinaryNode tempN2 = new BinaryNode(5556);

            bt.FindLastRightNode(tempN, ref tempN2);

            listBox1.Items.Add(Convert.ToString(tempN2.value));

            */



            BinaryNode tempN = new BinaryNode(5555);

            bt.FindNode(root_bn, 4, ref tempN);

            BinaryNode tempN2 = new BinaryNode(5556);

            tempN2 = tempN.GetLastRight();

            listBox1.Items.Add(Convert.ToString(tempN2.value));





            DrawBinaryTree(bt);

            //listBox1.Items.Add(Convert.ToString(bt.GetNodesCount()));  // Число вершин в дереве
            //listBox1.Items.Add(Convert.ToString(bt.GetMinValue())); // Минимальное значение
            //listBox1.Items.Add(Convert.ToString(bt.GetMaxValue())); // Максимальное значение

            //bt.TraversePreorder(root_bn); // Прямой обход дерева
            //bt.TraverseInorder(root_bn); // Симметричный обход дерева
            //bt.TraversePostorder(root_bn); // Обход дерева в обратном порядке
            //bt.TraverseDepth(root_bn); // Обход дерева в ширину

            //listBox1.Items.Add(bt.FindValue(root_bn, 9)); // Поиск значения вершины - true или false


            //if(bt.FindNodeParent(root_bn, 9, ref tempN)) // Поиск родительской вершины
            // listBox1.Items.Add(tempN.value);

            //if (bt.FindNodeParent(root_bn, 9, ref tempN)) // Уровень вершины
            // listBox1.Items.Add(tempN.GetLevel());

            //if(bt.Remove(21)) // Удаление вершины
            {
                // bt.Remove(21);
                // bt.TraverseDepth(root_bn);
                //if(bt.FindNodeParent(root_bn, 2, ref tempN)) // Поиск родительской вершины
                // listBox1.Items.Add(tempN.value);
            }

        }



        private bool CheckString(string str)
        {
            for (int i = 0; i < str.Length; i++)
            {
                if (str[i] == ' ')
                    continue;

                if (str[i] == '-')
                    continue;

                if (str[i] >= '0' && str[i] <= '9')
                {
                    continue;
                }

                MessageBox.Show("Ошибка! Допускаются только числовые значения и пробелы между ними.");
                return false;
            }
            return true;
        }

        public void DrawBinaryTree(BinaryTree bt)
        {
            Bitmap image1 = new Bitmap("1.jpg");

            pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
            pictureBox1.BorderStyle = BorderStyle.Fixed3D;
            pictureBox1.Image = image1;
        }
       

        private void button3_Click(object sender, EventArgs e)
        {
            int minQuantityOfNodes = Convert.ToInt32(textBox2.Text); // Минимальное количество вершин
            int maxQuantityOfNodes = Convert.ToInt32(textBox3.Text); // Максимальное значение вершин
            int minValueOfNodes = Convert.ToInt32(textBox4.Text); // Минимальное значение вершин
            int maxValueOfNodes = Convert.ToInt32(textBox5.Text); // Максимальное значение вершин

            Random r1 = new Random();
            int quantityOfNodes = r1.Next(minQuantityOfNodes, maxQuantityOfNodes); // Вычисляем количество вершин

            List<int> nodes = new List<int>(); // Создаём список для хранения числовых значений вершин

            BinaryNode root_bn = new BinaryNode(r1.Next(minValueOfNodes, maxValueOfNodes)); // Вычисляем корневую вершину
            BinaryTree bt = new BinaryTree(root_bn); // Создаём бинарное дерево


            for (int i = 0; i < quantityOfNodes - 1; i++)
            {
                nodes.Add(r1.Next(minValueOfNodes, maxValueOfNodes));
            }

            for (int i = 0; i < nodes.Count; i++) // Проверочный цикл
            {
               // listBox1.Items.Add(Convert.ToString(nodes[i]));
            }


        }



        private void textBox2_TextChanged(object sender, EventArgs e)
        {

        }


    }
    }





hVostt, к сожалению, не работает предложенная Вами функция-- выдаёт тот же результат.
...
Рейтинг: 0 / 0
Рекурсия - возвращает неправильное значение в некоторых случаях
    #39440520
Фотография mraklbrw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
С ref-ами делаю потому, что функции имеют тип bool.
Чтобы потом можно было легко проверять, как прошла работа функции.
...
Рейтинг: 0 / 0
Рекурсия - возвращает неправильное значение в некоторых случаях
    #39440525
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mraklbrwС ref-ами делаю потому, что функции имеют тип bool.
Чтобы потом можно было легко проверять, как прошла работа функции.

Можно же возвращать null?
...
Рейтинг: 0 / 0
Рекурсия - возвращает неправильное значение в некоторых случаях
    #39440529
Фотография mraklbrw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что-то там пошло не так.
Я ещё думаю над этим.
Надо бы переписать, действительно.

А что можете сказать по функции GetLastRight?

Само дерево строится правильно - это можно проверить функцией TraverseDepth.
...
Рейтинг: 0 / 0
Рекурсия - возвращает неправильное значение в некоторых случаях
    #39440531
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mraklbrw,

Вообще, можно пройтись отладчиком, и глазами посмотреть что в каком порядке вызывается, как работает твоя рекурсия изнутри и очень быстро вычислить проблему.

Рекомендую также заглянуть сюда:

https://github.com/aalhour/C-Sharp-Algorithms/tree/master/DataStructures/Trees
...
Рейтинг: 0 / 0
Рекурсия - возвращает неправильное значение в некоторых случаях
    #39440532
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mraklbrwЧто-то там пошло не так.
Я ещё думаю над этим.

Отладчиком пользоваться умеешь?
...
Рейтинг: 0 / 0
Рекурсия - возвращает неправильное значение в некоторых случаях
    #39440536
Фотография mraklbrw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так себе. Сейчас вот думаю разобраться с эти делом посерьёзнее.
...
Рейтинг: 0 / 0
Рекурсия - возвращает неправильное значение в некоторых случаях
    #39440538
Фотография mraklbrw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Странное дело - не останавливается на точках останова.
...
Рейтинг: 0 / 0
Рекурсия - возвращает неправильное значение в некоторых случаях
    #39440539
Фотография mraklbrw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А, всё, решил (в Debug переключил).
...
Рейтинг: 0 / 0
Рекурсия - возвращает неправильное значение в некоторых случаях
    #39440544
Фотография mraklbrw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Выяснил вот что: перед выполнением функции GetLastRight вершина tempN имеет параметры: left=null, right=null, хотя right не должно быть null, т.к. у неё есть правый потомок 7.
...
Рейтинг: 0 / 0
Рекурсия - возвращает неправильное значение в некоторых случаях
    #39440549
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mraklbrwПолный код Form1.cs
Код: c#
1.
public partial class

это точно не полный класс формы.
Последний раз предлагаю вам сделать так, чтобы вам можно было помочь.

Поставьте себя на место отвечающего. Что ему требуется сделать?
- создать проект WinForms
- создать форму
- на форме расположить КАКИЕ-ТО контролы (перечень контролов нужно вычислить на основе вашего кода)
- заполнить КАКИЕ-ТО контролы КАКИЕ-ТО данные (догадаться умозрительно)
- нажать какие-то кнопки (вычислить или догадаться)
- ГДЕ-ТО увидеть результат (то ли в отладчике, то ли в каком-то из контролов), понять, что в нем не так и что именно вы ожидали там увидеть

Это будет делать разве что кто-то, кому особенно скучно.

Последний раз предлагаю сделать все, чтобы получить ответ (ведь это в ваших интересах, кажется), а именно.
- Убрать ВСЁ, что не относится конкретно к вопросу, выложить оставшиеся классы.
- Выложить несколько команд, которые
-- не относятся к каким-либо контролам (ведь вопрос у вас про неверную работу рекурсии, а не самой формы)
-- можно запустить из консоли
-- инициализируют все нужные данные и состояния
-- внятно возвращают какой-то результат
А также написать, какой результат ожидается и почему.

Тогда вы достаточно быстро получите ответ (если с очень большой вероятностью не разберетесь с проблемой уже на вышеописанном этапе).
...
Рейтинг: 0 / 0
Рекурсия - возвращает неправильное значение в некоторых случаях
    #39440711
Фотография mraklbrw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Проблема с функцией GetLastRight.
Для последовательности вершин 2 3 5 9 1 0 4 7 - проверяем элемент 5 - возвращает 5, хотя должно 9.

Переписал функцию так:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
public BinaryNode GetLastRight()
        {
            //return this.Right == null ? this : this.Right.GetLastRight();

            if (this.Right == null)
            {
                return this;
            }
            else
                return this.Right.GetLastRight();
        }


Тот же самый результат.
Хотя вот эта функция - работает правильно:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
 public void FindLastRightNode(BinaryNode node, ref BinaryNode result_node)
        {
            // На вход подаём вершину, для которой нужно найти самого нижнего правого потомка

            if (node.Right == null)
            {
                result_node = node;
                return;
            }
            else
                FindLastRightNode(node.Right, ref result_node);
        }



Проект полностью: https://yadi.sk/d/EbhhiYjy3H88GN
...
Рейтинг: 0 / 0
Рекурсия - возвращает неправильное значение в некоторых случаях
    #39440717
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Похоже, автор не нуждается в помощи.
Попробуй еще несколько раз прочитать 20412845 , пока не станет понятно.
-----------

Ну выложил ты проект, в нем две кнопки. При нажатии каждой из них проект падает - и дальше что?
...
Рейтинг: 0 / 0
Рекурсия - возвращает неправильное значение в некоторых случаях
    #39440741
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVosttmraklbrw,

Вообще, можно пройтись отладчиком, и глазами посмотреть что в каком порядке вызывается, как работает твоя рекурсия изнутри и очень быстро вычислить проблему.

Рекомендую также заглянуть сюда:

https://github.com/aalhour/C-Sharp-Algorithms/tree/master/DataStructures/Trees
Фиговинький там способ получения перестановок.
https://github.com/aalhour/C-Sharp-Algorithms/blob/master/Algorithms/Strings/Permutations.cs
Вот лучше
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
     public static IEnumerable<IEnumerable<T>> Permute<T>(IEnumerable<T> list)

        {

            if (list.Count() == 1)
                return new List<IEnumerable<T>> { list };
            return list
                .Select((a, i1) =>
                {
                    var res = Permute(list.Where((b, i2) => i2 != i1)).Select(c =>
                    {
                        var res1 = (new T[] { a }).Union(c);
                        return res1;
                    });
                    return res;
                })
                .SelectMany(c => c);
        }
...
Рейтинг: 0 / 0
Рекурсия - возвращает неправильное значение в некоторых случаях
    #39440827
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЕвгенийВ,

Чёт не хочется иметь потенциальную возможность свалиться со StackOverflowException.
Поэтому, не — не лучше, хотя компактно :)
...
Рейтинг: 0 / 0
Рекурсия - возвращает неправильное значение в некоторых случаях
    #39440935
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVosttЕвгенийВ,

Чёт не хочется иметь потенциальную возможность свалиться со StackOverflowException.
Поэтому, не — не лучше, хотя компактно :)
Если list.Count() не сильно велик, не свалишься.
Тут tot kturj OutOfMemoryException схватить.
...
Рейтинг: 0 / 0
Рекурсия - возвращает неправильное значение в некоторых случаях
    #39441011
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЕвгенийВ,

Надо ещё перфоманс надо бы затестить, это другая сторона кроме возможного переполнения стека.
...
Рейтинг: 0 / 0
Рекурсия - возвращает неправильное значение в некоторых случаях
    #39441115
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVosttЕвгенийВ,

Надо ещё перфоманс надо бы затестить, это другая сторона кроме возможного переполнения стека.

Попробуй)
Сравни с http://www.cplusplus.com/reference/algorithm/next_permutation/
...
Рейтинг: 0 / 0
24 сообщений из 24, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Рекурсия - возвращает неправильное значение в некоторых случаях
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]