Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Бинарное дерево

58K
22 декабря 2010 года
Aндрей
17 / / 21.11.2010
Осваиваю двоичное дерево.
Написал программу, которая раскидывает выражение по дереву.
Например, (((1*2)+5)-((sin(1))-5))
У меня получилось:
 
Код:
-
                          +                   -
                 *            5         sin       5
             1      2               (1)

Все значения в формате char.
Помогите написать функцию, чтобы можно было теперь посчитать значение этого выражения.
Моя прога

Код:
#include <stdio.h>
#include <conio.h>
#include <malloc.h>

int sintaks(char *str)
{
   int i=0, sk=0;
   while(str!='\0')
   {
      if(str=='(')
     sk++;
      if(str==')')
     sk--;
      if(sk<0)
     return 1;
      i++;
   }
   if(sk==0)
      return 0;
   else
      return 1;
}

int proverka(char *str, int sk)
{
   if((*str==')')&&(sk==0))
      return 1;
   return 0;
}

int letter(char *str)
{
   char *item="CcEeGgIiLlNnOoPpSsTtXx";
   int i=0;
   while(item!='\0')
   {
      if(*str==item)
      return 1;
      i++;
   }
   return 0;
}

struct treeNode
{
   struct treeNode *left;
   //char *data;
   char data[100];
   struct treeNode *right;
};

typedef struct treeNode TREENODE;
typedef TREENODE *TREENODEPTR;

void inOrder(TREENODEPTR tree)
{
   if(tree!=NULL)
   {
      inOrder(tree->left);
      printf("%s",tree->data);
      inOrder(tree->right);
   }
}

void write(TREENODEPTR *treePtr, char *str)
{
   int k,i=0;
   if((str[0])!='\0')
   {
      if(*treePtr==NULL)
      {
     *treePtr=(treeNode *)malloc(sizeof(TREENODE));
     if(*treePtr!=NULL)
     {
        k=0;
        while(str!='\0')
        {
           (*treePtr)->data[k]=str;
           k++; i++;
        }
        (*treePtr)->data[k]='\0';
        (*treePtr)->left=NULL;
        (*treePtr)->right=NULL;
     }
     else
        printf("%c not inserted. No memory avaliable.\n", str);
      }
      else
      {
     write(&((*treePtr)->left),str);
      }
   }
}


void insertNode(TREENODEPTR *treePtr, char *str)
{
   //char *strmas, *smas, *masL, *masR;
   char strmas[100], smas[100], masL[100], masR[100], fmas[100];
   int flag=0, itemflag=0, k=0, sk=0, l=0, r=0, f=0;
   int i=0;

   if(str[0]=='(')
   {
      i++;
      sk=0; flag=0;
      while(proverka(&str,sk)!=1)
      {
     if((flag==0)&&(sk==0)&&(letter(&str[1])==1))
     {
        k=0; flag=1; itemflag=1;
        while(str!='(')
        {
           strmas[k]=str;
           i++; k++;
        }
        strmas[k]='\0';
        // write in the root of the tree
        if(*treePtr==NULL)
        {
           *treePtr=(treeNode *)malloc(sizeof(TREENODE));
           if(*treePtr!=NULL)
           {
          k=0;
          while(strmas[k]!='\0')
          {
             (*treePtr)->data[k]=strmas[k];
             k++;
          }
          (*treePtr)->data[k]='\0';
          (*treePtr)->left=NULL;
          (*treePtr)->right=NULL;
           }
           else
          printf("%s not inserted. No memory avaliable.\n", strmas);
        }
        else
        {
           insertNode(&((*treePtr)->left),strmas);
        }
        ///////////////////////////////////////////
        while(proverka(&str,sk)!=1)
        {
           fmas[f]=str;
           if(proverka(&str[i+1],0)==1)
           {
          fmas[f+1]=')';
          fmas[f+2]='\0';
           }
           i++; f++;
        }
        write(&(*treePtr)->left,fmas);
        break;//continue;
        ///////////////////////////////////////////
     }

     if(((str=='+')||(str=='-')||(str=='*')||(str=='/'))&&(flag==0)&&(sk==0))
     {
        flag=1;
        smas[0]=str;
        smas[1]='\0';
        // write in the root of the tree
        if(*treePtr==NULL)
        {
           *treePtr=(treeNode *)malloc(sizeof(TREENODE));
           if(*treePtr!=NULL)
           {
          (*treePtr)->data[0]=smas[0];
          (*treePtr)->data[1]='\0';
          (*treePtr)->left=NULL;
          (*treePtr)->right=NULL;
           }
           else
          printf("%s not inserted. No memory avaliable.\n", smas);
        }
        else
        {
           insertNode(&((*treePtr)->left),smas);
        }
        i++;
     }

     if(flag==0)
     {
        if(str=='(')
           sk++;
        if(str==')')
           sk--;
        masL[l]=str;
        l++;
     }

     if(flag!=0)
     {
        if(str=='(')
           sk++;
        if(str==')')
           sk--;
        masR[r]=str;
        r++;
        if(proverka(&str[i+1],0)==1)
        {
           masL[l]='\0';
           masR[r]='\0';
        }
     }

     i++;
      }

      // rekursia

      if((flag==1)&&(itemflag==0))
      {
     insertNode(&((*treePtr)->left),masL);
     insertNode(&((*treePtr)->right),masR);
      }

   }
   else
   {
      if((str[0])!='\0')
      {
     if(*treePtr==NULL)
     {
        *treePtr=(treeNode *)malloc(sizeof(TREENODE));
        if(*treePtr!=NULL)
        {
           k=0;
           while(str!='\0')
           {
          (*treePtr)->data[k]=str;
          k++; i++;
           }
           (*treePtr)->data[k]='\0';
           (*treePtr)->left=NULL;
           (*treePtr)->right=NULL;
        }
        else
           printf("%c not inserted. No memory avaliable.\n", str);
     }
     else
     {
        insertNode(&((*treePtr)->left),str);
     }
      }
   }
}




