talk is cheap,show me the code money
二叉排序树:要么是空树,要么是 左子树结点值
<
<
< 根结点值
<
<
< 右子树结点值 的二叉树。
左
<
<
< 根
<
<
< 右,中序遍历可以得到一个递增的序列。
1.插入构建
二叉排序树的插入只会插入到空的结点上面,形成新的叶结点。
每次可以比较,向下移动至正确的空结点上。如果有相同值的结点,那么插入失败。
递归插入:
//递归插入
bool Insert(BSTree &T, int x) {
if (T == NULL) {
T = new BSTNode;
T->data = x;
T->lchild = T->rchild = NULL;
return 1;
}
else if (x == T->data)
return 0;
else if (x < T->data)
return Insert(T->lchild, x); //递归的是T->lchild/rchild,是在原二叉树上生成结点
else
return Insert(T->rchild, x);
}
非递归插入:
//非递归插入
bool Insert2(BSTree &T, int x) {
if (T == NULL) {
T = new BSTNode;
T->data = x;
T->lchild = T->rchild = NULL;
return 1;
}
BSTNode* p = T;
while (p) {
if (p->data > x) {
if(p->lchild)
p = p->lchild;
else {
p->lchild = new BSTNode; //在原二叉树(二叉链表)上面生成结点,需要用p->lchild/rchild才行
p->lchild->data = x; //正如链表生成结点递归的是T->next
p->lchild->lchild = p->lchild->rchild = NULL;
return 1;
}
}
else if (p->data < x) {
if(p->rchild)
p = p->rchild;
else {
p->rchild = new BSTNode;
p->rchild->data = x;
p->rchild->lchild = p->rchild->rchild = NULL;
return 1;
}
}
else
return 0;
}
}
插入构建排序二叉树:
void Create_BST(BSTree& T, int* m, int n) { //m保持了结点值
T = NULL; //n为结点数
int i = 0;
while (i < n) {
Insert2(T, m[i]);
i++; //记得工作指针后移啊,老是忘记
}
}
2.查找
二叉排序树的查找从根节点开始比较,逐层向下,最坏情况是单分支二叉排序树,需要比较n次。
递归查找:
//递归查找
BSTNode* Search(BSTree T, int x) {
if (T->data == x)
return T;
else if (T->data > x)
return Search(T->lchild, x);
else
return Search(T->rchild, x);
}
非递归查找:
//非递归查找
BSTNode* Search2(BSTree T, int x) {
while (T && T->data != x) {
if (T->data > x)
T = T->lchild;
else
T = T->rchild;
//T = T->data > x ? T->lchild : T->rchild;
}
return T;
}
3.删除
分三种情况:
- 叶结点,直接删除
- 只有左/右子树,直接让左/右子树代替自己
- 有左、右子树,用中序前驱/后继结点代替自己。
1.找父结点:
\qquad 因为二叉排序树是二叉链表存储的,众所周知,链表要想删除结点必须要找到其父结点才行,若原地删除,父结点的子指针就会变成野指针。
递归找父结点:
//找父结点
BSTNode* father(BSTree T, BSTNode* p) {
if (T == NULL)
return NULL;
if (T->lchild == p || T->rchild == p)
return T;
else
return father(T->lchild, p) ? father(T->lchild, p) : (father(T->rchild, p) ? father(T->rchild, p) : NULL);
}
层序遍历找父结点:
BSTNode* father2(BSTree T, BSTNode* p) { //层序找到父结点
BSTree Q[100];
int front = 0, rear = 0;
BSTNode* q = T;
Q[rear++] = T;
while (front!=rear) {
q = Q[front++];
if (q->lchild == p || q->rchild == p)
return q;
else {
if (q->lchild) Q[rear++] = q->lchild;
if (q->rchild) Q[rear++] = q->rchild;
}
}
return NULL;
}
2.找中序前驱/后继
因为要保证删除之后仍然保持排序特性,我们只可用其中序前驱、后继替代,只有中序遍历依旧是递增序列。中序前驱、后继也是左、右子树中值最解决p的结点。
中序前驱——左子树最右边的结点
prior = p->lchild;
while (prior->rchild)
prior = prior->rchild;
中序后继——右子树最左边的结点
next = p->rchild;
while (next->lchild)
next = next->lchild;
3.删除
所谓3的替代,如B替代A,就是将B值赋给A,然后递归删除B。
以中序后继为例:
//删除
void Delete(BSTree& T, BSTNode* &p) {
BSTNode* f = father(T, p); //父结点
if (!p->lchild && !p->rchild) { //为叶子,直接删除
if (f->lchild == p) //为其父结点的左子
f->lchild = NULL;
else //为其父结点的右子
f->rchild = NULL;
delete(p);
}
else if (p->lchild && !p->rchild) { //只有左子树
if (f->lchild == p)
f->lchild = p->lchild;
else
f->rchild = p->lchild;
delete(p);
}
else if (p->rchild && !p->lchild) { //只有右子树
if (f->lchild == p)
f->lchild = p->rchild;
else
f->rchild = p->rchild;
delete(p);
}
else { //两颗子树都有
BSTNode* next = p->rchild; //next为其中序的后继
while (next->lchild)
next = next->lchild;
p->data = next->data; //赋值给自己
Delete(T, next); //递归删除其中序后继
}
}
考研向
二叉排序树选择题居多,算法题几乎没有
1.给定序列判断是否为二叉排序树
2.二叉排序树 T1,删除结点 A,再将结点 A 添加进去得到二叉排序树 T2:
\qquad
若 A 是 T1 叶结点,则 T1 与 T2 相同
\qquad
若 A 不是 T1 叶结点,则 T1 与 T2 不同
上述结论仅适用于二叉排序树,不适用于平衡树!
具体指向👉
测试代码,无聊可以跑一跑
int main()
{
BSTree T;
int m[] = { 3,5,1,4,2,7,0,6 };
Create_BST(T, m, 8);
InOrder(T); cout << endl;
LevelOrder(T); cout << endl;
cout << endl;
int x = 5;
BSTNode* p = Search(T, x); //查找值为x的结点
cout << p->data << endl;
BSTNode* f=father(T, p); //找到其父节点
cout << f->data << endl;
Delete(T, p); //删除该结点
InOrder(T); cout << endl;
}
原始蠢方法找前驱后继:
当你不知道怎么办的时候,用非递归遍历从栈里面找准没错,就是太蠢了。
BSTNode* Inprior(BSTree T, int x) { //找到中序前驱
BSTree S[30];
int top = -1;
BSTNode* pre = NULL; //保存前驱
BSTNode* p = T;
while (p || top != -1) {
if (p) {
S[++top] = p;
p = p->lchild;
}
else {
p = S[top--];
if (p->data != x)
pre = p; //保存上一个出栈元素
else
break;
p = p->rchild;
}
}
return pre;
}
BSTNode* Innext(BSTree T, int x) { //中序后继
BSTree S[50];
int top = -1;
BSTNode* p = T;
int tag = 0;
while (p || top != -1) {
if (p) {
S[++top] = p;
p = p->lchild;
}
else {
p = S[top--];
if (tag == 1)
return p;
if (p->data == x)
tag = 1;
p = p->rchild;
}
}
}