PAT甲级真题 1099 Build A Binary Search Tree (30分) C++实现 (二叉搜索树BST inorder中序遍历得到有序数列)

本文介绍了一种在不构建完整二叉搜索树的情况下,通过中序遍历序列填充节点并进行层序遍历的方法。利用vector模拟树结构,通过节点下标定位左右孩子,实现对二叉搜索树的有效遍历。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

A Binary Search Tree (BST) is recursively defined as a binary tree which has the following properties:
The left subtree of a node contains only nodes with keys less than the node’s key.
The right subtree of a node contains only nodes with keys greater than or equal to the node’s key.
Both the left and right subtrees must also be binary search trees.
Given the structure of a binary tree and a sequence of distinct integer keys, there is only one way to fill these keys into the tree so that the resulting tree satisfies the definition of a BST. You are supposed to output the level order traversal sequence of that tree. The sample is illustrated by Figure 1 and 2.

在这里插入图片描述

Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N (≤100) which is the total number of nodes in the tree. The next N lines each contains the left and the right children of a node in the format left_index right_index, provided that the nodes are numbered from 0 to N−1, and 0 is always the root. If one child is missing, then −1 will represent the NULL child pointer. Finally N distinct integer keys are given in the last line.
Output Specification:
For each test case, print in one line the level order traversal sequence of that tree. All the numbers must be separated by a space, with no extra space at the end of the line.

Sample Input:

9
1 6
2 3
-1 -1
-1 4
5 -1
-1 -1
7 -1
-1 8
-1 -1
73 45 11 58 82 25 67 38 42

Sample Output:

58 25 82 11 38 67 45 73 42

思路

一开始傻乎乎建了个树…然后又傻乎乎计算节点左侧有多少个节点(设为k),那么该节点的值就是第k+1小的值;然后递归计算其左、右孩子的节点,代码如“建树版”所示。

看了柳神的方法:

  1. 无需建树,只用一个vector模拟树即可,左右孩子可通过下标定位。
  2. 对二叉搜索树BST中序遍历就能得到升序序列。只需将序列排序后,按中序遍历的次序填入节点中即可;

改写了一遍代码,见“中序遍历版”。

代码

中序遍历版:

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

struct Node{
    int l, r, v;
};

void inorder(vector<Node> &nodes, int root, vector<int> &a, int &k){
    if (root==-1) return;
    inorder(nodes, nodes[root].l, a, k);
    nodes[root].v = a[k++];
    inorder(nodes, nodes[root].r, a, k);
}

int main(){
    int n;
    scanf("%d", &n);

    vector<Node> nodes(n);
    for (int i=0; i<n; i++){
        scanf("%d %d", &nodes[i].l, &nodes[i].r);
    }

    vector<int> a(n);
    for (int i=0; i<n; i++){
        scanf("%d", &a[i]);
    }
    sort(a.begin(), a.end());
    
    int k = 0;  //记录遍历次序
    inorder(nodes, 0, a, k);
	//层序遍历了,借助queue,相当于BFS
    queue<int> que;
    que.push(0);
    while (!que.empty()){
        int cur = que.front();
        que.pop();
        if (cur!=0) printf(" ");
        printf("%d", nodes[cur].v);
        if (nodes[cur].l!=-1) que.push(nodes[cur].l);
        if (nodes[cur].r!=-1) que.push(nodes[cur].r);
    }

    return 0;
}

建树版:

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

struct Node{
    Node *l;
    Node *r;
    int v;
};
//计算以root为根子树节点总数
int totalNodes(Node *root){
    int num = 0; 
    if (root!=NULL) {
        queue<Node*> que;
        que.push(root);
        while (!que.empty()){
            root = que.front();
            que.pop();
            num++;
            if (root->l) que.push(root->l);
            if (root->r) que.push(root->r);
        }
    }
    return num;
}

void fillNum(Node *root, vector<int> &a, int start){
    if (root==NULL) return;
    int pos = totalNodes(root->l);  //左子树有几个节点
    root->v = a[start+pos];
    fillNum(root->l, a, start);
    fillNum(root->r, a, start+pos+1);
}

int main(){
    int n;
    scanf("%d", &n);

    vector<Node> nodes(n);
    for (int i=0; i<n; i++){
        int l, r;
        scanf("%d %d", &l, &r);
        if (l!=-1) nodes[i].l = &nodes[l];
        if (r!=-1) nodes[i].r = &nodes[r];
    }

    vector<int> a(n);
    for (int i=0; i<n; i++){
        scanf("%d", &a[i]);
    }
    sort(a.begin(), a.end());
    
    fillNum(&nodes[0], a, 0);

    queue<Node*> que;
    que.push(&nodes[0]);
    a.clear();
    while (!que.empty()){
        Node *cur = que.front();
        que.pop();
        a.push_back(cur->v);
        if (cur->l) que.push(cur->l);
        if (cur->r) que.push(cur->r);
    }

    printf("%d", a[0]);
    for (int i=1; i<n; i++){
        printf(" %d", a[i]);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值