二叉搜索树的基本算法

今天我来介绍一下 搜索二叉树及其算法。

一。首先我们要先知道什么是搜索二叉树。

1.二叉搜索树又称为二叉排序树,它或者是一个空树。它的主要性质是

(1)若他的左子树不为空,则左子树上所有节点的值都小于根节点的值。

(2)若他的右子树不为空,则右子树上所有节点的值都大于根节点的值。

(3)它的左右子树也分别为二叉搜索树。

2.它的基本算法:查找、插入以及删除的普通和递归方法。

#pragma once
#include
#include
#include
#include
#include


typedef struct BSTreeNode{        //定义一个搜索二叉树的结构体
	int key;                      //包含值、左子树和右子树。
	struct BSTreeNode *pleft;
	struct BSTreeNode *pright;
}BSTreeNode;

BSTreeNode *CreatNode(int key)        //创建子树。
{
	BSTreeNode *pNew=(BSTreeNode *)malloc(sizeof(BSTreeNode));
	assert(pNew);
	pNew->key=key;
	pNew->pleft=pNew->pright=NULL;
	return pNew;
}
//普通查找
//1:找到。
//0:没找到。
int Find(BSTreeNode *pRoot,int key)    
{
	BSTreeNode *p=pRoot;                
	while(p!=NULL)                   //总循环是节点不为空。
	{
		if(p->key==key)              //当找到节点时,输出1.
		{
			return 1;
		}
		else if(keykey)          //如果小于节点的值,就往左子树走。
		{
			p=p->pleft;
		}
		else{                        //否则往右子树走。
			p=p->pright;
		}
	}
	return 0;                       //循环出来表示没找到。
}


//递归查找。
int FindR(BSTreeNode *pRoot,int key) 
{
	if(pRoot==NULL)              //若为空,没找到。
	{
		return 0;
	}
	if(key==pRoot->key)         //若等于根节点直接返回1.
	{
		return 1;
	}
	else if(keykey)             //小于根节点,则递归左子树。
	{
		return FindR(pRoot->pleft,key);
	}
	return FindR(pRoot->pright,key);    //否则递归右子树。
}

