引自强大而免费的微信小程序:皆我工具箱。
思路:
根据题目提供的存储规则,对于每个结点,如果有左子树,则存储其左子树的最大值;如果没有左子树但有右子树,则不存储任何值;否则为叶子结点时,如果有中序后继,则可以删除,反之不存储任何值。
首先构建二叉搜索树,根据给定的先序遍历结果。
然后对每个结点进行压缩处理,处理规则见上述。
具体步骤如下:
- 读取输入,得到BST的总结点个数n和先序遍历结果preorder。
- 创建一个结点类Node,包含数据value、子树元素数目count、中序遍历前驱predecessor,以及左右子结点left和right。
- 定义一个递归函数buildBST,构建二叉搜索树。在buildBST中,如果preorder为空,则返回空结点;否则,创建一个新的结点,将第一个元素作为结点的数据。根据上述存储规则,如果preorder的第二个元素pre大于当前节点的value,则preorder的第一个元素是当前节点的左子树的最大值,否则没有左子树。递归地构建左子树和右子树。
- 构建完毕后,根据题目要求输出经过压缩后新BST的先序遍历结果。可以采用先序遍历的方式遍历树,在访问每个结点时输出其数据value和前驱结点的数据predecessor。注意,如果一个结点既没有左子树也没有右子树(即叶子结点),并且没有中序后继,则前驱结点的数据predecessor为"-",否则为左子树的最大值。
具体实现见下面的代码:
#include <iostream>
#include <vector>
using namespace std;
struct Node {
int value;
int count;
int predecessor;
Node* left;
Node* right;
Node(int v): value(v), count(0), predecessor(-1), left(nullptr), right(nullptr) {}
};
Node* buildBST(vector<int>& preorder, int& idx) {
if (idx >= preorder.size()) {
return nullptr;
}
int value = preorder[idx];
Node* node = new Node(value);
idx++;
if (idx < preorder.size() && preorder[idx] > value) {
node->predecessor = preorder[idx];
node->left = buildBST(preorder, idx);
} else {
node->left = nullptr;
}
node->right = buildBST(preorder, idx);
return node;
}
void preorderTraversal(Node* root) {
if (root == nullptr) {
return;
}
cout << root->value;
if (root->predecessor != -1) {
cout << " " << root->predecessor;
} else if (root->left == nullptr && root->right == nullptr) {
cout << " -";
}
cout << " ";
preorderTraversal(root->left);
preorderTraversal(root->right);
}
int main() {
int n;
cin >> n;
vector<int> preorder(n);
for (int i = 0; i < n; i++) {
cin >> preorder[i];
}
int idx = 0;
Node* root = buildBST(preorder, idx);
preorderTraversal(root);
return 0;
}