Search, Insert, Create and Delete of Binary Sorting Tree

Features of a binary sort tree:

1. If the left subtree is not empty, the values ​​of all nodes on the left subtree are less than the value of the root node;

2. If the right subtree is not empty, the values ​​of all nodes on the right subtree are greater than the value of the root node;

3. The left and right subtrees are respectively a binary sorting tree;

In summary, the value of the left subtree node < the value of the root node < the value of the right subtree node. Therefore, an in-order traversal of the binary sort tree can obtain an increasing ordered sequence. 

1. Data structure definition 

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

2. Binary tree search is non-recursive

 The search of the binary tree starts from the root node and compares downwards layer by layer. If the binary sorting tree is not empty, the keyword is compared with the value of the root node. If they are equal, the search is successful. If it is greater than, go to the right subtree to search , if less than, look for it in the left subtree.

//二叉排序树的非递归查找
BSTNode *BST_Search(BSTree T,int key)
{
	while(T!=NULL&&T.key!=key)        //树不空以及没找到关键字 
	{
		if(T.key<key)                 //根结点小于关键字,左子树寻找 
		{
			T=T->lchild;
		} 
		else                           //否则右子树寻找 
		{
			T=T->rchild;
		}	
	}
	return T;
 } 

The space complexity of the non-recursive algorithm is O(1). 

 3. Recursive search of binary sorting tree

//二叉排序树的递归查找
BSTNode *BST_Search(BSTree T,int key)
{
	if(T==NULL)       //查找失败 
	return T;
	if(T.key==key)   //查找成功 
	{
		return T;
	}
	else if(T.key>key)
	return BST_Search(T->lchild,key);
	else
	return BST_Search(T->rchild,key);
 }

However, recursive search requires a recursive work stack, so its space complexity is the height of the tree. The worst case is a single subtree, that is, the time complexity is O(n). 

4.  Recursive insertion of binary sorting tree 

Since there are no two nodes with equal values ​​in the binary sorting tree, when inserting, it is found that the inserted value is equal to the value of a node in the tree, and the insertion fails.

Insertion process:

1. If the binary tree is empty, insert the node directly;

2. Otherwise, if the keyword is less than the value of the root node, it will be inserted into the left subtree; if the keyword is greater than the value of the root node, it will be inserted into the right subtree. The inserted node must be a newly added leaf node, and it is the left or right child of the last node visited on the search path when the search fails.

//二叉排序树的插入(递归实现) 
int BST_Insert(BSTree &T,int k)
{
	if(T==NULL)
	{
		T=(BSTree)malloc(sizeof(BSTNode));
		T->key=k;
		T->lchild=T->rchild=NULL;
		return 1;         //插入成功 
	}
	else if(T->key==k)    //有重复值,插入失败 
	return 0;
	else if(T->key<key)
	return BST_Insert(T->rchild,k);
	else
	return BST_Insert(T->lchild,k);
 } 

Its time complexity is: O(h), where h is the height of the tree. 

 5, the creation of binary sorting tree

The process of creating a binary tree is actually a process of continuous insertion.

//二叉树的创建
void Creat_BST(BSTree &T,int a[],int n)
{
	T=NULL;       //初始时T为空
	int i=0;
	while(i<n)
	{
		BST_Insert(T,a[i]);
		i++;
	} 
 } 

Different keyword sequences may get the same binary sorting tree, or different binary sorting trees.

6. Deletion of binary sort tree 

The deletion process of a binary sort tree:

1. If the node to be deleted is a leaf node, delete it directly;

2. If the deleted node a has only one left subtree or right subtree, let the subtree of a occupy the position of a and become the subtree of the parent node of a.

3. If node a has left and right subtrees, let the direct successor of a (the same is true for the direct predecessor) replace a, then delete the direct successor (direct predecessor) from the binary sorting tree, and then convert it to 1 or 2 Situation handling.

The direct successor of a: the leftmost node in the right subtree of a, this node must not have a left subtree, and the value of this node is the smallest in the right subtree.

The direct predecessor of a: the bottom right node in the left subtree of a, this node must have no right subtree, and the value of this node is the largest in the left subtree.

For the third case, the immediate successor node is used instead:

 //二叉排序树的删除 
