Учитывая двоичное дерево арифметических выражений, состоящее только из операторов сложения и вычитания и чисел, как сбалансировать дерево в максимально возможной степени?Задача состоит в том, чтобы сбалансировать дерево без оценки выражения, то есть количество узлов должно оставаться неизменным.
Пример:
+ +
/ \ / \
+ 15 >>>>>> - +
/ \ / \ / \
5 - 6 4 5 15
/ \
6 4
Добавление является коммутативным и ассоциативным, что позволяет проводить балансировку.Коммутативность позволяет менять местами дочерние узлы «+».Ассоциативность учитывает вращения.В приведенном выше примере выполненное преобразование можно просмотреть как
- Поворот вправо на «+» в корне.
- Замена мест «5» и «-».
Я думал о том, чтобы сделать обход по порядку и сначала уравновесить любые поддеревья.Я бы попытался сбалансировать любое поддерево с двумя последовательными узлами «+», попробовав все возможные расположения узлов (их всего 12), чтобы, надеюсь, уменьшить общую высоту дерева.Этот метод должен уменьшить высоту дерева максимум на 1 на любом шаге.Однако я не могу определить, будет ли оно всегда давать дерево минимальной высоты, особенно когда имеется более 2 последовательных узлов '+'.
Другой подход может состоять в том, чтобы прочитать дерево выражений в массив и заменить любое'-' поддерево с переменной.А потом нам DP, чтобы определить лучшие места для скобок.Это должно быть сделано снизу вверх, так что любое поддерево «-» уже сбалансировано, когда оно рассматривается алгоритмом DP.Тем не менее, я волнуюсь, потому что может быть (n + 1)!способы размещения узлов и скобок.Пока я ищу алгоритм O (n).
Это известная проблема и существует ли к ней особый подход?