-
+ -
* 5 sin 5
1 2 (1)
Бинарное дерево
Написал программу, которая раскидывает выражение по дереву.
Например, (((1*2)+5)-((sin(1))-5))
У меня получилось:
Код:
Все значения в формате 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();
}
#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();
}
если смог построить дерево то в чем трудность пройтись по нему и посчитать?..
Да просто все с очень большим трудом получилось, оч долго разбирался. вот не знаю теперь как посчитать и с преобразованиями не уверен, там же не только числа но и функции.. что с ними делать.
если что-то непонятно в деталях -- спрашивай
Что-то вроде такого:
Код:
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));
/* и т.д. */
}
{
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,
/* и т.д. - какие могут быть ещё операции */
};
{
eNoOperation = 0,
ePlus,
eMinus,
eMul,
eDiv,
eSinus,
/* и т.д. - какие могут быть ещё операции */
};
В структуру treeNode добавить переменную - объект этого enum, например:
Код:
struct treeNode
{
struct treeNode *left;
struct treeNode *right;
char data[100];
eOperation operType;
};
{
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:
/* Полагаю, тут нужно выбросить какую-нибудь ошибку */
}
}
{
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. Код писал на скорую руку, не проверял, в чём-то могут быть ошибки.
Добавил функцию
Код:
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));
/* и т.д. */
}
{
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));
/* и т.д. */
}
Все работает. Спасибо)))))