int BST_Delete(BSTree &T,int key)
{
	BSTree p=T;
	BSTree pre=NULL;        //指向要删除结点的前一个结点 
	while(p!=NULL&&p->key!=key)        //先找到要删除的结点 
	{
		if(key>p->key)
		{
			pre=p;
			p=p->rchild;
		}
		else
		{
			pre=p;
			p=p->lchild;
		}
	} 
	if(p==NULL)        //要删除的结点不存在 
	return 0; 
	else
	{
		//第一种情况:删除叶子结点,直接删
		if(p->lchild==NULL&&p->rchild==NULL)
		{
			if(pre->key<key)
			{
				pre->rchild=NULL;
			} 
			else
			{
				pre->lchild=NULL;
			}
		} 
		//第二种情况:单子树 
		else if((p->lchild==NULL&&p->rchild)||(p->rchild==NULL&&p->lchild))
		{
			if(pre->key<key)
			{
				if(p->rchild)    //右子树存在 
				{
					pre->rchild=p->rchild;
				}
				else            //左子树存在 
				{
					pre->rchild=p->lchild;
				}
			}
			else
			{
				if(p->rchild)
				{
					pre->lchild=p->rchild;
				} 
				else
				{
					pre->lchild=p->lchild;
				}
			}
		} 
		//第三种情况:左右子树都存在,这里我使用的是用直接后继填补(直接前驱一样,后面也给出)
		else if(p->lchild&&p->rchild)
		{
			BSTree *pre1=p;          //由于要删除的结点不需要动,只是被替换,所以不需要知道被删除结点的前驱,而是要知道被替换结点的前驱
			BSTree *q=p->rchild;
			while(q->lchild)         //寻找右子树的最左下的结点 
			{
				pre1=q;
				q=q->lchild;
			} 
			p->key=q->key;     //替换结点值 
			if(p!=pre1)   //右子树的左子树存在 
			{
				pre1->lchild=q->lchild; 
			}
			else              //右子树的左子树不存在,用根替换的 
			{
				pre1->rchild=q->rchild;
			}
			delete(q);
		} 
		return 1;          //删除成功 
	} 
}

For the third case the direct predecessor node substitute is used: 

//二叉排序树的删除 
int BST_Delete(BSTree &T,int key)
{
	BSTree p=T;
	BSTree pre=NULL;        //指向要删除结点的前一个结点 
	while(p!=NULL&&p->key!=key)        //先找到要删除的结点 
	{
		if(key>p->key)
		{
			pre=p;
			p=p->rchild;
		}
		else
		{
			pre=p;
			p=p->lchild;
		}
	} 
	if(p==NULL)        //要删除的结点不存在 
	return 0; 
	else
	{
		//第一种情况:删除叶子结点,直接删
		if(p->lchild==NULL&&p->rchild==NULL)
		{
			if(pre->key<key)
			{
				pre->rchild=NULL;
			} 
			else
			{
				pre->lchild=NULL;
			}
		} 
		//第二种情况:单子树 
		else if((p->lchild==NULL&&p->rchild)||(p->rchild==NULL&&p->lchild))
		{
			if(pre->key<key)
			{
				if(p->rchild)    //右子树存在 
				{
					pre->rchild=p->rchild;
				}
				else            //左子树存在 
				{
					pre->rchild=p->lchild;
				}
			}
			else
			{
				if(p->rchild)
				{
					pre->lchild=p->rchild;
				} 
				else
				{
					pre->lchild=p->lchild;
				}
			}
		} 
		//第三种情况:左右子树都存在,这里我使用的是用直接后继填补(直接前驱一样,后面也给出)
		else if(p->lchild&&p->rchild)
		{
			BSTree *pre1=p;          //由于要删除的结点不需要动,只是被替换,所以不需要知道被删除结点的前驱,而是要知道被替换结点的前驱
			BSTree *q=p->lchild;
			while(q->rchild)         //寻找左子树的最右下的结点 
			{
				pre1=q;
				q=q->rchild;
			} 
			p->key=q->key;     //替换结点值 
			if(p!=pre1)   //左子树的右子树存在 
			{
				pre1->rchild=q->lchild; 
			}
			else              //左子树的右子树不存在,用根替换的 
			{
				pre1->lchild=q->lchild;
			}
			delete(q);
		} 
		return 1;          //删除成功 
	} 
}

Guess you like

Origin blog.csdn.net/m0_51769031/article/details/125418998