C语言练习-day13

二叉排序树的存储结构

typedef struct BSTNode{
	int key;
	struct BSTNode *lchild,*rchild;
}BSTNode,*BSTree;

函数:二叉排序树的插入

输入:二叉排序树的结构体变量地址BSTree &T,和要插入的关键字e。该结构体变量的成员有关键字key,类型为int;指向左孩子和右孩子的二叉排序树指针。

输出:无。

优化目标:无。

分析:二叉排序树插入的基本过程就是查找,所以时间复杂度同查找一样是O(\log_{2}n)。

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(\log_{2}n),所以创建二叉排序树算法的时间复杂度为 O(n \log_{2}n)。很容易看出,一个无序序列可以通过构造一棵二叉排序树而变成有序序列,构造树的过程即对无序序列进行排序的过程,而且每次插入的新节点都是二叉排序树上的新的叶子结点,则进行插入操作时,不必移动其他结点,仅需改动某个结点的指针,由空变非空即可。

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(\log_{2}n)。

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);
	
}

今天把对二叉排序树的操作复习了一下,二叉排序树的删除要考虑的情况很多,左右孩子是否存在,单孩子的情况,根节点的情况等等,还是比较复杂的,后面还要进一步学习查找算法,并且还要多去复习复习。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值