通常来说可以通过中缀表达式直接求得后缀表达式的。但是题目里要求先建树再利用二叉树求后缀表达式,在此记录一下。
思想:可分成如下步骤:
(1)从当前传入的表达式中找出不在括号内,最靠后,优先级最低的一个运算符,这就是当前的根节点,并记录其位置
(2)利用上一步的运算符建立根节点,其左右子树分别赋值为此函数返回值,传入参数分别为选中运算符的左侧部分和右侧部分
(3)返回当前根节点
// 比较两个运算符的优先级
// -1:s1<s2 0:s1==s2 1:s1>s2
int compare(string s1, string s2){
if(s1.empty()){
return 1;
}
if((s1=="+" || s1=="-" )&& (s2=="*" || s2=="/")){
return -1;
}
if(((s1=="+" || s1=="-") && (s2=="+" || s2=="-")) ||
((s1=="*" || s1=="/") && (s2=="*" || s2=="/"))){
return 0;
}
if((s1=="*" || s1=="/") && (s2=="+" || s2=="-")){
return 1;
}
}
BiTree createTree(vector<string> data, int start, int end){
// 去掉最外侧括号
if(data[start] == "(" && data[end] == ")"){
start++; end--;
}
BiTree T = new BiTNode;
int size = end-start+1;
if(size <= 0){
return NULL;
}
// 长度为1, 数字直接作为叶结点
else if(size == 1){
T->s = data[start];
T->lchild = T->rchild = NULL;
return T;
} else {
string chosen; // 记录选中的运算符
int lcount = 0, mid; // lcount记录左括号数量,mid记录选中运算符位置
for(int i=start; i<=end; i++){
if(data[i] == "(") lcount++; // 这两行用于记录括号匹配是否结束
if(data[i] == ")") lcount--;
// isFour()用于判断是否是四则运算符, lcount==0表示外层不存在括号,
// compare()用于比较两运算符优先级
if(isFour(data[i]) && lcount==0 && compare(chosen, data[i]) != -1){
chosen = data[i]; mid = i;
}
}
T->s = chosen;
// 对左右子树分别赋值,递归调用此函数
T->lchild = createTree(data, start, mid-1);
T->rchild = createTree(data, mid+1, end);
return T;
}
}
该二叉树的后序遍历序列即为后缀表达式