表达式二叉树(C++实现,实现了通过前缀,中缀,后缀表达式构建二叉树)
学数据结构时的上机作业,花了半天时间写的。
问题描述:
1、对于任意给出的前缀表达式(不带括号)、中缀表达式(可以带括号)或后缀表达式(不带括号),能够在计算机内部构造出一棵表达式二叉树,并且图示出来(图形的形式)。
2、对于构造好的内部表达式二叉树,按照用户的要求输出相应的前缀表达式(不带括号)、中缀表达式(可以带括号,但不允许冗余括)或后缀表达式(不带括号)。
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //表达式二叉树 2 //作者:王锦 3 //邮箱:jinksw@vip.qq.com 4 5 #include "stdafx.h" 6 #include <stack> 7 #include <utility> 8 #include <iostream> 9 #include <sstream> 10 #include <queue> 11 #include <cmath> 12 #include <list> 13 using namespace std; 14 15 16 //二叉树结点类 17 template<class T> 18 class BinaryTreeNode 19 { 20 private: 21 T value; 22 BinaryTreeNode<T> *leftChild; 23 BinaryTreeNode<T> *rightChild; 24 public: 25 BinaryTreeNode(){leftChild = NULL,rightChild = NULL;}; 26 BinaryTreeNode(const T&mValue); 27 BinaryTreeNode(const T&mValue,BinaryTreeNode<T> *mLeftChild,BinaryTreeNode *mRightChild); 28 29 void setValue(const T&mValue); 30 T getValue()const; 31 32 BinaryTreeNode<T> * getLeftChild()const; 33 BinaryTreeNode<T> * getRightChild()const; 34 void setLeftChild(BinaryTreeNode<T> *leftChild); 35 void setRightChild(BinaryTreeNode<T> *rightChild); 36 37 bool isLeaf()const; 38 }; 39 template<class T> 40 BinaryTreeNode<T>::BinaryTreeNode(const T&mValue) 41 { 42 value = mValue; 43 leftChild = rightChild = NULL; 44 } 45 46 template<class T> 47 BinaryTreeNode<T>::BinaryTreeNode(const T&mValue,BinaryTreeNode<T> *mLeftChild,BinaryTreeNode *mRightChild) 48 { 49 value = mValue; 50 leftChild = mLeftChild; 51 rightChild = mRightChild; 52 } 53 54 template<class T> 55 T BinaryTreeNode<T>::getValue()const//得到该结点的值 56 { 57 return value; 58 } 59 60 template<class T> 61 BinaryTreeNode<T>* BinaryTreeNode<T>::getLeftChild()const//得到左子结点 62 { 63 return leftChild; 64 } 65 66 template<class T> 67 BinaryTreeNode<T>* BinaryTreeNode<T>::getRightChild()const//得到右子结点 68 { 69 return rightChild; 70 } 71 72 template<class T> 73 void BinaryTreeNode<T>::setLeftChild(BinaryTreeNode<T> *leftChild)//设置左子结点 74 { 75 this->leftChild = leftChild; 76 } 77 78 template<class T> 79 void BinaryTreeNode<T>::setRightChild(BinaryTreeNode<T> *rightChild)//设置右子结点 80 { 81 this->rightChild = rightChild; 82 } 83 84 template<class T> 85 void BinaryTreeNode<T>::setValue(const T&mValue)//设置该结点的值 86 { 87 value = mValue; 88 } 89 90 template<class T> 91 bool BinaryTreeNode<T>::isLeaf()const//是否为树叶 92 { 93 return leftChild == NULL && rightChild == NULL; 94 } 95 96 class ExpressionBinaryTree 97 { 98 private: 99 BinaryTreeNode<string> *root; 100 void clear() 101 { 102 if(root == NULL) 103 return; 104 recursionDeleteAll(root); 105 };//调用内部递归函数清空二叉树,以及释放空间 106 bool aIsGreaterOrEqualThanB(char a,char b);//工具方法,用于比较a,b优先级 107 int getHeight(BinaryTreeNode<string> *root);//求树的高度 108 void printBlank(int n);//工具方法,打印n个空格 109 void printInRightFormat(string value);//按照格式打印,以便对齐 110 void recursionPrintPreffixE(BinaryTreeNode<string> *root);//递归调用打印前缀表达式 111 void recursionPrintSuffixE(BinaryTreeNode<string> *root);//递归调用打印后缀表达式 112 bool shouldPrintLeftBracket(const stack<BinaryTreeNode<string>*> &nodeStack ,BinaryTreeNode<string> *pointer,int leftOrRight);//用于输出中缀表达式时判断是否需要输出左括号 113 void recursionDeleteAll(BinaryTreeNode<string> *root); 114 public: 115 ExpressionBinaryTree(){root = NULL;}; 116 ~ExpressionBinaryTree(){clear();}; 117 void buildBTreeByPreffixE();//以前缀表达式构建二叉树 118 void buildBTreeByInfixE();//以中缀表达式构建二叉树 119 void buildBTreeBySuffixE();//以后缀表达式构建二叉树 120 void printEBTree();//打印二叉树字符图 121 void printPreffixE(){recursionPrintPreffixE(root); cout << endl;}//将递归调用封装,只留给用户打印接口 122 void printSuffixE(){recursionPrintSuffixE(root); cout << endl;}//将递归调用封装,只留给用户打印接口 123 void printInfixE(); 124 static const int LEFT = 0;//为左子结点 125 static const int RIGHT = 1;//为右子结点 126 127 }; 128 129 bool ExpressionBinaryTree::aIsGreaterOrEqualThanB(char a,char b) 130 { 131 switch (a) 132 { 133 case '*': 134 case '/': 135 return true; 136 case '+': 137 case '-': 138 if(b == '*' || b == '/') 139 return false; 140 return true; 141 case '(': 142 return false; 143 } 144 return false; 145 } 146 147 int ExpressionBinaryTree::getHeight(BinaryTreeNode<string> *root)//求树的高度 148 { 149 if(root == NULL) 150 return 0; 151 int left = getHeight(root->getLeftChild()); 152 int right = getHeight(root->getRightChild()); 153 return left > right ? left+1 : right+1; 154 } 155 156 void ExpressionBinaryTree::printBlank(int n) 157 { 158 for(int i = 0;i < n;++i) 159 cout << " "; 160 } 161 162 void ExpressionBinaryTree::printInRightFormat(string value)//按照格式打印,以便对齐 163 { 164 switch (value.length()) 165 { 166 case 1://如果就1个字符,则在两端打印空格,以便对齐 167 cout << " "; 168 cout << value << " "; 169 break; 170 case 2://如果2个字符,则在其后补一个空格,以便对齐 171 cout << value << " "; 172 break; 173 case 3: 174 cout << value;//如果3个字符,则不用补空格 175 break; 176 } 177 } 178 179 void ExpressionBinaryTree::recursionPrintPreffixE(BinaryTreeNode<string> * root)//递归调用打印前缀表达式 180 { 181 if(root == NULL) 182 return; 183 cout << root->getValue() << " "; 184 recursionPrintPreffixE(root->getLeftChild()); 185 recursionPrintPreffixE(root->getRightChild()); 186 } 187 188 void ExpressionBinaryTree::recursionPrintSuffixE(BinaryTreeNode<string> * root)//递归调用打印后缀表达式 189 { 190 if(root == NULL) 191 return; 192 recursionPrintSuffixE(root->getLeftChild()); 193 recursionPrintSuffixE(root->getRightChild()); 194 cout << root->getValue() << " "; 195 } 196 197 bool ExpressionBinaryTree::shouldPrintLeftBracket(const stack<BinaryTreeNode<string> *> &nodeStack ,BinaryTreeNode<string> *pointer ,int leftOrRight)//是否应该添加左括号 198 { 199 if(nodeStack.empty()) 200 return false; 201 if(pointer == NULL) 202 return false; 203 char a = nodeStack.top()->getValue().c_str()[0];//a b 为栈中父子关系的两个结点值得首字母(为了区分是数字还是操作符) 204 char b = pointer->getValue().c_str()[0]; 205 if(b >= '0' && b <= '9')//如果是数字,则不用打括号 206 return false; 207 if(leftOrRight == LEFT)//如果pointer是左结点 208 { 209 switch (a) 210 { 211 case '*': 212 case '/': 213 if(b == '*' || b == '/') 214 return false; 215 return true; 216 case '+': 217 case '-': 218 return false; 219 } 220 } 221 else if(leftOrRight == RIGHT)//如果pointer是右结点 222 { 223 switch (a) 224 { 225 case '*': 226 case '/': 227 return true; 228 case '+': 229 case '-': 230 if(b == '+' || b == '-') 231 return true; 232 return false; 233 } 234 } 235 return false; 236 } 237 238 void ExpressionBinaryTree::recursionDeleteAll(BinaryTreeNode<string> *root) 239 { 240 if(root->getLeftChild() != NULL) 241 recursionDeleteAll(root->getLeftChild()); 242 if(root->getRightChild() != NULL) 243 recursionDeleteAll(root->getRightChild()); 244 delete root; 245 } 246 247 void ExpressionBinaryTree::buildBTreeByPreffixE() 248 { 249 clear(); 250 root = new BinaryTreeNode<string>(); 251 char c; 252 cout << "->请输入前缀表达式,以=结尾." << endl; 253 cout << "->:"; 254 cin >> c; 255 stack<BinaryTreeNode<string> *> parentStack;//用于保存存放父结点 256 BinaryTreeNode<string> *pointer = root;//用于指向下一个保存数据的结点 257 string blankStr = ""; 258 double tempDouble = 0; 259 string tempStr;//用于输入流,将浮点数转换成字符串 260 while(c != '=') 261 { 262 switch (c) 263 { 264 case '+': 265 case '-': 266 case '*': 267 case '/': 268 pointer->setValue(c+blankStr);//设置当前结点的值 269 pointer->setLeftChild(new BinaryTreeNode<string>());//生成左结点 270 parentStack.push(pointer); 271 pointer = pointer->getLeftChild(); 272 break; 273 default: 274 cin.putback(c); 275 cin >> tempDouble; 276 stringstream sss; 277 sss << tempDouble; 278 sss >> tempStr; 279 pointer->setValue(tempStr); 280 281 pointer = parentStack.top(); 282 while(pointer->getRightChild()!=NULL) 283 { 284 parentStack.pop();//找到按前序遍历的下一个结点 285 if(parentStack.empty()) 286 break; 287 pointer = parentStack.top(); 288 } 289 if(parentStack.empty())//如果此时栈空则表明表达式已经构建完成 290 break; 291 pointer->setRightChild(new BinaryTreeNode<string>());//找到了按前序遍历的下一个结点位置并生成结点 292 pointer = pointer->getRightChild(); 293 break; 294 } 295 cin >> c; 296 } 297 298 } 299 300 void ExpressionBinaryTree::buildBTreeByInfixE()//构造中缀表达式二叉树 301 { 302 clear(); 303 root = new BinaryTreeNode<string>(); 304 char c; 305 cout << "->请输入中缀表达式,以=结尾." << endl; 306 cout << "->:"; 307 cin >> c; 308 stack<BinaryTreeNode<string> *> opd;//操作数栈 //为了方便统一管理,操作数和操作符全部定义为string类型 309 stack<string> opt;//操作符栈 310 double tempDouble = 0; 311 string tempStr;//用于输入流,将浮点数转换成字符串 312 string blankStr = ""; 313 while(c != '=') 314 { 315 switch (c) 316 { 317 case '+': 318 case '-': 319 case '*': 320 case '/': 321 while(!opt.empty() && aIsGreaterOrEqualThanB(opt.top().c_str()[0],c))//如果栈顶操作符优先级高于读入操作符优先级,则表名应该先计算栈顶操作符 322 { 323 BinaryTreeNode<string> *secondOpd = opd.top(); 324 opd.pop(); 325 BinaryTreeNode<string> *firstOpd = opd.top(); 326 opd.pop();//从操作数栈取出两个操作数 327 opd.push(new BinaryTreeNode<string>(opt.top(),firstOpd,secondOpd));//将操作数和操作符组成一个新结点存入栈中 328 opt.pop(); 329 } 330 opt.push(c + blankStr);//将读入操作符入栈 331 break; 332 case '(': 333 opt.push(c + blankStr);//遇到左括号直接入栈 334 break; 335 case ')': 336 while(!opd.empty() && opt.top().c_str()[0] != '(')//为了防止冗赘括号,但未检测括号不匹配 337 { 338 BinaryTreeNode<string> *secondOpd = opd.top(); 339 opd.pop(); 340 BinaryTreeNode<string> *firstOpd = opd.top(); 341 opd.pop();//从操作数栈取出两个操作数 342 opd.push(new BinaryTreeNode<string>(opt.top(),firstOpd,secondOpd));//将操作数和操作符组成一个新结点存入栈中 343 opt.pop(); 344 } 345 opt.pop();//将左括号出栈 346 break; 347 default://如果是操作数,直接包装成结点入栈 348 cin.putback(c); 349 cin >> tempDouble; 350 stringstream sss; 351 sss << tempDouble; 352 sss >> tempStr; 353 opd.push(new BinaryTreeNode<string>(tempStr)); 354 break; 355 } 356 cin >> c; 357 } 358 while(!opt.empty() && aIsGreaterOrEqualThanB(opt.top().c_str()[0],c))//如果栈顶操作符优先级高于读入操作符优先级,则表名应该先计算栈顶操作符 359 { 360 BinaryTreeNode<string> *secondOpd = opd.top(); 361 opd.pop(); 362 BinaryTreeNode<string> *firstOpd = opd.top(); 363 opd.pop();//从操作数栈取出两个操作数 364 opd.push(new BinaryTreeNode<string>(opt.top(),firstOpd,secondOpd));//将操作数和操作符组成一个新结点存入栈中 365 opt.pop(); 366 } 367 root = opd.top();//此时操作数栈中唯一元素即为根元素 368 opd.pop(); 369 } 370 371 void ExpressionBinaryTree::buildBTreeBySuffixE() 372 { 373 clear(); 374 char c; 375 cout << "->请输入后缀表达式,以=结尾." << endl; 376 cout << "->:"; 377 cin >> c; 378 stack<BinaryTreeNode<string> *> opdStack;//抽象意义上为操作数栈,但实际为操作数和操作符构成的结点栈 379 double tempDouble = 0; 380 string tempStr;//用于输入流,将浮点数转换成字符串 381 string blankStr = ""; 382 while(c != '=') 383 { 384 switch (c) 385 { 386 case '+': 387 case '-': 388 case '*': 389 case '/': 390 { 391 BinaryTreeNode<string> *secondOpd = opdStack.top(); 392 opdStack.pop(); 393 BinaryTreeNode<string> *firstOpd = opdStack.top(); 394 opdStack.pop(); 395 opdStack.push(new BinaryTreeNode<string>(c+blankStr,firstOpd,secondOpd)); 396 break; 397 } 398 default: 399 cin.putback(c); 400 cin >> tempDouble; 401 stringstream sss; 402 sss << tempDouble; 403 sss >> tempStr; 404 opdStack.push(new BinaryTreeNode<string>(tempStr)); 405 break; 406 } 407 cin >> c; 408 } 409 root = opdStack.top();//此时操作数栈中唯一元素即为根元素 410 opdStack.pop(); 411 } 412 413 void ExpressionBinaryTree::printEBTree() 414 { 415 int height = getHeight(root); 416 int headIndentation;//行首缩进空格数 417 int InIndentation;//行中单位数据间隔空格数 418 queue<BinaryTreeNode<string> *> nodeQueue;//结点队列 419 nodeQueue.push(root);//将根结点入队列以便第一次操作 420 BinaryTreeNode<string> *pointer; 421 for(int i = 1;i <= height;++i) 422 { 423 headIndentation = (int)2*pow(2.0,double(height)-i)-2;//根据层数获得行首缩进空格数 424 printBlank(headIndentation); 425 InIndentation = (int)2*pow(2.0,double(height)-i+1)-3;//根据高度和层数计算行中单位数据间隔空格数 426 for(int j = 0;j < pow(2.0,double(i)-1)&&!nodeQueue.empty();++j)//遍历第i层结点 427 { 428 pointer = nodeQueue.front(); 429 if(pointer == NULL)//如果是空,则直接输行中单位数据间隔空格数+3个空格(数据占3位,无数据则用空格补全) 430 { 431 printBlank(InIndentation+3); 432 nodeQueue.pop(); 433 nodeQueue.push(NULL); 434 nodeQueue.push(NULL);//向队列内加入两个空子树,当作占位符,以便在无结点的地方输出空格 435 } 436 else 437 { 438 printInRightFormat(pointer->getValue()); 439 printBlank(InIndentation); 440 nodeQueue.pop(); 441 nodeQueue.push(pointer->getLeftChild());//左右子树入队列 442 nodeQueue.push(pointer->getRightChild()); 443 } 444 } 445 cout << endl; 446 } 447 } 448 449 void ExpressionBinaryTree::printInfixE() 450 { 451 stack<BinaryTreeNode<string> *> nodeStack;//结点栈,遍历使用 452 BinaryTreeNode<string> *pointer = root; 453 list<BinaryTreeNode<string> *> nodeList;//用于记录在哪些元素被输出之后要输出反括号 454 while(!nodeStack.empty() || pointer != NULL) 455 { 456 while(pointer != NULL)//一直向左子结点走,找到左子结点时,经过的结点已全部入栈 457 { 458 if(shouldPrintLeftBracket(nodeStack,pointer,LEFT))//如果应该添加左括号,为左子结点的情况下 459 { 460 BinaryTreeNode<string> * temp = pointer->getRightChild();//找到应该在输出哪个结点后输出右括号 461 while(temp->getRightChild() != NULL) 462 temp = temp->getRightChild(); 463 nodeList.push_back(temp);//将该位置放入序列中,供查询使用 464 cout << "("; 465 } 466 nodeStack.push(pointer); 467 pointer = pointer->getLeftChild(); 468 } 469 cout << nodeStack.top()->getValue();//输出结点 470 list<BinaryTreeNode<string> *>::iterator it = find(nodeList.begin(),nodeList.end(),nodeStack.top()); 471 while(it != nodeList.end())//若栈顶结点(即当前输出结点)为前面记录的应该输出右括号的结点时,输出右括号,可能有多个右括号需要输出,所以循环 472 { 473 cout << ")"; 474 nodeList.erase(it); 475 it = find(nodeList.begin(),nodeList.end(),nodeStack.top()); 476 } 477 pointer = nodeStack.top()->getRightChild();//所有左结点已经走完,向右走一个 478 if(shouldPrintLeftBracket(nodeStack,pointer,RIGHT))//如果应该添加左括号,为右子结点的情况下 479 { 480 BinaryTreeNode<string> * temp = pointer->getRightChild(); 481 while(temp->getRightChild() != NULL) 482 temp = temp->getRightChild(); 483 nodeList.push_back(temp); 484 cout << "("; 485 } 486 nodeStack.pop(); 487 } 488 cout << endl; 489 } 490 491 void printPrompting()//输出提示信息 492 { 493 cout << "->请选择要输入的表达式种类:" << endl; 494 cout << "->1:前缀表达式.2:中缀表达式.3:后缀表达式.(输入q退出)" << endl; 495 cout << "->:"; 496 } 497 498 int _tmain(int argc, _TCHAR* argv[]) 499 { 500 ExpressionBinaryTree ebt; 501 char c; 502 printPrompting(); 503 cin >> c; 504 while(c != 'q') 505 { 506 switch(c) 507 { 508 case '1': 509 ebt.buildBTreeByPreffixE(); 510 cout << "----------------------------------------------------" << endl; 511 cout << "->通过前缀表达式构建的二叉树为:" << endl; 512 ebt.printEBTree(); 513 break; 514 case '2': 515 ebt.buildBTreeByInfixE(); 516 cout << "----------------------------------------------------" << endl; 517 cout << "->通过中缀表达式构建的二叉树为:" << endl; 518 ebt.printEBTree(); 519 break; 520 case '3': 521 ebt.buildBTreeBySuffixE(); 522 cout << "----------------------------------------------------" << endl; 523 cout << "->通过后缀表达式构建的二叉树为:" << endl; 524 ebt.printEBTree(); 525 break; 526 default: 527 cout << "->序号选择错误,请重新输入。" << endl; 528 printPrompting(); 529 cin >> c; 530 continue; 531 } 532 cout << "->此表达式二叉树对应的前缀表达式为:" << endl; 533 cout << "->"; 534 ebt.printPreffixE(); 535 cout << "->此表达式二叉树对应的中缀表达式为:" << endl; 536 cout << "->"; 537 ebt.printInfixE(); 538 cout << "->此表达式二叉树对应的后缀表达式为:" << endl; 539 cout << "->"; 540 ebt.printSuffixE(); 541 cout << "----------------------------------------------------" << endl; 542 printPrompting(); 543 cin >> c; 544 } 545 }