首先,感谢https://www.jianshu.com/p/765ed8e6102e作者的文章,为我提供了思路。
然后,说一下问题:要求输入一个中序运算表达式,用二叉树将其存储起来,并且可以得到前序和后序表示。
关键:
- 找出表达式中优先级最小的运算符,作为根节点,然后从其左右分成一个树
- 优先级的大小定义:1. 不同级别之间的顺序是,括号 > 乘除 > 加减; 2. 同级,左边 > 右边
- 要去掉表达式最外层的括号
- 定义一个括号标志,用来记录进入的括号层级,由于括号内优先级最大,找最小优先级运算符时相当于屏蔽掉括号内的运算符
- 定义一个结果标志,用来表示找到的最小优先级运算符是加减还是乘除,有加减就没乘除什么事
- 递归,不停地找表达式的最小优先级运算符,直到表达式的长度小于3,即他不可能再有运算符(我们认为表达式长度至少3,例如负数应该写作(-4)这样)
找到字符串中优先级最小的运算符
// 找到字符串中优先级最小的运算符
function getMinPriorityOpe(exp) {
let bracketFlag = 0; // 括号标志
let resultFlag = 0; // 结果标志
let result;
for (let i = 0; i < exp.length; i++) {
let char = exp.charAt(i);
switch (char) {
case "+":
case "-":
if (bracketFlag === 0) {
resultFlag = 1; // 有了+-肯定就没*/什么事了
result = {
root: char,
left: exp.slice(0, i),
right: exp.slice(i + 1)
}
}
break;
case "*":
case "/":
if (bracketFlag === 0 && resultFlag === 0) {
result = {
root: char,
left: exp.slice(0, i),
right: exp.slice(i + 1)
};
}
break;
case "(":
bracketFlag++;
break;
case ")":
bracketFlag--;
break;
default:
break;
}
}
return result;
}
去掉最外层括号
// 去最外层括号运算
function brackets(exp) {
if (exp.charAt(0) === '(' && exp.charAt(exp.length - 1) === ")") {
return exp.slice(1, -1);
}
return exp;
}
递归实现
// 递归
function recursive(tree) {
if (tree.left.length >= 3) {
tree.left = recursive(getMinPriorityOpe(brackets(tree.left)));
}
if (tree.right.length >= 3) {
tree.right = recursive(getMinPriorityOpe(brackets(tree.right)));
}
return tree
}
// 前序遍历
function print_prefix(tree) {
if (tree.root !== null) {
console.log(tree.root);
if (typeof (tree.left) === 'string') {
console.log(tree.left);
} else {
print_prefix(tree.left);
}
if (typeof (tree.right) === 'string') {
console.log(tree.right)
} else {
print_prefix(tree.right)
}
}
}
// 后序遍历
function print_postfix(tree) {
if (tree.root !== null) {
if (typeof (tree.left) === 'string') {
console.log(tree.left);
} else {
print_postfix(tree.left);
}
if (typeof (tree.right) === 'string') {
console.log(tree.right)
} else {
print_postfix(tree.right)
}
console.log(tree.root);
}
}
// main
let exp = "(1*(2+3)/4*5+6)";
let tree = recursive(getMinPriorityOpe(brackets(exp)));
console.log("前序遍历:")
print_prefix(tree);
console.log("后序遍历:")
print_postfix(tree);
最终前序遍历的结果应该是:+*/*1+23456
后序遍历结果是:123+*4/5*6+
鉴于网上js实现数据结构的资料不是很多,后续有机会的话我会分享更多js数据结构的实现,抛砖引玉,以飨读者。