问题描述
给定两个不同的二叉搜索树,N个数,L次询问判断,判断这两个二叉搜索树是否结构一样。
题目链接:
https://pintia.cn/problem-sets/15/problems/712
数据范围:
N <= 10
L范围不确定
样例:
Input:
| 12
 3
 4
 5
 6
 7
 8
 
 | 4 23 1 4 2
 3 4 1 2
 3 2 4 1
 2 1
 2 1
 1 2
 0
 
 | 
Output:
知识点
二叉搜索树
定义
BST(Binary Search tree),可能为空树,可能是一个具有以下性质的一颗树:
优点
插入 查找复杂度较低。(相对于线性数据结构来说)
期望:$ {O(\log n)} $
当序列有序时,树退化成线性表
最坏:${O(n)}$
支持操作
查找
在一个二叉搜索树T中,查找值为X的结点
查找过程:递归
0.若T为空树,则查找失败,否则。
1.若X等于T的根节点的键值,则查找成功,否则。
2.若X小于T的根节点的键值,则查找T的左子树,否则。
3.查找T的右子树。
代码:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 
 | Status SearchBST(BiTree T, KeyType key, BiTree f, BiTree &p) {
 if (!T) {
 p = f;
 return false;
 } else if (key == T->data.key) {
 p = T;
 return true;
 } else if (key < T->data.key)
 return SearchBST(T->lchild, key, T, p);
 else
 return SearchBST(T->rchild, key, T, p);
 }
 
 | 
相关联系:
与此题相比,没有让你查找X的值的位置,判断两个二叉搜素树是否相同,即从根节点开始遍历树T,判断每一个结点及其左右孩子是否相同,反之,则树不相同。
插入
向一个二叉搜索树T中,插入一个键值为X的结点。(不要破坏原有的二叉搜索树的结构特点)
插入过程:递归
0.若T为空树,则X的结点作为根节点插入,否则。
1.若X等于T的根节点的键值,则返回,否则。
2.若X小于T的根节点的键值,则将X的结点插入到T的左子树中,否则。
3.把X插入到T的右子树中。
注:新插入的结点总是叶子节点(想一下就出来了)
代码:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | Status InsertBST(BiTree *&T, ElemType e) {if (!T) {
 s = new BiTNode;
 s->data = e;
 s->lchild = s->rchild = NULL;
 T = s;
 } else if (e.key == T->data.key)
 return false;
 if (e.key < T->data.key)
 InsertBST(T->lchild, e);
 else
 InsertBST(T->rchild, e);
 return true;
 }
 
 | 
删除
在一个二叉搜索树T中,删除一个键值为X的结点。(不要破坏原有的二叉搜索树的结构特点)
删除过程:递归+旋转结点
0.若X结点为叶子结点,只需要修改其双亲结点的指针。
1.若X有左孩子结点XL或右孩子结点XR,直接令XL/XR成为删除结点的左孩子结点/右孩子结点。
2.若X有左孩子结点XL和右孩子结点XR,有两种做法:(规定删除结点为X 其父节点为T)
- 令XL为T的左/右子树结点(依据X是T的左/右子树),S是XL的最右下结点,而X的右子树为S的右子树。
- 令X的直接前驱/直接后驱替代T,再直接删除X的直接前驱/直接后驱。
基本思路:不要去删除X,而是选择X的有序的前驱结点或者有序的后驱结点来替代X。
参考资料:https://en.wikipedia.org/wiki/Binary_search_tree
代码:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 
 | Status DeleteBST(BiTree *T, KeyType key) {
 
 if (!T)
 return false;
 else {
 if (key == T->data.key)
 return Delete(T);
 else if (key < T->data.key)
 return DeleteBST(T->lchild, key);
 else
 return DeleteBST(T->rchild, key);
 }
 }
 
 Status Delete(BiTree *&p) {
 
 BiTree *q, *s;
 if (!p->rchild && !p->lchild) {
 delete p;
 p = NULL;
 } else if (!p->rchild) {
 q = p->lchild;
 
 
 
 
 
 p->data = q->data;
 p->lchild = q->lchild;
 p->rchild = q->rchild;
 delete q;
 } else if (!p->lchild) {
 q = p->rchild;
 
 
 
 
 
 p->data = q->data;
 p->lchild = q->lchild;
 p->rchild = q->rchild;
 delete q;
 } else {
 q = p;
 s = p->lchild;
 while (s->rchild) {
 q = s;
 s = s->rchild;
 }
 p->data = s->data;
 if (q != p)
 q->rchild = s->lchild;
 else
 q->lchild = s->lchild;
 delete s;
 }
 return true;
 }
 
 | 
