板子:判断二叉排序树(2022)
BST 的中序序列是严格递增的。中序遍历时记住上一个访问的结点
pre,一旦当前值pre的值,就不是 BST。
代码:二叉链表
bool isBST(BiTree T, BiTNode *&pre) { // 调用前 pre = NULL;pre:中序遍历的上一个结点
if (T == NULL) return true; // 空树是 BST
if (!isBST(T->lchild, pre)) return false; // 左子树不是 BST,直接失败
if (pre != NULL && pre->data >= T->data) return false; // 当前值不大于前一个:不是严格递增
pre = T; // 当前结点成为下一个结点的「上一个」
return isBST(T->rchild, pre);
}
// 调用:BiTNode *pre = NULL; isBST(T, pre);pre 要写成引用 BiTNode *&pre:递归里改了它,外层要能看到。
代码:顺序存储(2022 原题)
#define MAX_SIZE 100
typedef struct { // 2022 原题给的结构
int SqBiTNode[MAX_SIZE]; // 结点值都是正整数,不存在的结点用 -1 表示
int ElemNum; // 数组中元素的个数
} SqBiTree;
bool judgeBST(SqBiTree &bt, int k, int &pre) { // 中序遍历下标为 k 的子树;调用前 pre = 0
if (k >= bt.ElemNum || bt.SqBiTNode[k] == -1) return true; // 超出数组或结点不存在:空树
if (!judgeBST(bt, 2 * k + 1, pre)) return false; // 左孩子的下标是 2k+1
if (bt.SqBiTNode[k] <= pre) return false; // 不是严格递增
pre = bt.SqBiTNode[k];
return judgeBST(bt, 2 * k + 2, pre); // 右孩子的下标是 2k+2
}
// 调用:int pre = 0; judgeBST(bt, 0, pre);复杂度:两种都是时间
关键边界
| 位置 | 为什么 |
|---|---|
| 孩子下标 | 数组从 0 开始存根。如果从 1 开始存,孩子是 |
pre 初值为 0 | 原题保证结点值都是正整数,所以 0 比任何结点都小 |
判失败用 >= / <= | 要求严格递增,值相等也不是 BST |
k >= bt.ElemNum 先判 | 下标越界时就不能再读 SqBiTNode[k] 了 |
易错点
- 只比较父子是不够的。例如根为 10,左孩子为 5,5 的右孩子为 15:每一对父子都满足大小关系,但 15 在 10 的左子树里。必须用中序,或者给每个结点传下上下界。
- 顺序存储时,
SqBiTree用引用传参,避免每层递归都复制一遍整个数组。原题答案按值传也对。
链接
- 📕 返回:数据结构代码板子
- ⬅️ 上一篇:表达式树转中缀表达式
- ➡️ 下一篇:判断完全二叉树与平衡二叉树
- 🔗 7.3.1 二叉排序树