SLIDE1

Saturday, May 16, 2015

tính giá trị biểu thức bằng cây nhị phân

lập trình c++ trính giá trị biểu thức toán học gồm số nguyên, dấu ngoặc (), phép toán +-*/ bằng phương pháp cây nhị phân.
#include<iostream>
#include<string>
using namespace std;
typedef struct tagnode
{
     string s;
     struct tagnode *left;
     struct tagnode *right;
}node;
node *taonode(string s)
{
     node *p=new node;
     if(p==NULL)
     {
          cout<<"khong du bo nho";
          system("pause");
          exit(1);
     }
     p->s=s;
     p->left=p->right=NULL;
     return p;
}
typedef node *cay;
void taocay(cay &t)
{
     t=NULL;
}
int vitridau(string s,int j)
{
     for(int i=j+1;i<s.size();i++)
          if(s[i]=='+' || s[i]=='-' || s[i]=='*' || s[i]=='/' || s[i]=='(')
               return i;
     return -1;
}
int timngoac(string s,int i)
{
     int j,dem=1;
     for(j=i+1;j<s.size();j++)
     {
          if(s[j]=='(') dem++;
          else if(s[j]==')') dem--;
          if(dem==0) return j;
     }
     return -1;
}
void xulyngoac(string &s)
{
     if(s[0]=='(')
     {
          int i=timngoac(s,0);
          if(i==s.size()-1)
          {
               s.erase(0,1);
               s.erase(s.size()-1,1);
          }
     }
}
void doidau(string &c)
{
     int x=0;
     do{
          x=vitridau(c,x);
          if(x!=-1)
          {
               if(c[x]=='(') x=timngoac(c,x);
               else if(c[x]=='-' && c[x-1]!='*' && c[x-1]!='/') c[x]='+';
               else if(c[x]=='+' && c[x-1]!='*' && c[x-1]!='/') c[x]='-';
               //chỉ đổi dấu + thành - và dấu - thành cộng khi nó là dấu của 1 số hạng
               //nếu nó dấu của 1 thừa số thì dữ nguyên không thay đổi gì cả mặc dù
               //dấu của node của cây tức s[i] là dấu - vì dấu của thừa số không liên quan đến số hạng
          }
     }while(x!=-1);
}
node *setcay(string s)
{
     xulyngoac(s);
     node *p;
     int k,j,x;
     string a,b,c;
     int i=vitridau(s,0);//tìm vị trí dấu đầu tiên trong biểu thức, có 2 trường hợp, có dấu và không có dấu
     if(s[0]=='(') i=0;
     if(i==-1)// trường hợp không có dấu
     {
          p=taonode(s);
          return p;
     }
     else//trường hợp có dấu, có 3 trường hợp nhỏ
     {
          if(s[i]=='+' || s[i]=='-')// dấu + hoặc -
          {
               a=s[i];
               p=taonode(a);
               b=s.substr(0,i);
               xulyngoac(b);
               c=s.substr(i+1,s.size()-i-1);
               xulyngoac(c);
               //đổi dấu các số hạng phía sau nếu s[i] là dấu -
               if(s[i]=='-') doidau(c);
               p->left=setcay(b);
               p->right=setcay(c);
          }
          else if(s[i]=='*' || s[i]=='/')//dấu * hoặc /
          {
               k=i;
               //tìm vị trí dấu + hoặc - phía sau dấu ngoặc nhưng nằm ngoài dấu ngoặc
               do{
                    k=vitridau(s,k);
                    if(k!=-1)
                    {
                         if(s[k]=='(') k=timngoac(s,k);
                         if(k>0 && (s[k]=='+' || s[k]=='-') && (s[k-1]!='*' && s[k-1]!='/')) break;
                    }
               }while(k!=-1);
               if(k==-1)//nếu không có thì node sẽ là dấu * hoặc / tại vị trí i ban đầu
               {
                    a=s[i];
                    p=taonode(a);
                    b=s.substr(0,i);
                    xulyngoac(b);
                    c=s.substr(i+1,s.size()-i-1);
                    xulyngoac(c);
                    p->left=setcay(b);
                    p->right=setcay(c);
               }
               else//nếu tìm thấy thì node là dấu tìm thấy
               {
                    a=s[k];
                    p=taonode(a);
                    b=s.substr(0,k);
                    xulyngoac(b);
                    c=s.substr(k+1,s.size()-k-1);
                    xulyngoac(c);
                    //doi dau +-
                    if(s[k]=='-') doidau(c);
                    p->left=setcay(b);
                    p->right=setcay(c);
               }
          }
          else if(s[i]=='(')//dấu mở ngoặc (
          {
               j=timngoac(s,i);//tìm vị trí dấu đóng ngoặc
               
               if(s[j+1]=='+' || s[j+1]=='-')//sau dấu đóng ngoặc là dấu + hoặc - thì node là dấu + hoặc -
               {
                    a=s[j+1];
                    p=taonode(a);
                    b=s.substr(0,j+1);
                    xulyngoac(b);
                    c=s.substr(j+2,s.size()-j-2);
                    xulyngoac(c);
                    //doi dau +-
                    if(s[j+1]=='-') doidau(c);
                    p->left=setcay(b);
                    p->right=setcay(c);
               }
               else if(s[j+1]=='*' || s[j+1]=='/')//nếu sau đóng ngoặc là * hoặc /
               {
                    k=j+1;
                    //tiếp tục tìm dấu + - phía sau nó mà nằm ngoài tất cả dấu ngoặc
                    do{
                         k=vitridau(s,k);
                         if(k!=-1)
                         {
                              if(s[k]=='(') k=timngoac(s,k);
                              if(k>0 && (s[k]=='+' || s[k]=='-') && (s[k-1]!='*' && s[k-1]!='/')) break;
                         }
                    }while(k!=-1);
                    if(k==-1)//nếu không tìm thấy thì node là dấu */ tại trí j+1
                    {
                         a=s[j+1];
                         p=taonode(a);
                         b=s.substr(0,j+1);
                         xulyngoac(b);
                         c=s.substr(j+2,s.size()-j-2);
                         xulyngoac(c);
                         p->left=setcay(b);
                         p->right=setcay(c);
                    }
                    else//nếu tìm thấy thì node là dấu tìm thấy
                    {
                         a=s[k];
                         p=taonode(a);
                         b=s.substr(0,k);
                         xulyngoac(b);
                         c=s.substr(k+1,s.size()-k-1);
                         xulyngoac(c);
                         //doi dau +-
                         if(s[j+1]=='-') doidau(c);
                         p->left=setcay(b);
                         p->right=setcay(c);
                    }
               }
          }
     }
     return p;
}
long atol(string s)
{
     long x=0,d=1;
     int j=0,k=0;
     if(s[0]=='+' || s[0]=='-')
     {
          j=1;
          if(s[0]=='-') k=1;
     }
     for(int i=s.size()-1;i>=j;i--)
     {
          switch(s[i])
          {
          case '0':x+=0*d;break;
          case '1':x+=1*d;break;
          case '2':x+=2*d;break;
          case '3':x+=3*d;break;
          case '4':x+=4*d;break;
          case '5':x+=5*d;break;
          case '6':x+=6*d;break;
          case '7':x+=7*d;break;
          case '8':x+=8*d;break;
          case '9':x+=9*d;break;
          }
          d*=10;
     }
     if(k==0)return x;
     return -x;
}
long tinh(cay t)
{
     long x;
     if(t)
     {
          if(t->s=="+") return tinh(t->left)+tinh(t->right);
          else if(t->s=="-") return tinh(t->left)-tinh(t->right);
          else if(t->s=="*") return tinh(t->left)*tinh(t->right);
          else if(t->s=="/") return tinh(t->left)/tinh(t->right);
          else return atol(t->s);
     }
     return 0;
}
void main()
{
     cay t;
     taocay(t);
     string s;
     cout<<"nhap bieu thuc toan hoc cua cac so nguyen duong:\n";
     getline(cin,s);
     t=setcay(s);
     cout<<"gia tri bieu thuc = "<<tinh(t)<<endl;
     system("pause");
}

