二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
算法实现
1 二叉排序树的查找算法
2 在二叉排序树插入结点的算法
3 在二叉排序树删除结点的算法
递归实现 :
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef struct BSTreeNode
{
int key;//不允许重复,不允许更改
struct BSTreeNode *pLeft;
struct BSTreeNode *pRight;
}BSTreeNode;
//递归实现
//查找
//是否找到:1 找到, 0 没找到
int FindR(BSTreeNode *pRoot, int key)
{
if (pRoot == NULL)
{
return 0;
}
if (key == pRoot->key)
{
return 1;
}
if (key < pRoot->key)
{
return FindR(pRoot->pLeft, key);
}
return FindR(pRoot->pRight, key);
}
BSTreeNode * CreateNode(int key)
{
BSTreeNode *pNode = (BSTreeNode *)malloc(sizeof(BSTreeNode));
assert(pNode);
pNode->key = key;
pNode->pLeft = pNode->pRight = NULL;
return pNode;
}
//插入
//0表示成功 -1表示失败
int InsertR(BSTreeNode **pRoot, int key)
{
if (*pRoot == NULL)
{
*pRoot = CreateNode(key);
return 0;
}
if (key == (*pRoot)->key)
{
return -1;
}
if (key < (*pRoot)->key)
{
return InsertR(&(*pRoot)->pLeft, key);
}
return InsertR(&(*pRoot)->pRight, key);
}
//删除 0表示成功,-1表示失败
int RemoveR(BSTreeNode **pRoot, int key)
{
if (*pRoot == NULL)
{
return -1;
}
if (key < (*pRoot)->key)
{
return RemoveR(&(*pRoot)->pLeft, key);
}
else if (key>(*pRoot)->key)
{
return RemoveR(&(*pRoot)->pRight,key);
}
//处理删除
if ((*pRoot)->pLeft == NULL)//左子树为空
{
*pRoot = (*pRoot)->pRight;
return 0;
}
if ((*pRoot)->pRight == NULL)//右子树为空
{
*pRoot = (*pRoot)->pLeft;
return 0;
}
//左右子树都不为空,找右子树中的最小孩子替换删除
/*BSTreeNode *pSwap = (*pRoot)->pRight;
while (pSwap->pLeft != NULL)
{
pSwap= pSwap->pLeft;
}
(*pRoot)->key = pSwap->key;
RemoveR(&(*pRoot)->pRight, pSwap->key);
return 0;*/
//找左子树中最大的孩子替换删除
BSTreeNode *pSwap = (*pRoot)->pLeft;
while (pSwap->pRight != NULL)
{
pSwap = pSwap->pRight;
}
(*pRoot)->key = pSwap->key;
RemoveR(&(*pRoot)->pLeft, pSwap->key);
return 0;
}
非递归实现:
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef struct BSTreeNode
{
int key;//不允许重复,不允许更改
struct BSTreeNode *pLeft;
struct BSTreeNode *pRight;
}BSTreeNode;
//查找
//是否找到:1 找到 0 没找到
int Find(BSTreeNode *pRoot, int key)
{
BSTreeNode *pNode = pRoot;
while (pNode != NULL)
{
if (key == pNode->key)
{
return 1;
}
else if (key < pNode->key)
{
pNode = pNode->pLeft;
}
else
{
pNode = pNode->pRight;
}
}
return 0;
}
BSTreeNode * CreateNode(int key)
{
BSTreeNode *pNode = (BSTreeNode *)malloc(sizeof(BSTreeNode));
assert(pNode);
pNode->key = key;
pNode->pLeft = pNode->pRight = NULL;
return pNode;
}
//插入
//0表示成功 -1表示失败
int Insert(BSTreeNode **pRoot, int key)
{
BSTreeNode *pNode =*pRoot;
BSTreeNode *pParent = NULL;
while (pNode != NULL)
{
if (key == pNode->key)
{
return -1;
}
else if (key < pNode->key)
{
pParent = pNode;
pNode = pNode->pLeft;
}
else
{
pParent = pNode;
pNode = pNode->pRight;
}
}
if (pParent == NULL)//空树
{
*pRoot = CreateNode(key);
return 0;
}
//左还是右?
if (key < pParent->key)
{
pParent->pLeft=CreateNode(key);
}
else if (key>pParent->key)
{
pParent->pRight=CreateNode(key);
}
return 0;
}
//删除 0表示成功,-1表示失败
int Remove(BSTreeNode **pRoot, int key)
{
BSTreeNode *pNode = *pRoot;
BSTreeNode *pParent = NULL;
BSTreeNode *pSwap = NULL;
BSTreeNode *pSwapParent = NULL;
while (pNode != NULL)
{
//处理删除
if (key==pNode->key)
{
if (pNode->pLeft == NULL)//要删除的结点左孩子为空
{
if (pNode == *pRoot)//要删除的为根节点
{
*pRoot = pNode->pRight;
free(pNode);
return 0;
}
else
{
if (pNode == pParent->pLeft)//要删除的为父亲的左孩子
{
pParent->pLeft = pNode->pRight;
}
else//要删除的为父亲的右孩子
{
pParent->pRight = pNode->pRight;
}
free(pNode);
return 0;
}
}
else if (pNode->pRight == NULL)//要删除的结点右孩子为空
{
if (pNode == *pRoot)
{
*pRoot = pNode->pLeft;
free(pNode);
return 0;
}
else
{
if (pNode = pParent->pLeft)
{
pParent->pLeft = pNode->pLeft;
}
else
{
pParent->pRight = pNode->pLeft;
}
free(pNode);
return 0;
}
}
else//要删除的结点左,右孩子都不为空.用右子树的最小孩子替换删除
{
pSwap = pNode->pRight;
while (pSwap->pLeft != NULL)//找右子树的左子树
{
pSwapParent = pSwap;
pSwap = pSwap->pLeft;
}
pNode->key = pSwap->key;//将找到左子树的最小孩子(pSwap)与要删除的结点(pNode)进行数据交换
//删除pSwap结点
if (pSwap == pNode->pRight)
{
pNode->pRight = pSwap->pRight;
}
else
{
pSwapParent->pLeft = pSwap->pRight;
}
free(pSwap);
return 0;
}
}
else if (key <= pNode->key)
{
pParent = pNode;
pNode = pNode->pLeft;
}
else
{
pParent = pNode;
pNode = pNode->pRight;
}
}
return -1;
}
例:如图演示二叉搜索树的8种删除情况: