Re: Рекурсивное построение дерева-формулы
От: Глеб Алексеев  
Дата: 19.09.05 14:43
Оценка: +1
Здравствуйте, TerryKath, Вы писали:

TK>Помогите, пожалуйста! Никак не могу придумать, как написать эту рекурсивную процедуру...

Почитай про метод Дейкстры (преобразование выражения в обратную польскую нотацию):
http://algolist.manual.ru/maths/misc/revpn.php
Рекурсивное построение дерева-формулы
От: TerryKath  
Дата: 18.09.05 11:31
Оценка:
Никак не могу сообразить, как решить эту задачу:
Формулу вида
<формула>::=<терминал>|(<формула><знак><формула>)
<знак>::= + | -| /1 *
<терминал>::= 0|1|2|3|4|5|6|7|8|9
можно представить в виде двоичного дерева с элементами типа char. Написать
программу, которая используя рекурсивную подпрограмму, по формуле строит
дерево-формулу.

То есть, например, если дана формула 2*1+2*3-3, то дерево будет иметь такой вид:
................+
............./.....\
............*.......-
.........../\......./\
..........2..1....*..3
................../\
.................2..3

Помогите, пожалуйста! Никак не могу придумать, как написать эту рекурсивную процедуру...
Re: Рекурсивное построение дерева-формулы
От: LuciferMoscow Россия  
Дата: 18.09.05 12:20
Оценка:
Здравствуйте, TerryKath, Вы писали:
TK>Помогите, пожалуйста! Никак не могу придумать, как написать эту рекурсивную процедуру...
Строить дерево — это идея правильная.
Строить нужно
1. с хвоста. Пример:
2-2+2
2. Причем вначале искать знаки с наименьшим приоритетом. Пример:
2*2-2
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re: Рекурсивное построение дерева-формулы
От: LuciferMoscow Россия  
Дата: 18.09.05 12:20
Оценка:
Здравствуйте, TerryKath, Вы писали:
TK>Помогите, пожалуйста! Никак не могу придумать, как написать эту рекурсивную процедуру...
Строить дерево — это идея правильная.
Строить нужно
1. с хвоста. Пример:
2-2+2
2. Причем вначале искать знаки с наименьшим приоритетом. Пример:
2*2-2

P.S. Janus глючит, если таких сообщений будет 2 — не обесудьте
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re: Рекурсивное построение дерева-формулы
От: Кодт Россия  
Дата: 19.09.05 10:51
Оценка:
Здравствуйте, TerryKath, Вы писали:

TK>Помогите, пожалуйста! Никак не могу придумать, как написать эту рекурсивную процедуру...


Вообще говоря, это задача построить парсер операторной грамматики. За подробностями — велкам то Ахо,Хопкрофт,Ульман, гугл и т.п.

Парсер представляет собой стековый автомат. Стек можно хранить как отдельную структуру, либо совместить со стеком вызовов. Вот первое место для рекурсии.
Парсер последовательно читает входную строку и выполняет над каждым символом и своим стеком некие действия. Этот итерационный процесс можно заменить на эквивалентную концевую рекурсию (а в функциональных языках — не только можно, но и нужно). Это второе место.

Дальнейшие объяснения хорошо бы приводить с комментариями на каком-то конкретном языке программирования. Поэтому за тобой "выбор оружия". Затем продолжим.
Перекуём баги на фичи!
Re: Рекурсивное построение дерева-формулы
От: Рома Мик Россия http://romamik.com
Дата: 19.09.05 20:05
Оценка:
Здравствуйте, TerryKath, Вы писали:

TK>То есть, например, если дана формула 2*1+2*3-3, то дерево будет иметь такой вид:

TK>................+
TK>............./.....\
TK>............*.......-
TK>.........../\......./\
TK>..........2..1....*..3
TK>................../\
TK>.................2..3

TK>Помогите, пожалуйста! Никак не могу придумать, как написать эту рекурсивную процедуру...

Вот минут за 10 накатал, особо не тестировал, но идея должна быть ясна
struct Tree 
{
    virtual ~Tree() {};
};

struct Node : Tree
{
    char op_;
    Tree * left_, * right_;
    Node(char op, Tree * left, Tree * right) : op_(op), left_(left), right_(right) {}
    ~Node()
    {
        delete left_;
        delete right_;
    }
};

struct Leaf : Tree
{
    int number_;
    Leaf(char * &s) : number_(0)
    {
        while(*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n')
            ++s;
        int sign = 1;
        while(*s == '+' || *s == '-')
        {
            if(*s == '-')
                sign *= -1;
            ++s;
        }
        while(*s >= '0' && *s <= '9')
            (number_ *= 10) += *s++ - '0';
    }
};

Tree * MulDiv(char * &s)
{
    Tree * tree = new Leaf(s);
    for(;;)
        if(*s == '*' || *s == '/')
        {
            char op = *s++;
            tree = new Node(op, tree, new Leaf(s));
        }
        else if(*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n')
            ++s;
        else
            return tree;
}

Tree * PlusMinus(char * &s)
{
    Tree * tree = MulDiv(s);
    for(;;)
        if(*s == '-' || *s == '+')
        {
            char op = *s++;
            tree = new Node(op, tree, MulDiv(s));
        }
        else if(*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n')
            ++s;
        else
            return tree;
}

Tree * Parse(char * s)
{
    return PlusMinus(s);
}

int main()
{
    char s[] = "10 + 20 * 30";
    Tree * tree = Parse(s);
    delete tree;
}
... << RSDN@Home 1.1.4 beta 7 rev. 468>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.