二叉排序树的存储结构
typedef struct BSTNode{
int key;
struct BSTNode *lchild,*rchild;
}BSTNode,*BSTree;
函数:二叉排序树的插入
输入:二叉排序树的结构体变量地址BSTree &T,和要插入的关键字e。该结构体变量的成员有关键字key,类型为int;指向左孩子和右孩子的二叉排序树指针。
输出:无。
优化目标:无。
分析:二叉排序树插入的基本过程就是查找,所以时间复杂度同查找一样是O()。
void InsertBST(BSTree &T,int e){
//当二叉树排序树T中不存在关键字等于e时,则插入该元素
if(T==NULL){
BSTNode *s = (BSTNode *)malloc(sizeof(BSTNode));
s->key = e;
s->lchild = s->rchild = NULL;
T = s;
}
//将*s插入左孩子
else if(e<T->key){
InsertBST(T->lchild,e);
}
//将*s插入右孩子
else if(e>T->key){
InsertBST(T->rchild,e);
}
}
二叉排序树的创建
输入:二叉排序树的结构体变量地址BSTree &T。该结构体变量的成员有关键字key,类型为int;指向左孩子和右孩子的二叉排序树指针。
输出:无。
优化目标:无。
分析:假设有n个结点,则需要n次插入操作,而插入一个结点的算法时间复杂度为 O(),所以创建二叉排序树算法的时间复杂度为 O(
)。很容易看出,一个无序序列可以通过构造一棵二叉排序树而变成有序序列,构造树的过程即对无序序列进行排序的过程,而且每次插入的新节点都是二叉排序树上的新的叶子结点,则进行插入操作时,不必移动其他结点,仅需改动某个结点的指针,由空变非空即可。
void CreateBST(BSTree &T){
//依次读入一个关键字为key的结点,将此结点插入二叉排序树T中
//初始化为空树
T = NULL;
int e;
scanf("%d",&e);
//MAX就是作为输入结束标志
while(e!=MAX){
//将此结点插入二叉排序树中
InsertBST(T,e);
scanf("%d",&e);
}
}
二叉排序树的删除
输入:二叉排序树的结构体变量BSTree T,和要删除的关键字key,类型为int。该结构体变量的成员有关键字key,类型为int;指向左孩子和右孩子的二叉排序树指针。
输出:无。
优化目标:无。
要点:被删除的结点可能是二叉排序树的任何结点,删除结点后,要根据其位置不同修改其双亲结点及相关结点的指针,以保持二叉排序树的特性。
分析:同二叉排序树插入一样,二叉排序树删除的基本操作也是查找,所以时间复杂度也是 O()。
void DeleteBST(BSTree &T,int key){
BSTNode *p = T,*f,*q,*s;
//找到想要删除的结点
while(p){
if(p->key == key){
break;
}
f = p;
if(p->key>key){
p = p->lchild;
}
else{
p = p->rchild;
}
}
//未找到
if(p == NULL){
return;
}
q = p;
//p结点左右都有孩子的情况,删除p最左边的最大的值与p交换,然后删除那个结点
if((p->lchild!=NULL)&&(p->rchild!=NULL)){
//s就是指向p最左边最大值的结点(无右孩子),p指向s的父亲
s = p->lchild;
while(s->rchild!=NULL){
q = s;
s = s->rchild;
}
//p与s的值交换
p->key = s->key;
//q不等于p意思是q的右孩子是s,因为我们要删s,让s的左孩子接到q的右孩子
if(q!=p){
q->rchild = s->lchild;
}
//q对于p意思是q的左孩子是s
else{
q->lchild = s->lchild;
}
free(s);
return;
}
//p没有右孩子就指向左孩子
else if(!(p->rchild)){
p = p->lchild;
}
//p没有左孩子就指向右孩子
else if(!(p->lchild)){
p = p->rchild;
}
//以下q只有p结点的孩子(无论左右)
//f是指向p的父节点,若f为空,意思是被删的结点为根节点
if(!f){
T = p;
}
//此时q指向的是想要删除的结点
//让f的左/右孩子去指向q唯一的孩子
else if(q == f->lchild){
f->lchild = p;
}
else{
f->rchild = p;
}
//删除想要删除的结点
free(q);
}
今天把对二叉排序树的操作复习了一下,二叉排序树的删除要考虑的情况很多,左右孩子是否存在,单孩子的情况,根节点的情况等等,还是比较复杂的,后面还要进一步学习查找算法,并且还要多去复习复习。