1015 | 你们要的中缀表达式树
一开始没注意,以为数值结点值是0 - 9,后来才发现是0 - 10 。= =
但是懒得改太多还是用了char存,printf(“%c”, char(‘9’+1))确认了一下不会和运算符重合= =
- 第一版
先中序遍历(注意括号的处理),输出中缀表达式。
后序遍历,转成后缀表达式,再stack模拟求值。(这个思路昨天的博客刚写到……
#include
#include
#include
#include
#include
using namespace std;
struct Node {
char value;
int lchild = -1, rchild = -1;
} btree[32];
string suffix_exp;
bool isRoot[32];
int _root = -1;
void in_traverse(int root) {
if (root != _root && (btree[root].lchild != -1 || btree[root].rchild != -1)) printf("(");
if (btree[root].lchild != -1) in_traverse(btree[root].lchild);
btree[root].value == char('0' + 10) ? printf("10") : printf("%c", btree[root].value);
if (btree[root].rchild != -1) in_traverse(btree[root].rchild);
if (root != _root && (btree[root].lchild != -1 || btree[root].rchild != -1)) printf(")");
}
void post_traverse(int root) {
if (btree[root].lchild != -1) post_traverse(btree[root].lchild);
if (btree[root].rchild != -1) post_traverse(btree[root].rchild);
suffix_exp += btree[root].value;
}
double calc(const string &str) {
stack nums;
int size = str.length(), i = 0;
while (i < size) {
if (isdigit(str[i]) || str[i] == char('0' + 10))
nums.push(str[i] - '0');
else {
double n2 = nums.top(), n1;
nums.pop();
n1 = nums.top();
nums.pop();
switch (str[i]) {
case '+':
nums.push(n1 + n2);
break;
case '-':
nums.push(n1 - n2);
break;
case '*':
nums.push(n1 * n2);
break;
case '/':
nums.push(n1 / n2);
break;
}
}
i++;
}
return nums.top();
}
int main() {
int nn;
string value;
cin >> nn;
fill(isRoot, isRoot + nn, true);
for (int i = 0; i < nn; ++i) {
cin >> value;
if (isdigit(value[0])) btree[i].value = char(stoi(value) + '0');
else btree[i].value = value[0];
}
string lc, rc;
for (int i = 0; i < nn; ++i) {
cin >> lc >> rc;
if (lc[0] != '-') isRoot[btree[i].lchild = stoi(lc)] = false;
if (rc[0] != '-') isRoot[btree[i].rchild = stoi(rc)] = false;
}
for (int i = 0; i < nn; ++i) {
if (isRoot[i]) {
_root = i;
break;
}
}
in_traverse(_root);
post_traverse(_root);
printf(" %.2lf\n", calc(suffix_exp));
return 0;
}
- 第二版
感觉自己好像绕弯路了 = =,看了晴神的题解,果然= =
直接在中序遍历时,顺带着求值啊。 - 表达式树的叶子结点一定是数,非叶子结点一定是运算符。
- 只含二目运算符的表达式形成的树,一定只有度为2(运算符)和度为0(数)的点。
- 那么,若为运算符,递归的求这个结点的值;若为叶子,直接返回该结点的值。
#include
#include
#include
#include
using namespace std;
struct Node {
char value;
int lchild = -1, rchild = -1;
} btree[32];
bool isRoot[32];
int _root = -1;
// 有孩子的都是operator结点,双目运算符,必有两个孩子
double in_traverse(int root) {
double res1, res2, res;
bool isLeaf = true;
if (root != _root && (btree[root].lchild != -1 || btree[root].rchild != -1)) printf("(");
if (btree[root].lchild != -1) {
isLeaf = false;
res1 = in_traverse(btree[root].lchild);
}
btree[root].value == char('0' + 10) ? printf("10") : printf("%c", btree[root].value);
if (btree[root].rchild != -1) res2 = in_traverse(btree[root].rchild);
if (root != _root && (btree[root].lchild != -1 || btree[root].rchild != -1)) printf(")");
if (!isLeaf)
switch (btree[root].value) {
case '+':
res = res1 + res2;
break;
case '-':
res = res1 - res2;
break;
case '*':
res = res1 * res2;
break;
case '/':
res = res1 / res2;
break;
}
return isLeaf ? btree[root].value - '0' : res;
}
int main() {
int nn;
string value;
cin >> nn;
fill(isRoot, isRoot + nn, true);
for (int i = 0; i < nn; ++i) {
cin >> value;
if (isdigit(value[0])) btree[i].value = char(stoi(value) + '0');
else btree[i].value = value[0];
}
string lc, rc;
for (int i = 0; i < nn; ++i) {
cin >> lc >> rc;
if (lc[0] != '-') isRoot[btree[i].lchild = stoi(lc)] = false;
if (rc[0] != '-') isRoot[btree[i].rchild = stoi(rc)] = false;
}
for (int i = 0; i < nn; ++i) {
if (isRoot[i]) {
_root = i;
break;
}
}
printf(" %.2lf\n", in_traverse(_root));
return 0;
}
另外,可以思考一下,怎么由表达式建树。
1016 | 二叉树の狂欢
一道巨无霸……
- 思路
- 是AVL tree吗?
(递归计算子树height)
不是,输出不平衡结点个数,over; 是,转2。 - 是完全二叉树吗?
(层序遍历⚠️:注意判断条件,顺便给3作准备,用数组存CBT)
不是,输出满结点的最后一层的层号,over;是,转3。 - 将CBT调整为大顶堆,输出swap次数,over。(详见 二叉树|堆 那篇= =
- 是AVL tree吗?
#include
#include
#include
#include
#include
#include
using namespace std;
struct Node {
int key;
int lchild = -1, rchild = -1, height = 0;
} btree[22];
int nn, root, cnt_not_balance = 0, levels[22] = {0};
bool isRoot[22], isAVL = true;
int max_heap[22];
int updateHeight(int curr) {
if (btree[curr].lchild == btree[curr].rchild)
return btree[curr].height = 1; //leaf child == -1
btree[curr].height = max(updateHeight(btree[curr].lchild), updateHeight(btree[curr].rchild)) + 1;
int hl = btree[curr].lchild == -1 ? 0 : btree[btree[curr].lchild].height,
hr = btree[curr].rchild == -1 ? 0 : btree[btree[curr].rchild].height;
if (abs(hl - hr) > 1) {
isAVL = false;
cnt_not_balance++;
}
return btree[curr].height;
}
int max_full_level(int rt) { //if not CBT, return max full level
bool isFull = true;
int index = 0;
queue mq;
levels[rt] = 1;
mq.push(rt);
while (!mq.empty()) {
int temp = mq.front();
mq.pop();
max_heap[index++] = btree[temp].key;
if (!isFull && (btree[temp].lchild != -1 && btree[temp].rchild != -1))
return levels[temp];
if (btree[temp].lchild == -1 && btree[temp].rchild != -1)
return levels[temp];
else {
if (btree[temp].lchild == -1 || btree[temp].rchild == -1)
isFull = false;
if (btree[temp].lchild != -1) {
levels[btree[temp].lchild] = levels[temp] + 1;
mq.push(btree[temp].lchild);
}
if (btree[temp].rchild != -1) {
levels[btree[temp].rchild] = levels[temp] + 1;
mq.push(btree[temp].rchild);
}
}
}
return -1;
}
void downAdjust(int curr, int &cnt) {
while (2 * curr + 1 < nn) {
int li = 2 * curr + 1, ri = 2 * curr + 2;
if (ri >= nn && max_heap[li] > max_heap[curr]) {
swap(max_heap[li], max_heap[curr]);
cnt++;
curr = li;
} else {
if (max(max_heap[li], max_heap[ri]) < max_heap[curr]) break;
if (max_heap[li] > max_heap[ri]) {
swap(max_heap[li], max_heap[curr]);
curr = li;
} else {
swap(max_heap[ri], max_heap[curr]);
curr = ri;
}
cnt++;
}
}
}
int adjustHeap() { //heap index 0 - nn-1 not-leaf: 0 - nn/2-1
int cnt_swap = 0;
for (int i = nn / 2 - 1; i >= 0; --i) {
downAdjust(i, cnt_swap);
}
return cnt_swap;
}
int main() {
scanf("%d", &nn);
for (int i = 1; i <= nn; ++i) {
scanf("%d", &btree[i].key);
isRoot[i] = true;
}
string kv;
for (int i = 1; i <= nn; ++i) {
cin >> kv;
if (kv[0] != '-') isRoot[btree[i].lchild = stoi(kv)] = false;
cin >> kv;
if (kv[0] != '-') isRoot[btree[i].rchild = stoi(kv)] = false;
}
for (int i = 1; i <= nn; ++i) {
if (isRoot[i]) {
root = i;
break;
}
}
updateHeight(root);
if (isAVL) {
int mlevel = max_full_level(root);
if (mlevel == -1) {
puts("OHHHHH HEAP!!!");
printf("%d\n", adjustHeap());
} else {
puts("NOT COMPLETE TREE!!!");
printf("%d\n", mlevel);
}
} else {
puts("NOT AVL TREE!!!");
printf("%d\n", cnt_not_balance);
}
return 0;
}