二叉查找树的性质和用法

二叉查找树的定义:左子树都要小于或者等于根节点的数据域,右子树都要大于根节点的数据与。

1.二叉查找树的寻找操作:

该根节点的数据域大于x值,说明该结点的数据域大了,就该往左子树寻找进行递归。

该根结点的数据域小于x值,说明该结点的数据域小了,就该往右子树寻找进行递归。

root等于NULL的话说明寻找失败。

代码:

void search(node* root,int x){
	if(root==NULL){
		printf("search failed");
		return ;
	}
	if(root->data==x){
		printf("%d",root->data);
	}else if(root->data>x){
		search(root->lchild,x);
	}else {
		search(root->rchild,x);
	}
}

一般的二叉树寻找,因为子树的数据域是无序的,没有选择,而二叉寻找树可以有选择地递归左右子树,且二叉寻找树的数据域大小排序是root->lchild->data  <  root->data   <root->rchild->data

2.二叉查找树的插入操作:

对一个二叉查找树来说,查找某个数据域的结点一定是沿着确定的路径进行的,在寻找失败的地方就是要插入的地方,即在root=NULL时新建需要插入的结点。

代码:

node* newnode(int x){
	node* root=new node;
	root->data=x;
	root->rchild=NULL;
	root->lchild=NULL;
	return root; 
}
void insert(node* &root,int x){//insert插入结点就关于根节点新建的结点的连线问题了,因为要在建立新节点后同时更新根节点的数据域,形成连线 ,因此Insert要引用; 
	if(root==NULL){//寻找失败建立结点; 
		root=newnode(x);
		return;
	}
	if(root->data<x){
		insert(root->rchild,x);
	}else {
		insert(root->lchild,x);
	}
}


3.二叉查找树的建立:
本质和插入是一样的,要注意的是插入的顺序不同,生成的二叉查找树也不同,毕竟第一个插入的元素就是根节点了。

代码:

node* create(int data[ ],int n){
	node* root=NULL;
	for(int i=0;i<n;i++){
		insert(root,data[i]);
	}
	return root;
} 

4.二叉查找树的删除(难点):

难点:删除操作后仍然是一颗二叉查找树。

有两种方法:

①是找左子树的最大值(根节点的前驱---根节点左树最右结点)去替换被删除的根节点,因为左子树的值都比右子树的值小,左子树的最大值比除了该最大值以外的值大,所以可以用左子树的最大值去替换根节点的值,再删除掉原最大值结点。
②是找右子树的最小值(根节点的后继---根节点右子树最左结点),来替换掉根节点,然后将该值删除。

前驱,后继,就相当于该      前驱(比根节点小一点)<-根节点<-后继(比根节点大一点),根节点被删找前驱或者后继去代替。

下面两个是寻找前驱后继的方法;

node* findpre(node* root){//找前驱,root是左子树的根节点; 
	while(root->rchild!=NULL){
		findpre(root->rchild);
	}
	return root;
}

node* findpost(node* root){//找后继,root是右子树根节点; 
	while(root->lchild!=NULL){
		findpost(root->lchild);
	}
	return root;
}

删除的代码:

void deletendoe(node* &root,int x){//在二叉查找树中删除数x;
	//递归边界 
	 if(root==NULL)return ;//按一定的路线都找不到,说明该树没有这个数;
	 if(root->data==x){
	 	if(root->lchild==NULL&&root->rchild){
	 		root=NULL;//因为是引用,子节点为NULL,子树的根节点也会变成NULL,这步相当于删除了这个叶子结点; 
		 }else if(root->lchild!=NULL){//有左子树,删除结点不是叶子结点; 
		 	node* pre=findpre(root->lchild);
		 	root->data=pre->data;//替换掉删除结点;
			deletenode(root->lchild,pre->data);//进入左子树找到前驱结点,删除前驱结点,一个递归过程,用前驱替换,删除前驱...直到删掉叶子结点后结束; 
		 }else if(root->rchild!=NULL){//有右子树; 
		 	node* post=findpost(root->rchild);
		 	root->data=post->data;
		 	deletenode(root->rchild,post->data);
		 } 
	 }
	 if(root->data>x){
	 	deletenode(root->lchild,x);
	 }else {
	 	deletenode(root->rchild,x);
	 }
}

注意:总是优先删除前驱或者后继会导致二叉查找树退化成一条链,因此可以用交替删除前驱后继,或者记录子树的高度,总是优先在高度较高的一科子树里删除结点。

二叉查找树实用的性质,对二叉查找树进行中序遍历,遍历结果是有序的,因为遍历的顺序是左根右


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值