PTA 二叉搜索树的插入序列

7-2 二叉搜索树的插入序列

二叉搜索树定义为:
左子树仅包含小于根结点的元素;
右子树仅包含大于根结点的元素;
左右子树均为二叉搜索树。
一棵二叉搜索树可以有不同的插入顺序。例如,对于如下的二叉搜索树
在这里插入图片描述
插入序列可以是 3 2 1 4 6 5, 也可以是 3 2 4 1 6 5 但不可以是 3 2 4 5 6 1。
下面给出一棵二叉搜索树的先序遍历序列,请编写程序求出该树的插入序列个数。考虑到总数可能非常大,请输出总数对 1000000007 (10^​9+7)取余的结果。

输入格式:

第一行给出一个整数 N (0<N<=100),表示二叉树中元素个数;
第二行给出 N 个正整数,以空格分隔,表示二叉树的先序遍历序列;

输出格式:

在一行中输出插入序列总数。
输入样例:

6
3 2 1 4 6 5

输出样例:

10

当前子树插入序列个数N(T)=C(num_l,num_r+num_l)*N( TL )*N( TR );
num_l为左子树元素个数,num_r为右子树元素个数,N(TL)为左子树插入序列个数,N(TR)为右子树插入序列个数。后序遍历递归求N(T)。

C代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int ElementType;
typedef struct BiTNode{
    ElementType data;
    long long n;
    int num;
    struct BiTNode *lchild;
    struct BiTNode *rchild;
}BiTNode,*BiTree;
BiTree CreatBinTree(int *pre,int n );
const int N = 100 + 5;
const int MOD = (int)1e9 + 7;
int C[N][N];//C[n][m]就是C(n,m),n>m
void init(){//杨辉三角求组合数防爆必备。常规求组合数会溢出,推荐用递推式求组合数。
    for(int i = 0; i < N; i ++){
        C[i][0] = C[i][i] = 1;
        for(int j = 1; j < i; j ++){
            C[i][j] = C[i-1][j] + C[i-1][j-1];
            C[i][j] %= MOD;
        }
    }
}
void postorder( BiTree T)//后序遍历为结点添加种类数n
{
    if(T)//树不空
    {
      postorder(T->lchild);
      postorder(T->rchild);

      if(!(T->lchild)&&!(T->rchild))//叶子结点,就1种插入顺序
          T->n=1;
      else if((T->lchild)&&!(T->rchild))//只有左子树,插入顺序个数和左子树的一样。
          T->n=T->lchild->n;
      else if(!(T->lchild)&&(T->rchild))//只有右子树,插入顺序个数和右子树的一样。
          T->n=T->rchild->n;
      else//左右子树均存在。N(T)=C(num_l,num_r+num_l)*N( TL )*N( TR )
          T->n=(T->lchild->n)*(T->rchild->n)%MOD*C[T->lchild->num+T->rchild->num][T->lchild->num]%MOD;
    }
};

int main()
{
    init();
    BiTree T;
    int prelist[101];
    int length;
    scanf("%d",&length);
    for(int i=0;i<length;i++)
    {   scanf("%d",&prelist[i]);}
        prelist[length]=-1;//确定最后一个结点位置。
        T=CreatBinTree(prelist,length);
        postorder(T);
        printf("%lld",T->n);
    return 0;
}
BiTree CreatBinTree(int *pre,int n)//先序造树
{
    BiTree T;
    int i;
    if(n<=0||pre[0]==-1) return NULL;//pre[0]==-1说明已经到了序列末尾。

    T=(BiTree)malloc(sizeof(BiTNode));
    T->data=pre[0];
    T->n=1;
    T->num=n;//num确定当前子树元素个数
    for(i=1;pre[i]<pre[0];i++);//i为下一根结点位置
    T->lchild=CreatBinTree(pre+1,i-1);
    T->rchild=CreatBinTree(pre+i,n-i);
    return T;
}

### 二叉搜索树的结构 二叉搜索树(Binary Search Tree, BST),是一种特殊的二叉树,满足如下条件: - 对于任意节点`N`而言,在其左子树中的每一个节点的数据域的值都小于它自己的数据域的值; - 而在其右子树中的每一个节点的数据域的值又都大于或等于它自己的数据域的值[^5]。 这种特性使得二叉搜索树非常适合用于快速查找、插入和删除操作。当树保持平衡时,这些操作的时间复杂度接近O(log n),其中n是节点数量。 ### PTA 中关于二叉搜索树的相关题目解释 #### 判断是否为同一棵二叉搜索树PTA平台上的一个典型问题是给出多个插入序列来构建二叉搜索树,并询问这些不同顺序能否生成相同的BST。这个问题的核心在于理解如何通过特定规则建立唯一的BST实例。具体来说,即使两个不同的插入序列可能最终形成外观相似甚至完全一致的BST形态,但如果遵循严格的构造逻辑——即每次总是优先尝试向左侧分支添加较小数值直到无法再加为止才转向右侧处理较大数值,则只有当所有对应位置处待加入元素相等的情况下才会真正创建出相同拓扑结构下的两棵树[^1]。 #### 前序遍历验证二叉搜索树及其镜像 另一个常见的练习涉及从前序遍历结果出发去检验某给定数组是不是某个合法BST或是它的镜像版本经过同样方式访问后的产物。这里的关键点是要明白标准BST与其反射形式之间存在的区别仅限于左右方向互换了而已;因此可以通过调整比较关系来进行区分[^3]。 ### C语言实现示例 下面提供了一个简单的C函数用来检查给定的一系列整数是否能够构成同一个二叉搜索树: ```c #include <stdbool.h> #include <stdlib.h> typedef struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; } TreeNode; TreeNode* insertIntoBST(TreeNode* root, int key){ if (!root) { TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode)); node->val = key; node->left = NULL; node->right = NULL; return node; } if (key < root->val) root->left = insertIntoBST(root->left, key); else root->right = insertIntoBST(root->right, key); return root; } bool isSameTree(TreeNode* p, TreeNode* q) { if (!p && !q) return true; // Both are null if (!p || !q) return false;// One of them is not null return (p->val == q->val && isSameTree(p->left , q->left ) && isSameTree(p->right, q->right)); } ``` 此代码片段展示了基本的功能模块,包括新节点插入以及对比两棵树是否相等等功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

椰子zii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值