算法源代碼在 Veeupup Github
考點:
- 二叉搜索樹遍歷方式和性質運用
對於二叉搜索樹,我們規定任一結點的左子樹僅包含嚴格小於該結點的鍵值,而其右子樹包含大於或等於該結點的鍵值。如果我們交換每個節點的左子樹和右子樹,得到的樹叫做鏡像二叉搜索樹。
現在我們給出一個整數鍵值序列,請編寫程序判斷該序列是否爲某棵二叉搜索樹或某鏡像二叉搜索樹的前序遍歷序列,如果是,則輸出對應二叉樹的後序遍歷序列。
輸入格式:
輸入的第一行包含一個正整數N(≤1000),第二行包含N個整數,爲給出的整數鍵值序列,數字間以空格分隔。
輸出格式:
輸出的第一行首先給出判斷結果,如果輸入的序列是某棵二叉搜索樹或某鏡像二叉搜索樹的前序遍歷序列,則輸出
YES
,否側輸出NO
。如果判斷結果是YES
,下一行輸出對應二叉樹的後序遍歷序列。數字間以空格分隔,但行尾不能有多餘的空格。輸入樣例1:
7 8 6 5 7 10 8 11
輸出樣例1:
YES 5 7 6 8 11 10 8
輸入樣例2:
7 8 6 8 5 10 9 11
輸出樣例2:
NO
這道題想考二叉搜索樹性質的運用以及二叉樹的幾種遍歷方式,需要對二叉樹的遍歷方式和搜索二叉樹的性質有比較好的理解,建議畫圖加深理解和推導。
思路:
對於給定的先序遍歷序列,我們可以構建一顆二叉搜索樹,然後根據生成的二叉搜索樹的性質來做。
- 如果生成二叉搜索樹的前序遍歷序列和輸入的序列的一致,那麼直接輸出後序遍歷的值
- 如果不符合 1,那麼需要和這棵樹的鏡像二叉搜索樹的前序遍歷進行比較,但我們此時不需要真的互換每個結點的左右結點,只需要在先序遍歷時先訪問右子結點,此時得到的序列就是鏡像二叉樹的序列。
當我們確定是鏡像二叉樹的序列的時候,我們就可以後序遍歷,但此時後序遍歷的順序會有所區別,應該是先訪問右子樹,再訪問左子樹,最後訪問本身結點的順序來進行後序遍歷,此時得到的就是鏡像二叉樹的後序遍歷。
完整代碼如下:
/*
Author: Veeupup
*/
#include <iostream>
#include <vector>
using namespace std;
const int maxn = 1010;
vector<int> inputOrder, preStr, preMirrorStr,postStr, postMirrorStr; // 保存輸入的前序遍歷的值,保存生成二叉搜索樹的序列
struct node
{
int data;
node *left, *right;
node(int _data): data(_data), left(NULL), right(NULL) {}
};
void insert(node* &root, int val)
{
if(root == NULL)
{
root = new node(val);
return;
}else if(val < root->data) {
insert(root->left, val);
}else {
insert(root->right, val);
}
}
// 後續遍歷的值
void postOrder(node *root) {
if(root == NULL)
return;
postOrder(root->left);
postOrder(root->right);
postStr.push_back(root->data);
}
void postMirrorOrder(node *root) {
if(root == NULL)
return;
postMirrorOrder(root->right);
postMirrorOrder(root->left);
postMirrorStr.push_back(root->data);
}
void preOrder(node *root) {
if(root == NULL)
return;
preStr.push_back(root->data);
preOrder(root->left);
preOrder(root->right);
}
void preMirrorOrder(node *root) {
if(root == NULL)
return;
preMirrorStr.push_back(root->data);
preMirrorOrder(root->right);
preMirrorOrder(root->left);
}
int main()
{
freopen("data.txt", "r", stdin);
int n;
scanf("%d", &n);
int num;
node *root = NULL;
for (int i = 0; i < n; i++)
{
scanf("%d", &num);
insert(root, num);
inputOrder.push_back(num); //保存
}
preOrder(root);
preMirrorOrder(root);
if (inputOrder == preStr)
{
printf("YES\n");
postOrder(root);
for (int i = 0; i < postStr.size(); i++)
{
if(i > 0) {
printf(" ");
}
printf("%d", postStr[i]);
}
}
else if (inputOrder == preMirrorStr)
{
printf("YES\n");
postMirrorOrder(root);
for (int i = 0; i < postMirrorStr.size(); i++)
{
if(i > 0) {
printf(" ");
}
printf("%d", postMirrorStr[i]);
}
}
else
{
printf("NO\n");
}
return 0;
}