Related Posts:

  • sắp xếp trộn run sắp xếp ngoại Phương pháp trộn Run Khái niệm cơ bản:  Run là một dãy liên tiếp các phần tử được sắp thứ tự. Ví dụ 2  4  7  12  50 là một run gồm có 5 phần tử  Chiều dài run chính là số phần tử trong Run. Chẳng h… Read More
  • danh sách liên kết kép danh sách liên kết kép, định nghĩa struct và các hàm thành phần có trong danh sách kép Cấu Trúc Dữ Liệu Cấu trúc dữ liệu 1 nút typedef struct tagDnode { Data Info; struct tagDnode *pPre; struct tagDnode *pNext; }DN… Read More
  • thuật toán merge sort - sắp xếp trộn Giải thuật Merge sort sắp xếp dãy a1, a2, ..., an dựa trên nhận xét sau: Mỗi dãy a1, a2, ..., an bất kỳ là một tập hợp các dãy con liên tiếp mà mỗi dãy con đều đã có thứ tự. Ví dụ: dãy 12, 2, 8, 5, 1, 6, 4, 15 có thể coi… Read More
  • thuật toán sắp xếp radix sort Radix Sort là một thuật toán tiếp cận theo một hướng hoàn toàn khác. Nếu như trong các thuật toán khác, cơ sở để sắp xếp luôn là việc so sánh giá trị của 2 phần tử thì Radix Sort lại dựa trên nguyên tắc phân loại thư của b… Read More
  • danh sách liên kết đơnMỗi phần tử liên kết với phần tử đứng liền sau trong danh sách Mỗi phần tử trong danh sách liên kết đơn là một cấu trúc có hai thành phần Thành phần dữ liệu: Lưu trữ thông tin về bản thân phần tử Thành phần liên kết: Lưu địa … Read More