//普通插入
//0:插入成功
//-1:插入失败。
int Insert(BSTreeNode **pRoot,int key)
{
	BSTreeNode *p=*pRoot;       //定义两个变量。
	BSTreeNode *q=NULL;
	while(p!=NULL)              //总循环直到找到节点为空的。
	{
		if(p->key==key)          //如果与根节点相同则插入失败。
		{
			return -1;
		}
		else if(keykey)     //若小于根节点,先用一个变量保存这个节点,在让根节点往左子树移。
		{
			q=p;
			p=p->pleft;
		}
		q=p;                    //若大于根节点,先用一个变量保存这个节点,在让根节点往右子树移。
		p=p->pright;
	}
	if(q==NULL)                   //如果根节点为空,直接插入即可。
	{
		(*pRoot)=CreatNode(key);
		return 0;
	}
	if(keykey)             //如果空节点的父节点的值大于要插入的值,则给它的左子树直接插入。
	{
		q->pleft=CreatNode(key);
		return 0;
	}
	else if(key>q->key)
	{
		q->pright=CreatNode(key);       //否则给它的右子树插入。
		return 0;
	}
}
//递归插入。
int InsertR(BSTreeNode **pRoot,int key)
{
	if(*pRoot==NULL)                   //如果根节点为空,直接插入。
	{
		*pRoot=CreatNode(key);
		return 0;
	}
	if((*pRoot)->key==key)          //若与根节点相等,插入失败。
	{
		return -1;
	}
	else if(key<((*pRoot)->key))             //小于根节点的值,递归左子树。
	{
		return InsertR(&((*pRoot)->pleft),key);
	}
	return InsertR(&((*pRoot)->pright),key);   //否则递归右子树。
}
//普通删除
//0:删除成功。
//-1:删除失败。
int Remove(BSTreeNode **pRoot,int key)
{
	BSTreeNode *p=*pRoot;
	BSTreeNode *q=*pRoot;
	BSTreeNode *m=NULL;
	while(p!=NULL)          //循环节点不为空。
	{
		if(keykey)      //若小于节点的值,向左子树移。
		{
			q=p;
			p=p->pleft;
		}
		else if(key>p->key)  //若大于节点的值,向右子树移。
		{
			q=p;
			p=p->pright;
		}
		else{                      //当等于节点的值时。
			if(p->pleft==NULL)        //若它的左子树为空
			{
				if(q->pleft==NULL)    //当它的父节点的左子树为空时
				{
					q->pright=p->pright; //直接替换删除即可。
					free(p);
					return 0;
				}
				else if(q->pright==NULL)  //当它的父节点的右子树为空
				{
					q->pleft=p->pright;  //同理。
					free(p);
					return 0;
				}
			}
			else if(p->pright==NULL)     //当节点的右子树为空时,同理如上。
			{
				if(q->pleft==NULL)
				{
					q->pright=p->pleft;
					free(p);
					return 0;
				}
				else if(q->pright==NULL)
				{
					q->pleft=p->pleft;
					free(p);
					return 0;
				}
			}
			else{                      //当节点的左右子树都不为空时
				m=p->pleft;            //用变量m记下它的左子树。
				while(m->pright)
				{                      
					q=m;
					m=m->pright;
				}                     //循环找最后的右子树。
				if(p->pleft=m)        //若m没变,证明m的右子树为空。
				{
					if(m->pleft==NULL) //若m的左子树也为空。
					{
						p->key=m->key;  //直接将m赋给p即可。
						free(m);
						return 0;
					}
					else{                 //若M的左子树不为空。
						p->key=m->key;    //将m赋给p之后,让p的左子树指向m的左子树,再删除即可。
						p->pleft=m->pleft;
						free(m);
						return 0;
					}
				}
				else{                      //若m变了,证明m是最后的右子树,直接赋值删除即可。
					p->key=m->key;
					free(m);
				}

			}

		}
	}
	return -1;                      //若退出循环,则删除失败。
}

//递归删除。

int RemoveR(BSTreeNode **pRoot,int key)
{
	BSTreeNode *q=NULL;            
	if(*pRoot==NULL)           //如果根节点为空,删除失败。
	{
		return -1;
	}
	if((*pRoot)->key>key)         //若小于根节点的值,递归左子树。
	{
		return RemoveR(&((*pRoot)->pleft),key);
	}
	else if(key>(*pRoot)->key)      //大于根节点的值,递归右子树。
	{
		return RemoveR(&((*pRoot)->pright),key);
	}
	else{                             //当等于根节点的值时。
		if((*pRoot)->pleft==NULL)         //如果根节点的左子树为空,则它的右孩子作为根节点。
		{
			*pRoot=(*pRoot)->pright;
			return 0;
		}
		else if((*pRoot)->pright==NULL)   //右子树为空,它的左孩子为根节点。
		{
			*pRoot=(*pRoot)->pleft;
			return 0;
		}
		q=(*pRoot)->pleft;              //当左右孩子都不为空时。先用变量记下根节点的左子树。
		while(q->pright)               //循环找到最后的右子树。
		{
			q=q->pright;
		}
		(*pRoot)->key=q->key;            //此时将右子树的值替换根节点的值。
		RemoveR(&((*pRoot)->pleft),q->key);  //在删除掉这个右子树即可。
		return 0;
	}
}


void test1()
{
	BSTreeNode *p=NULL;
	Insert(&p,1);
	Insert(&p,2);
	Insert(&p,3);
	Insert(&p,4);
	printf("%d\n",Find(p,3));
	printf("%d\n",FindR(p,4));
	Remove(&p, 4);
	RemoveR(&p, 3);
	printf("%d\n",FindR(p,4));
	printf("%d\n",Find(p,3));
	printf("\n");
}

以上就是搜索二叉树的基本算法。

你可能感兴趣的:(二叉搜索树的基本算法)