概述
本文是在学习数据结构时有感而发
二叉搜索树的递归实现性能比较差,所以除了函数DestroyBST()以外均采用循环而非递归实现
作者刚刚步入计算机行业,难免问题众多,欢迎各位大佬斧正
头文件BinarySearchTree.h
包含插入,查找,删除等操作
BinarySearchTree.h
#pragma once
#include<stdlib.h>
#include<stdbool.h>
#define ElementType int
//单向二叉查找树
struct BinarySearchTree
{
struct BinarySearchTree* leftChild;
ElementType element;
struct BinarySearchTree* rightChild;
};
typedef struct BinarySearchTree BST_node;//BST即首字母的组合
typedef struct BinarySearchTree* ptrBST_RootNode;
typedef ptrBST_RootNode Position;
//为树创建根节点
ptrBST_RootNode CreateBinarySearchTree()
{
return (ptrBST_RootNode)calloc(1, sizeof(BST_node));
}
//将树销毁
ptrBST_RootNode DestoryBST(ptrBST_RootNode tree)
{
if (tree)
{
DestoryBST(tree->leftChild);
DestoryBST(tree->rightChild);
free(tree);
}
return NULL;
}
//查找树的最小值
Position FindMin(ptrBST_RootNode tree)
{
Position min = tree;
while (min->leftChild)
{
min = min->leftChild;
}
return min;
}
//查找树的最大值
Position FindMax(ptrBST_RootNode tree)
{
if (!tree)
{
return NULL;
}
else
{
Position max = tree;
while (max->rightChild)
{
max = max->rightChild;
}
return max;
}
}
//二叉搜索树的插入
ptrBST_RootNode InsertBST(ElementType element, ptrBST_RootNode tree)
{
if (!tree)//检测是否为空树
{
tree = (ptrBST_RootNode)calloc(1, sizeof(BST_node));
if (tree)
{
tree->element = element;
}
else
return NULL;
}
else
{
Position pointer = tree;
while (true)
{
if (pointer->element > element)//向左子树推进
{
if (!pointer->leftChild)
{
pointer->leftChild = (Position)calloc(1, sizeof(BST_node));
if (pointer->leftChild)
{
pointer->leftChild->element = element;
break;
}
else
{
return NULL;
}
}
else
{
pointer = pointer->leftChild;
}
}
if (pointer ->element <element)//向右子树推进
{
if (!pointer->rightChild)
{
pointer->rightChild = (Position)calloc(1, sizeof(BST_node));
if (pointer->rightChild)
{
pointer->rightChild->element = element;
break;
}
else
{
return NULL;
}
}
else
{
pointer = pointer->rightChild;
}
}
if (pointer->element == element)//此节点已存在于树中,无需插入
{
break;
}
}
}
return tree;
}
//查找的基础函数
Position PositionIsEmpty(ptrBST_RootNode tree, ElementType element)
{
if (tree)//当tree所指的节点不为null时,返回true,原函数继续向下寻找
{
if (element > tree->element)
{
return tree->rightChild;
}
else
{
return tree->leftChild;//注意,这里指针tree改变了原函数中sign所指向的节点
}
}
else//当tree所指的节点为null时,创建一个新的节点,然后返回false,将原函数跳出循环
{
tree = InsertBST(element, tree);//注意,这里指针tree改变了原函数中sign所指向的节点
return tree;
}
}
//查找操作
Position Find_BSTnode(const ptrBST_RootNode const tree, ElementType element)
{
/*递归实现
Position sign = NULL;
if (tree->element == element)
{
sign = tree;
return sign;
}
if (tree->element > element )
{
sign = Find_BSTnode(tree->rightChild, element);
}
if (tree->element < element)
{
sign = Find_BSTnode(tree->leftChild, element);
}
return sign;*/
//循环实现
Position sign = tree;
while (true)
{
if (sign->element == element)
{
break;
}
if (sign->element > element)
{
sign = PositionIsEmpty(sign, element);
continue;
}
if (sign->element < element)
{
sign = PositionIsEmpty(sign, element);
continue;
}
}
return sign;
}
//查找目标节点的父节点
Position Find_BSTnodeFather(const ptrBST_RootNode const tree, ElementType element)
{
Position sign = tree;
if (sign->element == element)//检测根节点
{
return NULL;
}
while (true)
{
if (sign->leftChild)//先判断sign的左右孩子是否存在再判断与element的关系
{
if (sign->leftChild->element == element)
break;
}
if (sign->rightChild)
{
if (sign->rightChild->element == element)
break;
}
if (sign->element > element)//进入左子树
{
sign = PositionIsEmpty(sign, element);//sign指向下一个节点
continue;
}
if (sign->element < element)//进入右子树
{
sign = PositionIsEmpty(sign, element);
continue;
}
}
return sign;
}
//二叉搜索树的删除操作
Position Delete_BSTnode_element(ptrBST_RootNode tree, ElementType element)
{
Position pointer = Find_BSTnode(tree, element);//查找要删除的目标节点的位置
Position pointerfather = Find_BSTnodeFather(tree, element);//查找目标节点的父节点
if (pointerfather)//当pointerfather不为空,即pointer不是此树的根节点时
{
Position left = pointer->leftChild;
Position right = pointer->rightChild;
//若目标节点为父节点的右孩子,则删除后,父节点的右孩子指向目标节点的左子树
//目标节点的左子树的最大节点的右孩子指向目标节点的右子树
if (pointer->element > pointerfather->element)
{
Position left_max = FindMax(pointer->leftChild);
if (left_max)
{
pointerfather->rightChild = pointer->leftChild;
left_max->rightChild = right;
}
else
{
pointerfather->rightChild = pointer->rightChild;
}
}
//若目标节点为父节点的左孩子,则删除后,父节点的左孩子指向目标节点的右子树
//目标节点的右子树的最小节点的左孩子指向目标节点的左子树
else
{
Position right_min = FindMin(pointer->rightChild);
if (right_min)
{
pointerfather->leftChild = pointer->rightChild;
right_min->leftChild = pointer->leftChild;
}
else
{
pointerfather->leftChild = pointer->leftChild;
}
}
free(pointer);//销毁节点
return tree;
}
else//当pointer是树的根节点时
{
Position right_min = FindMin(pointer->rightChild);
Position left = pointer->leftChild;
if (right_min)
{
right_min->leftChild = pointer->leftChild;//将左子树接入right_min的左孩子
}
free(pointer);
return left;
}
}
测试函数
test.c
#include<stdio.h>
#include"BinarySearchTree.h"
int main()
{
ptrBST_RootNode MyFirstBST = NULL;
// MyFirstBST = CreateBinarySearchTree();
MyFirstBST = InsertBST(5, MyFirstBST);
InsertBST(7, MyFirstBST);
InsertBST(3, MyFirstBST);
InsertBST(4, MyFirstBST);
InsertBST(9, MyFirstBST);
InsertBST(8, MyFirstBST);
InsertBST(6, MyFirstBST);
InsertBST(1, MyFirstBST);
InsertBST(10, MyFirstBST);
InsertBST(2, MyFirstBST);
Position place = InsertBST(2, MyFirstBST);
printf("测试插入重复元素:%p %d\n", place, place->element);
printf("此树的最小值为:%d\n", FindMin(MyFirstBST)->element);
printf("此树的最大值为:%d\n", FindMax(MyFirstBST)->element);
place = Find_BSTnode(MyFirstBST, 2);
printf("查找操作测试:\n元素2的位置为:%p %d\n", place, place->element);
place = Find_BSTnodeFather(MyFirstBST, 2);
printf("元素2的父节点位置为:%p %d\n", place, place->element);
printf("删除操作测试:\n");
ptrBST_RootNode new = Delete_BSTnode_element(MyFirstBST, 2);
printf("删除元素2后根节点的地址为:%p %d\n", new, new->element);
DestoryBST(MyFirstBST);
// printf("\n%p\n", MyFirstBST);
return 0;
}