题目做法
代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 
 | #include <bits/stdc++.h>using namespace std;
 int N, L;
 typedef struct binnode
 {
 int data;
 struct binnode *lchild;
 struct binnode *rchild;
 }binnode, *bintree;
 void bintreeinsert(bintree &Tree, bintree &temp)
 {
 if(Tree == NULL)
 return ;
 if(temp->data >= Tree->data)
 {
 if(Tree->rchild != NULL)
 bintreeinsert(Tree->rchild, temp);
 else
 Tree->rchild = temp;
 }
 if(temp->data < Tree->data)
 {
 if(Tree->lchild != NULL)
 bintreeinsert(Tree->lchild, temp);
 else
 Tree->lchild = temp;
 }
 }
 void createbintree(bintree &T, int n)
 {
 for(int i = 0; i < n; i++)
 {
 int x;
 cin >> x;
 bintree temp;
 temp = (bintree)malloc(sizeof(binnode));
 temp->data = x;
 temp->lchild = NULL;
 temp->rchild = NULL;
 if(T != NULL)
 bintreeinsert(T, temp);
 else
 T = temp;
 }
 }
 bool is_same_binsearchtree(bintree T1, bintree T2)
 {
 if(T1 == NULL && T2 == NULL)
 return true;
 else if((T1 != NULL && T2 == NULL) || (T1 == NULL && T2 != NULL))
 return false;
 else if((T1 != NULL && T2 != NULL) && (T1->data != T2->data))
 return false;
 else
 return (is_same_binsearchtree(T1->lchild, T2->lchild) && is_same_binsearchtree(T1->rchild, T2->rchild));
 }
 void Allfree(bintree &T)
 {
 if(T->lchild == NULL && T->rchild == NULL)
 free(T);
 else if(T->lchild != NULL)
 Allfree(T->lchild);
 else if(T->rchild != NULL)
 Allfree(T->rchild);
 }
 int main(void)
 {
 while(cin >> N && N != 0)
 {
 cin >> L;
 bintree T1, T2;
 T1 = T2 = NULL;
 createbintree(T1, N);
 while(L--)
 {
 T2 = NULL;
 createbintree(T2, N);
 bool flag = is_same_binsearchtree(T1, T2);
 if(flag)
 cout << "Yes" << endl;
 else
 cout << "No" << endl;
 Allfree(T2);
 }
 Allfree(T1);
 }
 return  0;
 }
 
 | 
总结点
- 一定记得建完后释放内存(删除当前树)[否则回WA on test 2]
- main函数中T1 T2 的初始化。(代码习惯问题)
- 建树过程中第一次插入中要特判T==NULL是否为空
- free函数是释放的单个结点,释放整个树要手写函数!
- 递归判断时思路要清晰,左右子树递归下去一定是&&(因为要左右同时成立才满足true条件)。
参考资料
1.结构体定义中的细节问题:
https://zhidao.baidu.com/question/274601639.html
https://blog.csdn.net/hk121/article/details/80839063
2.《算法导论》对于BST的讲解:
https://blog.csdn.net/csdn0123zl/article/details/81253648
3.BST的Wiki百科:
https://zh.wikipedia.org/wiki/%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91
https://en.wikipedia.org/wiki/Binary_search_tree