#pragma once
typedef int DataType;
typedef struct BSTreeNode
{
struct BSTreeNode* _pLeft;
struct BSTreeNode* _pRight;
DataType _data;
}BSTNode;
#include<assert.h>
#include<stdio.h>
#include<stdlib.h>
BSTNode* BuyBSTreeNode(DataType data)
{
BSTNode* pNewNode = (BSTNode*)malloc(sizeof(BSTNode));
if(NULL == pNewNode)//申请失败的话
{
assert(0);
return NULL;
}
pNewNode->_data = data;
pNewNode->_pLeft = NULL;
pNewNode->_pRight = NULL;
return pNewNode;
}
void BSTreeInit(BSTNode** pRoot)
{
assert(pRoot);
*pRoot = NULL;
}
void BSTreeInsert(BSTNode** pRoot,DataType data)//非递归的
{
BSTNode* pCur = NULL;
BSTNode* pParent = NULL;
assert(pRoot);
if(*pRoot == NULL)
{
*pRoot = BuyBSTreeNode(data);
return;
}
//1、找待插入节点的插入位置
pCur = *pRoot;//从根的位置找
while(pCur)
{
if(data < pCur->_data)
{
pParent = pCur;
pCur = pCur->_pLeft;//往左边走
}
else if(data >pCur->_data)
{
pParent = pCur;
pCur = pCur->_pRight;//往后边走
}
else//说明已经存在了
return;
}
//2、插入新节点
pCur = BuyBSTreeNode(data);
if(data < pParent->_data)//如果插入的新数据小于双亲的数据往左边插
pParent->_pLeft = pCur;
else
pParent->_pRight = pCur;
}
void BSTreeInsert(BSTNode** pRoot,DataType data)//递归的
{
assert(pRoot);//保证树存在
if(NULL == *pRoot)//树是空的
*pRoot = BuyBSTreeNode(data);
else
{
if(data < (*pRoot)->_data)//要插入的数据小于根节点的data,往左边插
BSTreeInsert(&(*pRoot)->_pLeft,data);
else if(data > (*pRoot)->_data)//往右边插
BSTreeInsert(&(*pRoot)->_pRight,data);
else //已经找到了
return;
}
}
void BSTreeDelete(BSTNode** pRoot,DataType data)//删除结点(非递归的)
{
BSTNode* pCur = NULL;
BSTNode* pParent = NULL;
assert(pRoot);
pCur = *pRoot;
//1、找待删除结点在二叉搜索树中的位置
while(pCur)
{
if(data == pCur->_data)
break;
else if(data < pCur->_data)
{
pParent = pCur;
pCur = pCur->_pLeft;
}
else
{
pParent = pCur;//保存双亲
pCur = pCur->_pRight;
}
}
if(pCur == NULL)
return;
//只有右孩子 或者 是叶子节点
if(pCur->_pLeft == NULL)
{
if(pCur == *pRoot)
{
*pRoot = pCur->_pRight;
}
else
{
//检测待删除结点是其双亲的左还是右
if(pParent->_pLeft == pCur)//pCur是双亲的左孩子
pParent->_pLeft = pCur->_pRight;
else//是双亲的右孩子
pParent->_pRight = pCur->_pRight;
}
}
else if(NULL == pCur->_pRight)//只有左孩子
{
if(pCur == *pRoot)//如果删除的是根
*pRoot = pCur->_pLeft;//根指向当前的左子树
else//不是根
{
if(pParent->_pLeft == pCur)//如果是双亲的左孩子
pParent->_pLeft = pCur->_pLeft;
else//双亲的右孩子
pParent->_pRight = pCur->_pLeft;
}
}
else
{
//左右孩子都存在
//在右子树中找最左侧的结点,也就是最小的结点。
BSTNode* pDel = pCur->_pRight;//先让它走到右子树的那边,然后再找最左边的结点
pParent = pCur;
while(pDel->_pLeft)
{
pParent = pDel;
pDel = pDel->_pLeft;
}
pCur->_data = pDel->_data;//在右子树中删除pDel
if(pDel == pParent->_pLeft)//要删除的pDel是双亲的左孩子
pParent->_pLeft = pDel->_pRight;
else
pParent->_pRight = pDel->_pRight;
pCur = pDel;
}
free(pCur);
}
void BSTreeDelete(BSTNode** pRoot,DataType data)//删除结点(递归的)
{
assert(pRoot);//保证树存在
if(NULL == *pRoot)//树是空的
return;
else
{
if(data < (*pRoot)->_data)//要插入的数据小于根节点的data,在左边删除data
BSTreeDelete(&(*pRoot)->_pLeft,data);
else if(data > (*pRoot)->_data)//在右边删除data
BSTreeDelete(&(*pRoot)->_pRight,data);
else //在根的位置
{
//左孩子为空,只有右孩子或者叶子节点
BSTNode* pDel = *pRoot;
if(NULL == pDel->_pLeft)
{
*pRoot = pDel->_pRight;
free(pDel);
}
else if(NULL == pDel->_pRight) //只有左孩子
{
*pRoot = pDel->_pLeft;
free(pDel);
}
else//左右孩子都存在
{
pDel = (*pRoot)->_pRight;//在右子树中找替代结点
while(pDel->_pLeft)//在右子树中找最左边的结点
pDel = pDel->_pLeft;//一直在左边找
(*pRoot)->_data = pDel->_data;//替代结点的数据交给待删除结点
BSTreeDelete(&(*pRoot)->_pRight,pDel->_data);//pDel在pRoot的右子树中,然后再在pRoot的右子树中删除pDel的data
}
}
}
}
BSTNode* BSTreeFind(BSTNode* pRoot,DataType data)//非递归
{
BSTNode* pCur = pRoot;
while(pCur)
{
if(data = pCur->_data)
return pCur;
else if(data < pCur->_data)
pCur = pCur->_pLeft;
else
pCur = pCur->_pRight;
}
return NULL;
}
BSTNode* BSTreeFind(BSTNode* pRoot,DataType data)//递归的
{
if(NULL == pRoot)//这个树为空
return NULL;
else//这个树不为空
{
if(data == pRoot->_data)// 删除的结点是不是根节点
return pRoot;
else if(data < pRoot->_data)//要找的这个是数小于根节点的data。在左子树中找
return BSTreeFind(pRoot->_pLeft,data);//在左子树中递归找data
else
return BSTreeFind(pRoot->_pRight,data);//在右子树中递归找data
}
}
void InOrder(BSTNode* pRoot)//中序遍历
{
if(pRoot)//如果这个树不为空
{
InOrder(pRoot->_pLeft);
printf("%d ",pRoot->_data);
InOrder(pRoot->_pRight);
}
}
void BSTreeDestroy(BSTNode** pRoot)
{
assert(pRoot);
if(*pRoot)
{
BSTreeDestroy(&(*pRoot)->_pLeft);//先销毁左子树
BSTreeDestroy(&(*pRoot)->_pRight);//销毁右子树
free(*pRoot);
*pRoot = NULL;
}
}
void TestBSTree()
{
int a[] = {5,3,4,1,7,8,2,6,0,9};
int i = 0;
BSTNode* pRoot;
BSTreeInit(&pRoot);
for(;i < sizeof(a)/sizeof(a[0]);++i)
{
BSTreeInsert(&pRoot,a[i]);
}
printf("中序遍历的结果:");
InOrder(pRoot);
printf("\n");
BSTreeInsert(&pRoot,10);
BSTreeDelete(&pRoot,2);
printf("中序遍历的结果:");
InOrder(pRoot);
printf("\n");
BSTreeDelete(&pRoot,1);
printf("中序遍历的结果:");
InOrder(pRoot);
printf("\n");
//分别删除5 和 7
BSTreeDelete(&pRoot,5);
//BSTreeDelete(&pRoot,7);
printf("中序遍历的结果:");
InOrder(pRoot);
printf("\n");
BSTreeDestroy(&pRoot);
//BSTreeDelete(&pRoot,2);
}
//1、删除的该结点左右孩子均为空(叶子)-----直接删除
//2、删除的该结点只有左孩子------直接删除
//3、删除的该结点只有右孩子------直接删除
/*(1)待删除的结点没有双亲
(2)待删除节点是其双亲的左或者右
(1)是双亲的左:pParent->left = pCur->right
(2)是双亲的右:pParent->right = pCur->right*/
//4、删除的该结点左右孩子都存在:一、在左子树或者右子树找替代结点
//(1)、左子树中找替代---找左子树中最大的结点
//(2)、右子树中找替代---找右子树中最小的结点
//二、将替代结点中的数据交给待删除结点(pDel)
//三、连接起来
/*(1)pDel为其双亲的左孩子
(2)pDel为其双亲的右孩子*/
二叉搜索树的基本操作
最新推荐文章于 2022-07-08 14:24:05 发布