void main(void)
{
   clrscr();
   FILE *f=fopen("c:\\1.txt","r");
   char item, *str;
   int i=0;
   while(!feof(f))
   {
      item=getc(f);
      if(item!='\0')
      {
     if(i>1)
        str[i-2]=item;
      i++;
      }
   }
   fclose(f);
   i-=3;
   str='\0';
   printf("%s\n", str);
   //////////////////////////////////////////////////////////////

   int k=sintaks(str);
   if(k==0)
   {
      TREENODEPTR rootPtr=NULL;
      insertNode(&rootPtr,str);
      printf("\n");
      inOrder(rootPtr);
   }
      else
     printf("error!");

    getch();
}
1.8K
23 декабря 2010 года
LM(AL/M)
332 / / 20.12.2005
если смог построить дерево то в чем трудность пройтись по нему и посчитать?..
58K
23 декабря 2010 года
Aндрей
17 / / 21.11.2010
Да просто все с очень большим трудом получилось, оч долго разбирался. вот не знаю теперь как посчитать и с преобразованиями не уверен, там же не только числа но и функции.. что с ними делать.
1.8K
23 декабря 2010 года
LM(AL/M)
332 / / 20.12.2005
нужно сделать рекурсивный обход дерева: (начинаем с корня дерева) если текущая вершина содержит строку-число -- преобразовать в int/float и вернуть вызывающему коду; если функциональный символ, то 1) повторить то же самое для каждого потомка вершины (получится набор чисел) 2) определить по имени записанному в тек. вершине адрес конкретной функции (можно например завести таблицу соответствия строкам адресов и делать в ней поиск) и вызвать по этому адресу передав туда набор чисел найденный из потомков, результат вызова опять возвращаем наверх. Таким образом каждый treeNode "отдает" своему родителю какой-то результат, а корневой нод возвращает конечный результат вычисления по формуле.
если что-то непонятно в деталях -- спрашивай
12K
23 декабря 2010 года
Ghox
297 / / 26.07.2009
Поясню поподробнее то, что описал LM(AL/M). Нужна функция, которая получает аргумент - узел бинарного дерева, и в зависимости от содержимого узла, возвращает некоторый числовой результат. Если в содержащейся в узле строке записано число - то нужно извлечь его и вернуть. Если записана операция - то нужно определить что за операция, и применить её к результатам вызовов функцией самой себя: если операция унарная (с одним операндом) - то применить её результату применению функции к левому узлу (или правому, я не разбирал как у вас сделано в случае унарной операции); если бинарная - то к результатам вызова функции к каждому из узлов.

Что-то вроде такого:
Код:
double CalcExprTree(struct treeNode *node)
{
    if(node == NULL)
        return 0.0;

    if(/* проверка на то что в node->data записано число*/)
        return atof(node->data);

    if(strcmp(node->data, "+") == 0)
        return CalcExprTree(node->left) + CalcExprTree(node->right);

    /* аналогично для прочих бинарных операций - вычитание и т.д. */

    if(strcmp(node->data, "sin") == 0)
        return sin(CalcExprTree(node->left));

    /* и т.д. */
}


А вообще, можно было бы организовать архитектуру программы немного по-другому. Создать перечисление (enum) для разных операций:
 
Код:
enum eOperation
{
    eNoOperation = 0,
    ePlus,
    eMinus,
    eMul,
    eDiv,
    eSinus,
    /* и т.д. - какие могут быть ещё операции */
};

В структуру treeNode добавить переменную - объект этого enum, например:
 
Код:
struct treeNode
{
   struct treeNode *left;
   struct treeNode *right;
   char data[100];
   eOperation operType;
};


И при прочтении дерева, если обнаружено, что узел является операцией, то проставлять в переменную-enum соотв. значение, в data - ничего не писать. Если же узел - число, то в enum писать eNoOperation, в data - само значение числа.

И тогда в рекурсивной функции можно применить switch для анализа enum-переменной, если же в нём записано eNoOperation - то парсить число хранящееся в data, и возвращать его. Как-то так:
Код:
double CalcExprTree(struct treeNode *node)
{
    if(node == NULL)
        return 0.0;

    switch(node->operType)
    {
        case eNoOperation:
            return atof(node->data);

        case ePlus:
            return CalcExprTree(node->left) + CalcExprTree(node->right);

        /* аналогично вычитание, умножение и деление */

        case eSinus:
            return sin(CalcExprTree(node->left));

        /* и т.д. */

        default:
            /* Полагаю, тут нужно выбросить какую-нибудь ошибку */
    }
}


P.S. Код писал на скорую руку, не проверял, в чём-то могут быть ошибки.
58K
23 декабря 2010 года
Aндрей
17 / / 21.11.2010
спасибо, препод сказал что в принципе уже хорошо что по дереву раскидал. у нас просто экзамен уже 29. на каникулах обязательно попробую. даже самому интересно.
Добавил функцию
Код:
double CalcExprTree(struct treeNode *node)
{
    if(node == NULL)
        return 0.0;

    if(/* проверка на то что в node->data записано число*/)
        return atof(node->data);

    if(strcmp(node->data, "+") == 0)
        return CalcExprTree(node->left) + CalcExprTree(node->right);

    /* аналогично для прочих бинарных операций - вычитание и т.д. */

    if(strcmp(node->data, "sin") == 0)
        return sin(CalcExprTree(node->left));

    /* и т.д. */
}


Все работает. Спасибо)))))
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог