二叉搜索树也称为二叉排序树,具有以下性质:
1.若它的左子树不为空,则左子树上所有结点的值都小于根节点的值;
2.若它的右子树不为空,则右子树上所有节点的值都小于根节点的值;
3.它的左右子树均是二叉搜索树。
本篇正是利用二叉搜索树的这些性质实现了查找节点、插入节点以及删除节点的基本操作(递归及循环实现)。
头文件
BinarySearchTree.h
# ifndef __BINARYSEARCHTREE_H__
# define __BINARYSEARCHTREE_H__
# include <stdio.h>
# include <stdlib.h>
# include <assert.h>
typedef int DataType;
typedef struct BSTree
{
DataType data;
struct BSTree * pLeft;
struct BSTree * pRight;
}BSTree, * pBSTree;
int BSTreeInsert(pBSTree * pRoot, DataType data); // (循环实现)在二叉搜索树中插入数据,若插入数据成功则返回0,失败则返回-1
int BSTreeInsertRecursion(pBSTree * pRoot, DataType data); // (递归实现)在二叉搜索树中插入数据,若插入数据成功则返回0,失败则返回-1
int BSTreeFind(pBSTree pRoot, DataType data); // (循环实现)在二叉搜索树中查找某个数据,找到返回0,没找到返回-1
int BSTreeFindRecursion(pBSTree pRoot, DataType data); // (递归实现)在二叉搜索树中查找某个数据,找到返回0,没找到返回-1
int BSTreeRemove(pBSTree * pRoot, DataType data); // (循环实现)在二叉搜索树中删除某个数据,删除成功则返回0,失败则返回-1
int BSTreeRemoveRecursion(pBSTree * pRoot, DataType data); // (递归实现)在二叉搜索树中删除某个数据,删除成功则返回0,失败则返回-1
void BSTreeInOrder(pBSTree pRoot); // 中序遍历(递归)
# endif // __BINARYSEARCHTREE_H__
难点剖析
删除结点
当找到需要删除的结点时,分情况讨论即可。
1.左孩子为空
2.右孩子为空
3.左右孩子均为空
4.左右孩子均不为空
a.替换左子树中最大的;
b.替换右子树中最小的。
实际上,左右孩子均为空这种情况可以归为1或者2处理即可,是个特例。综上,分三种情况讨论即可。
源代码
BinarySearchTree.c
#define _CRT_SECURE_NO_WARNINGS 1
/*
* Copyright (c) 2018, code farmer from sust
* All rights reserved.
*
* 文件名称:BinarySearchTree.c
* 功能:二叉搜索树的基本操作内部实现细节
*
* 当前版本:V1.0
* 作者:sustzc
* 完成日期:2018年6月21日15:06:25
*/
# include "BinarySearchTree.h"
/*
* 函数名称:CreateTreeNode
*
* 函数功能:创建新的结点
*
* 入口参数:data
*
* 出口参数:pNewNode
*
* 返回类型:pBSTree
*/
pBSTree CreateTreeNode(DataType data)
{
pBSTree pNewNode = (pBSTree)malloc(sizeof(BSTree));
assert(pNewNode);
pNewNode->data = data;
pNewNode->pLeft = pNewNode->pRight = NULL;
return pNewNode;
}
/*
* 函数名称:BSTreeInsert
*
* 函数功能:(循环实现)在二叉搜索树中插入数据,若插入数据成功则返回0,失败(data在树中)则返回-1
*
* 入口参数:pRoot, data
*
* 出口参数:0 or -1
*
* 返回类型:int
*/
int BSTreeInsert(pBSTree * pRoot, DataType data)
{
if (NULL == *pRoot)
{
*pRoot = CreateTreeNode(data);
return 0;
}
else
{
pBSTree pCur = *pRoot;
pBSTree pParent = NULL;
while (NULL != pCur)
{
pParent = pCur;
if (data == pCur->data)
{
return -1;
}
else if (data < pCur->data)
{
pCur = pCur->pLeft;
}
else
{
pCur = pCur->pRight;
}
}
if (data < pParent->data)
{
pParent->pLeft = CreateTreeNode(data);
}
else if (data > pParent->data)
{
pParent->pRight = CreateTreeNode(data);
}
else
{
;
}
}
return 0;
}
/*
* 函数名称:BSTreeInsertRecursion
*
* 函数功能:(递归实现)在二叉搜索树中插入数据,若插入数据成功则返回0,失败(data在树中)则返回-1
*
* 入口参数:pRoot, data
*
* 出口参数:0 or -1
*
* 返回类型:int
*/
int BSTreeInsertRecursion(pBSTree * pRoot, DataType data)
{
if (NULL == *pRoot)
{
*pRoot = CreateTreeNode(data);
return 0;
}
else
{
if (data == (*pRoot)->data)
{
return -1;
}
else if (data < (*pRoot)->data)
{
return BSTreeInsertRecursion(&((*pRoot)->pLeft), data);
}
else
{
return BSTreeInsertRecursion(&((*pRoot)->pRight), data);
}
}
return 0;
}
/*
* 函数名称:BSTreeFind
*
* 函数功能:(循环实现)在二叉搜索树中查找某个数据,找到返回0,没找到返回-1
*
* 入口参数:pRoot, data
*
* 出口参数:0 or -1
*
* 返回类型:int
*/
int BSTreeFind(pBSTree pRoot, DataType data)
{
if (NULL == pRoot)
{
return -1;
}
else
{
pBSTree pCur = pRoot;
while (NULL != pCur)
{
if (data == pCur->data)
{
return 0;
}
else if (data < pCur->data)
{
pCur = pCur->pLeft;
}
else
{
pCur = pCur->pRight;
}
}
}
return -1;
}
/*
* 函数名称:BSTreeFind
*
* 函数功能:(递归实现)在二叉搜索树中查找某个数据,找到返回0,没找到返回-1
*
* 入口参数:pRoot, data
*
* 出口参数:0 or -1
*
* 返回类型:int
*/
int BSTreeFindRecursion(pBSTree pRoot, DataType data)
{
if (NULL == pRoot)
{
return -1;
}
else if (data == pRoot->data)
{
return 0;
}
else if (data < pRoot->data)
{
return BSTreeFindRecursion(pRoot->pLeft, data);
}
else
{
return BSTreeFindRecursion(pRoot->pRight, data);
}
}
/*
* 函数名称:BSTreeRemove
*
* 函数功能:(循环实现)在二叉搜索树中删除某个数据,删除成功返回0,失败返回-1(data不在树中)
*
* 入口参数:pRoot, data
*
* 出口参数:0 or -1
*
* 返回类型:int
*/
int BSTreeRemove(pBSTree * pRoot, DataType data)
{
pBSTree pCur = *pRoot;
pBSTree pParent = NULL;
pBSTree pDelParent = NULL;
while (NULL != pCur)
{
if (data == pCur->data)
{
//左孩子为空
if (NULL == pCur->pLeft)
{
//此时的pCur不是根节点
if (NULL != pParent)
{
if (data < pParent->data)
{
pParent->pLeft = pCur->pRight;
}
else
{
pParent->pRight = pCur->pRight;
}
}
else
{
*pRoot = pCur->pRight;
}
free(pCur);
}
//右孩子为空
else if (NULL == pCur->pRight)
{
if (NULL != pParent)
{
if (data < pParent->data)
{
pParent->pLeft = pCur->pLeft;
}
else
{
pParent->pRight = pCur->pLeft;
}
}
else
{
*pRoot = pCur->pLeft;
}
free(pCur);
}
//左右孩子均不为空(替换法),用右子树中最小的替换
else
{
//pBSTree pDel = pCur->pRight;
//pDelParent = pCur;
//while (NULL != pDel->pLeft)
//{
// pDelParent = pDel;
// pDel = pDel->pLeft;
//}
//pCur->data = pDel->data;
//pDel->data = data;
//
//pCur = pCur->pRight;
pBSTree pDel = pCur->pRight;
pDelParent = pCur;
while (NULL != pDel->pLeft)
{
pDelParent = pDel;
pDel = pDel->pLeft;
}
pCur->data = pDel->data;
if (pCur == pDelParent)
{
pDelParent->pRight = pDel->pRight;
}
else
{
pDelParent->pLeft = pDel->pRight;
}
free(pDel);
}
return 0;
}
else
{
pParent = pCur;
}
if (data < pCur->data)
{
pCur = pCur->pLeft;
}
else
{
pCur = pCur->pRight;
}
}
return -1;
}
/*
* 函数名称:BSTreeRemoveRecursion
*
* 函数功能:(递归实现)在二叉搜索树中删除某个数据,删除成功返回0,失败返回-1(data不在树中)
*
* 入口参数:pRoot, data
*
* 出口参数:0 or -1
*
* 返回类型:int
*/
int BSTreeRemoveRecursion(pBSTree * pRoot, DataType data)
{
if (NULL == *pRoot)
{
return -1;
}
else if (data < (*pRoot)->data)
{
return BSTreeRemoveRecursion(&((*pRoot)->pLeft), data);
}
else if (data > (*pRoot)->data)
{
return BSTreeRemoveRecursion(&((*pRoot)->pRight), data);
}
else
{
pBSTree pFree = *pRoot;
//左孩子为空
if (NULL == (*pRoot)->pLeft)
{
*pRoot = (*pRoot)->pRight;
free(pFree);
return 0;
}
//右孩子为空
else if (NULL == (*pRoot)->pRight)
{
*pRoot = (*pRoot)->pLeft;
free(pFree);
return 0;
}
//左右孩子均不为空
else
{
pBSTree pDel = (*pRoot)->pRight;
while (NULL != pDel->pLeft)
{
pDel = pDel->pLeft;
}
//替换
(*pRoot)->data = pDel->data;
BSTreeRemoveRecursion(&((*pRoot)->pRight), pDel->data);
return 0;
}
}
}
/*
* 函数名称:BSTreeInOrder
*
* 函数功能:中序遍历(递归)
*
* 入口参数:pRoot
*
* 出口参数:void
*
* 返回类型:void
*/
void BSTreeInOrder(pBSTree pRoot)
{
if (NULL == pRoot)
{
return;
}
else
{
;
}
BSTreeInOrder(pRoot->pLeft);
printf("%d ", pRoot->data);
BSTreeInOrder(pRoot->pRight);
return;
}
test.c
#define _CRT_SECURE_NO_WARNINGS 1
/*
* Copyright (c) 2018, code farmer from sust
* All rights reserved.
*
* 文件名称:test.c
* 功能:测试二叉搜索树的基本操作
*
* 当前版本:V1.0
* 作者:sustzc
* 完成日期:2018年6月21日15:07:37
*/
# include "BinarySearchTree.h"
/*
* 函数名称:main
*
* 函数功能:测试主程序
*
* 入口参数:void
*
* 出口参数:0
*
* 返回类型:int
*/
int main(void)
{
pBSTree pRoot = NULL;
int i = 0;
/*BSTreeInsert(&pRoot, 5);
BSTreeInsert(&pRoot, 2);
BSTreeInsert(&pRoot, 3);
BSTreeInsert(&pRoot, 8);
BSTreeInsert(&pRoot, 9);
BSTreeInsert(&pRoot, 5);*/
BSTreeInsertRecursion(&pRoot, 5);
BSTreeInsertRecursion(&pRoot, 2);
BSTreeInsertRecursion(&pRoot, 3);
BSTreeInsertRecursion(&pRoot, 8);
BSTreeInsertRecursion(&pRoot, 9);
BSTreeInsertRecursion(&pRoot, 5);
printf("中序遍历二叉树(递归):\n");
BSTreeInOrder(pRoot);
printf("\n\n查找数据(循环):\n");
for (i = 0; i < 10; i++)
{
printf("查找数据: %d, 查找结果: %d\n", i, BSTreeFind(pRoot, i));
}
printf("\n查找数据(递归):\n");
for (i = 0; i < 10; i++)
{
printf("查找数据: %d, 查找结果: %d\n", i, BSTreeFindRecursion(pRoot, i));
}
/*BSTreeRemove(&pRoot, 2);
printf("\n中序遍历二叉树(递归):\n");
BSTreeInOrder(pRoot);
BSTreeRemove(&pRoot, 3);
printf("\n中序遍历二叉树(递归):\n");
BSTreeInOrder(pRoot);
BSTreeRemove(&pRoot, 8);
printf("\n中序遍历二叉树(递归):\n");
BSTreeInOrder(pRoot);
BSTreeRemove(&pRoot, 9);
printf("\n中序遍历二叉树(递归):\n");
BSTreeInOrder(pRoot);
BSTreeRemove(&pRoot, 5);
printf("\n中序遍历二叉树(递归):\n");
BSTreeInOrder(pRoot);
printf("\n");*/
BSTreeRemoveRecursion(&pRoot, 2);
printf("\n中序遍历二叉树(递归):\n");
BSTreeInOrder(pRoot);
BSTreeRemoveRecursion(&pRoot, 3);
printf("\n中序遍历二叉树(递归):\n");
BSTreeInOrder(pRoot);
BSTreeRemoveRecursion(&pRoot, 8);
printf("\n中序遍历二叉树(递归):\n");
BSTreeInOrder(pRoot);
BSTreeRemoveRecursion(&pRoot, 9);
printf("\n中序遍历二叉树(递归):\n");
BSTreeInOrder(pRoot);
BSTreeRemoveRecursion(&pRoot, 5);
printf("\n中序遍历二叉树(递归):\n");
BSTreeInOrder(pRoot);
printf("\n");
return 0;
}
输出结果