1. 梗概:
- 一种特殊的二叉树, 规定每个子树的节点数据都遵循:
- 左孩子<根(双亲)<右孩子
- 拥有相同结点的排序二叉树, 有多种形态
- 根据插入顺序的不同, 形态各不相同
特殊的二叉排序树
child::平衡排序二叉树
2. 排序二叉树与折半查找的区别:
2.1. 排序二叉树特点:
- 不同的插入顺序, 形成的排序二叉树往往不同, 甚至可能形成单支树, 平均性能非常差
- 看上去根好像是中位数, 但实际上因为左右子树规模不同, 根往往偏离中位数很远
2.2. 折半查找特点:
- 每次取的关键字都非常接近与中位数, 平均性能良好
- 不同的插入顺序, 所形成的记录表都一样
2.3. 相同点:
- 两者平均性能相似
3. 操作:
- 插入
- 时间复杂度: O(logn)
- 查找
- 删除
- 时间复杂度: O(logn)
4. 在c语言中的实现
4.1. 定义:
typedef struct BSTNode{
KeyType key;
struct BSTNode *LChild, *RChlid;
}BSTNode,*BSTree;
4.2. 查找结点
BSTNode* SearchBST(BSTree tree, KeyType key){
BSTree q;
q= tree;
for(;q;){
if(q->key==key)return q;
if(q->key>key)q=q->LChild;
else q=q->RChild;
}
return NULL;
}
4.3. 插入结点
梗概:
- 参数需要根结点指针的地址
- 当连树都不存在时候
- 就在该地址放上一个根结点
- 当连树都不存在时候
- 找到将插入位置的双亲结点
- 在该双亲的对应孩子结点地址放上新的结点 代码:
void InsertBST(BSTree *tree, KeyType key){
BSTNode *parent=NULL,*p;
for(p=*tree;p;){
parent = p;
if(key>p->key) p=p->RChild;
else p=p->LChild;
}
BSTNode* s=(BSTNode*)calloc(1,sizeof(BSTNode));
s->key=key; s->LChild=s->RChild=NULL;
if(!parent)*tree=s;
else if(parent->LChild==p)
parent->LChild=s;
else parent->RChild=s;
}
4.4. 创建二叉排序树
void CreateBST(BSTree tree){
KeyType key;
tree=NULL;
scanf("%d",&key);
for(;key!=-1;){
InsertBST(tree,key);
scanf("%d",&key);
}
}
4.5. 删除结点
梗概:
- 按复杂程度分两种大情况:
- 目标只有左子树或右子树
- 目标两个子树都有
- 目标只有左子树或右子树
- 则把子树接上目标双亲结点, 再删掉目标结点即可
- 两个子树都有
- 还需要额外找出两个结点, 分别是直接前驱(数值上的), 前驱的双亲
- 直接前驱在左子树的最右结点
- 把直接前驱拿过来, 顶上目标结点
- 相当于也删除该结点, 但该节点必定没有右子树
- 所以直接把前驱的左子树接上前驱的双亲即可
- 相当于也删除该结点, 但该节点必定没有右子树
- 实际上只要释放掉前驱节点即可 代码:
- 还需要额外找出两个结点, 分别是直接前驱(数值上的), 前驱的双亲
BSTree DelBST(BSTree tree, KeyType key){
BSTNode *tar, *par_tar, *front, *par_front;
tar=tree; par_tar=NULL;
/*查找目标并记录其双亲*/
for(;tar;){
if(tar->key==key) break;
par_tar=tar;
if(tar->key>key)tar=tar->LChild;
else tar=tar->RChild;
}
if(tar==NULL) return tree;
/*先判断右子树是否独立*/
if(tar->LChild==NULL){
/*把目标的右子树直接接上*/
if(par_tar==NULL) tree=tar->RChild;
else if(par_tar->LChild==tar)par_tar->LChild=tar->RChild;
else par_tar->RChild=tar->RChild;
free(tar);
}
/*处理左子树*/
else{
par_front=tar;
/*找左子树的最右结点,并记录其双亲*/
front=tar->LChild;
for(;front->RChild;){
par_front=front; front=front->RChild;
}
if(par_front==tar) par_front->LChild=front->LChild;
/*先用更前驱顶上前驱*/
else par_front->RChild=front->LChild;
/*前驱顶上目标*/
tar->key=front->key;
free(front);
}
return tree;
}
5. 在ts/js中的实现:
5.1. 定义:
type keytype = number;
class BSTNode{
constructor(key:keytype,LChild?:BSTNode,RChild?:BSTNode){
this.key=key;
this.LChild=LChild?LChild:null;
this.RChild=RChild?RChild:null;
}
key:keytype;
LChild:BSTNode|null;
RChild:BSTNode|null;
}
5.2. 插入/创建/查找:
class BSTree{
constructor(){
this.root=null;
}
root:BSTNode|null;
SearchBST(key:keytype){
let q = this.root;
for(;q;){
console.log(q.key);
if(q.key==key)return q;
else if(q.key<key)q=q.RChild;
else q=q.LChild;
}
return null;
}
InsertBST(key:keytype){
if(this.root==null){
this.root=new BSTNode(key);
return;
}
let parent:BSTNode|null = this.root;
let q:BSTNode|null = this.root;
for(;q;){
parent=q;
if(q.key<key)
q=q.RChild;
else q=q.LChild;
}
let NewNode = new BSTNode(key);
if(parent.key<key)parent.RChild=NewNode;
else parent.LChild=NewNode;
}
CreatBST(keys:keytype[]){
for(let i=0;i<keys.length;++i){
this.InsertBST(keys[i]);
}
}
}