二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
算法实现分为递归和非递归:
1.插入节点
2.寻找节点
3.删除节点
//创建结构
#pragma once
#include<stdio.h>
#include<Windows.h>
#include<assert.h>
typedef int DataType;
typedef struct BSTreeNode
{
struct BSTreeNode* _left;
struct BSTreeNode* _right;
DataType _data;
}BSTreeNode;
// 非递归
BSTreeNode* BuyBSTreeNode(DataType x)
{
BSTreeNode* newnode = (BSTreeNode*)malloc(sizeof(BSTreeNode));
assert(newnode);
newnode->_data = x;
newnode->_left = NULL;
newnode ->_right = NULL;
return newnode;
}
//向二叉搜索树中插入一个节点
int BSTreeInsert(BSTreeNode** tree, DataType x)
{
//如果该树为空树,则直接把该节点作为根节点
//如果该树不是空树,则寻找该节点的位置,如果发现该节点已经存在于树中,则插入失败,返回0,插入成功返回1
//遍历各个节点找到x所插入节点cur,并定义一个parent找到cur的父母
//根据cur和parent的大小判断cur链左还是右
assert(tree);
BSTreeNode *cur = *tree;
BSTreeNode *parent = *tree;
if (*tree == NULL)
{
*tree = BuyBSTreeNode(x);
return 1;
}
else
{
while (cur)
{
if (cur->_data > x)
{
parent = cur;
cur = cur->_left;
}
else if (cur->_data < x)
{
parent = cur;
cur = cur->_right;
}
else
{
printf("该二叉搜索树中已经存在该值的节点\n");
return 0;
}
}
//运行到此处说明已经找到了要插入的位置及他的父亲节点
cur = BuyBSTreeNode(x);
if (parent->_data > x)//需要确定cur是链在parent左还是parent右
{
parent->_left = cur;
}
else
{
parent->_right = cur;
}
return 1;
}
}
const BSTreeNode* BSTreeFind(BSTreeNode* tree, DataType x)
{
assert(tree);
const BSTreeNode* cur = tree;
if (tree == NULL)
{
return NULL;
}
else
{
while (cur != NULL)
{
if (x < cur->_data)
{
cur = cur->_left;
}
else if (x > cur->_data)
{
cur = cur->_right;
}
else
{
return cur;
}
}
}
return NULL;
}
int BSTreeRemove(BSTreeNode** tree, DataType x)
{
assert(*tree);
BSTreeNode* cur = *tree;
BSTreeNode*parent = NULL; //存在只有一个节点情况
if (*tree == NULL)
{
return -1;
}
else
{
while (cur != NULL)
{
if ( x < cur->_data)
{
parent = cur;
cur = cur->_left;
}
else if (x > cur->_data)
{
parent = cur;
cur = cur->_right;
}
// 这时已找到删除节点cur
//删除位置: 1.叶子节点 2.无左孩子或右孩子 3.左右都有孩子
else if(cur->_data==x) //此时找到要删除节点
{
if (cur->_left == NULL) //左为空
{
if (parent == NULL)// 一个节点的情况
{
*tree = (*tree)->_right;
return 1;
}
if (parent->_left == cur)//cur时parent的左
{
parent->_left = cur->_right;
return 1;
}
if (parent->_right == cur)//cur时parent的右
{
parent->_right = cur->_right;
return 1;
}
}
if (cur->_right == NULL) //右为空,和上面情况相同
{
if (parent == NULL)
{
*tree = (*tree)->_left;
return 1;
}
if (parent->_left == cur)
{
parent->_left = cur->_left;
return 1;
}
if (parent->_right == cur)
{
parent->_right = cur->_left;
return 1;
}
}
else //删除节点有左右孩子
//思路:
//首先我们需要找到待删除节点cur的左子树上的最大值节点,或右子树的最小节点SubLeft
//交换cur和SubLeft的值 然后处理特殊情况,见下图
{
BSTreeNode* SubLeft = cur->_left;
BSTreeNode*parent = cur;
while (SubLeft->_right) //找到最左节点和和他的父亲
{
parent = SubLeft;
SubLeft = SubLeft->_right;
}
cur->_data = SubLeft->_data;
if (parent->_left == SubLeft)
{
parent->_left = SubLeft->_right;
free(SubLeft);
return 1;
}
else
{
free(SubLeft);
parent->_right = SubLeft->_right;
return 1;
}
}
}
}
}
return -1;
}
递归版:
int BSTreeInsertR(BSTreeNode** tree, DataType x)
{
if (*tree == NULL)
{
*tree = BuyBSTreeNode(x);
return 1;
}
if ((*tree)->_data < x)
{
return BSTreeInsertR(&(*tree)->_right, x);
}
if ((*tree)->_data > x)
{
return BSTreeInsertR(&(*tree)->_left, x);
}
else
{
return -1;
}
}
const BSTreeNode* BSTreeFindR(BSTreeNode* tree, DataType x)
{
if (tree == NULL)
{
return NULL;
}
if (x < tree->_data)
{
return BSTreeFindR(tree->_left, x);
}
if (x > tree->_data)
{
return BSTreeFindR(tree->_right, x);
}
else if (x == tree->_data)
{
return tree;
}
return NULL;
}
int BSTreeRemoveR(BSTreeNode** tree, DataType x)
{
if (*tree == NULL) //此时树为空或找到根的NULL
{
return -1;
}
if (x < (*tree)->_data)
{
return BSTreeRemoveR(&(*tree)->_left, x);
}
if (x > (*tree)->_data)
{
return BSTreeRemoveR(&(*tree)->_right, x);
}
else //已找到删除节点
{
if ((*tree)->_left == NULL)
{
*tree = (*tree)->_right;
}
else if ((*tree)->_right == NULL)
{
*tree = (*tree)->_left;
}
else
{
BSTreeNode *subright = (*tree)->_left;
while (subright->_right)
{
subright = subright->_right;
}
(*tree)->_data = subright->_data;
return BSTreeRemoveR(&(*tree)->_left, subright->_data);
}
}
return 1;
}
完整代码:
BST.h :
#pragma once
#include<stdio.h>
#include<Windows.h>
#include<assert.h>
typedef int DataType;
typedef struct BSTreeNode
{
struct BSTreeNode* _left;
struct BSTreeNode* _right;
DataType _data;
}BSTreeNode;
int BSTreeInsert(BSTreeNode** tree, DataType x);
const BSTreeNode* BSTreeFind(BSTreeNode* tree, DataType x);
int BSTreeRemove(BSTreeNode** tree, DataType x);
void BSTreeDestory(BSTreeNode* tree);
// 非递归
BSTreeNode* BuyBSTreeNode(DataType x)
{
BSTreeNode* newnode = (BSTreeNode*)malloc(sizeof(BSTreeNode));
assert(newnode);
newnode->_data = x;
newnode->_left = NULL;
newnode ->_right = NULL;
return newnode;
}
//向二叉搜索树中插入一个节点
int BSTreeInsert(BSTreeNode** tree, DataType x)
{
//如果该树为空树,则直接把该节点作为根节点
//如果该树不是空树,则寻找该节点的位置,如果发现该节点已经存在于树中,则插入失败,返回0
//插入成功返回1
assert(tree);
BSTreeNode *cur = *tree;
BSTreeNode *parent = *tree;
if (*tree == NULL)
{
*tree = BuyBSTreeNode(x);
return 1;
}
else
{
while (cur)
{
if (cur->_data > x)
{
parent = cur;
cur = cur->_left;
}
else if (cur->_data < x)
{
parent = cur;
cur = cur->_right;
}
else
{
return 0;
}
}
//运行到此处说明已经找到了要插入的位置及他的父亲节点
cur = BuyBSTreeNode(x);
if (parent->_data > x)//需要确定cur是链在parent左还是parent右
{
parent->_left = cur;
}
else
{
parent->_right = cur;
}
return 1;
}
}
const BSTreeNode* BSTreeFind(BSTreeNode* tree, DataType x)
{
assert(tree);
const BSTreeNode* cur = tree;
if (tree == NULL)
{
return NULL;
}
else
{
while (cur != NULL)
{
if (x < cur->_data)
{
cur = cur->_left;
}
else if (x > cur->_data)
{
cur = cur->_right;
}
else
{
return cur;
}
}
}
return NULL;
}
int BSTreeRemove(BSTreeNode** tree, DataType x)
{
assert(*tree);
BSTreeNode* cur = *tree;
BSTreeNode*parent = NULL; //存在只有一个节点情况
if (*tree == NULL)
{
return -1;
}
else
{
while (cur != NULL)
{
if ( x < cur->_data)
{
parent = cur;
cur = cur->_left;
}
else if (x > cur->_data)
{
parent = cur;
cur = cur->_right;
}
//删除位置: 1.叶子节点 2.无左孩子或右孩子 3.左右都有孩子
else if(cur->_data==x) //此时找到要删除节点
{
if (cur->_left == NULL) //左为空
{
if (parent == NULL)
{
*tree = (*tree)->_right;
return 1;
}
if (parent->_left == cur)
{
parent->_left = cur->_right;
return 1;
}
if (parent->_right == cur)
{
parent->_right = cur->_right;
return 1;
}
}
if (cur->_right == NULL) //右为空
{
if (parent == NULL)
{
*tree = (*tree)->_left;
return 1;
}
if (parent->_left == cur)
{
parent->_left = cur->_left;
return 1;
}
if (parent->_right == cur)
{
parent->_right = cur->_left;
return 1;
}
}
else //删除节点右左右孩子
//首先我们需要找到待删除节点的左子树上的最大值节点,
//或者右子树上的最小值节点,然后将该节点的参数值与待删除的节点参数值进行交换,
//最后删除该节点,
{
BSTreeNode* SubLeft = cur->_left;
BSTreeNode*parent = cur;
while (SubLeft->_right) //找到最左子树最大节点和他的父亲
{
parent = SubLeft;
SubLeft = SubLeft->_right;
}
cur->_data = SubLeft->_data;
if (parent->_left == SubLeft)
{
parent->_left = SubLeft->_right;
free(SubLeft);
return 1;
}
else
{
parent->_right = SubLeft->_left;
free(SubLeft);
return 1;
}
}
}
}
}
return -1;
}
//////////////////////////////////
//递归
//向二叉搜索树中插入一个节点
int BSTreeInsertR(BSTreeNode** tree, DataType x)
{
if (*tree == NULL)
{
*tree = BuyBSTreeNode(x);
return 1;
}
if ((*tree)->_data < x)
{
return BSTreeInsertR(&(*tree)->_right, x);
}
if ((*tree)->_data > x)
{
return BSTreeInsertR(&(*tree)->_left, x);
}
else
{
return -1;
}
}
const BSTreeNode* BSTreeFindR(BSTreeNode* tree, DataType x)
{
if (tree == NULL)
{
return NULL;
}
if (x < tree->_data)
{
return BSTreeFindR(tree->_left, x);
}
if (x > tree->_data)
{
return BSTreeFindR(tree->_right, x);
}
else if (x == tree->_data)
{
return tree;
}
return NULL;
}
int BSTreeRemoveR(BSTreeNode** tree, DataType x)
{
if (*tree == NULL) //此时树为空或找到根的NULL
{
return -1;
}
if (x < (*tree)->_data)
{
return BSTreeRemoveR(&(*tree)->_left, x);
}
if (x > (*tree)->_data)
{
return BSTreeRemoveR(&(*tree)->_right, x);
}
else //已找到删除节点
{
if ((*tree)->_left == NULL)
{
*tree = (*tree)->_right;
}
else if ((*tree)->_right == NULL)
{
*tree = (*tree)->_left;
}
else
{
BSTreeNode *subright = (*tree)->_left;
while (subright->_right)
{
subright = subright->_right;
}
(*tree)->_data = subright->_data;
return BSTreeRemoveR(&(*tree)->_left, subright->_data);
}
}
return 1;
}
void test()
{
BSTreeNode* BST;
BST = NULL;
BSTreeInsertR(&BST, 5);
BSTreeInsertR(&BST, 3);
BSTreeInsertR(&BST, 7);
BSTreeInsertR(&BST, 1);
BSTreeInsertR(&BST, 4);
BSTreeInsertR(&BST, 6);
BSTreeInsertR(&BST, 8);
BSTreeInsertR(&BST, 0);
BSTreeInsertR(&BST, 2);
BSTreeInsertR(&BST, 9);
const BSTreeNode* ret = BSTreeFindR(BST, 1);
BSTreeRemove(&BST, 3);
}