二叉排序树的建立、查找、插入、删除详解及C++实现
二叉排序树的建立、查找、插入、删除详解及C++实现
二叉排序树(Binary Search Tree,BST)是一种特殊的二叉树,其中每个节点的值都大于其左子树中的所有节点的值,且小于其右子树中的所有节点的值。这种结构使得二叉排序树在查找、插入和删除操作中具有较高的效率。本文将详细介绍二叉排序树的基本操作,并通过C++代码实现这些操作。
实验题目
设计一个算法,建立一棵二叉排序树,并实现对它进行查找、插入、删除操作。
问题分析
二叉排序树的理解
二叉排序树是一颗二叉树,每个节点最多有两个子节点。对于二叉排序树来说,任何节点的键值一定大于其左子树中的每一个节点的键值,并小于其右子树中的每一个节点的键值。
二叉排序树的建立
二叉树的排序建立主要使用了二叉树排序的插入操作。具体思路为:先输入一个n表示二叉树结点的个数,再使用for循环依次输入n个数,进行n次二叉排序树的插入,这样就建立起了一个二叉排序树。
二叉排序树的查找
查找操作的思路为:如果当前结点比要找的数小,就往当前结点的右子树找,否则就往当前结点的左子树找。直到找到叶子结点,如果叶子结点是要找的数,那么查找成功,否则查找失败。
二叉排序树的插入
插入操作的思路为:
- 如果树为空,当前结点作为根结点
- 如果要插入的数比当前结点大,就往当前结点的右子树走,否则就往当前结点的左子树走,直到末端,如果比末端的这个元素小,就成为它的左孩子,否则就成为它的右孩子。
二叉排序树的删除
删除操作相对繁琐,一共有两种情况:
- 如果A只有一个子节点,就直接将A的子节点连至A的父节点上,并将A删除。
- 如果A有两个子节点,我们就以右子树内的最小节点取代A,对于怎么得最小节点,这个最小结点就是A右子树最左下角那个结点。
二叉树排序遍历
这里采取的先序遍历,就是先遍历左子树再遍历当前结点最后遍历右子树。
输入
输入数据为:10,7,15,20,6,8,3。共7个数。按照输入的顺序构建二叉排序树,输出先序遍历结果,然后再分别输出插入9和删除15后先序遍历的结果。
完整代码
#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
typedef struct Bitnode { //结点结构
int data;
struct Bitnode *lchild, *rchild; //左右孩子指针
}Bitnode, *BitTree;
//非递归二叉排序树查找
BitTree Search_Bit(BitTree root, int key)
{
BitTree p = root;
while (p)
{
if (p->data == key) return p;
p = (key < p->data) ? p->lchild : p->rchild;
}
return NULL;
}
//二叉排序树的插入操作
void Insert_Bit(BitTree *root, int data)
{
//初始化插入节点
BitTree p = new Bitnode;
p -> data = data;
p -> lchild = p -> rchild = NULL;
//空树时,直接作为根节点
if (*root == NULL)
{
*root = p;
return;
}
//进行插入,首先找到要插入的位置的父节点
//然后如果比这个父节点小就成为它的左孩子,否则就成为它的右孩子
BitTree tnode = NULL, troot = *root;
while (troot)
{
tnode = troot;
troot = (data < troot -> data) ? troot -> lchild : troot -> rchild;
}
if (data < tnode -> data)
tnode -> lchild = p;
else
tnode -> rchild = p;
}
void DeleteBitNode(BitTree *root,int data)
{
BitTree p = *root, parent = NULL, s = NULL;
if (!p) return;
if (p -> data == data) //找到要删除的节点了
{
//叶子结点找到
if (!p->rchild && !p->lchild)
*root = NULL;
//只有一个左节点
else if (!p -> rchild&&p -> lchild)
*root = p->lchild;
//只有一个右节点
else if (!p -> lchild&&p -> rchild)
*root = p -> rchild;
//左右节点都不空
else
{
s = p -> rchild;
if (!s -> lchild)
s -> lchild = p -> lchild;
else
{
while (s -> lchild)
{
parent = s;
s = s -> lchild;
}
parent -> lchild = s -> rchild;
s -> lchild = p -> lchild;
s -> rchild = p -> rchild;
}
*root = s;
}
free(p);
}
else if (data > p -> data) //向右找
DeleteBitNode(&(p -> rchild), data);
else if (data < p -> data) //向左找
DeleteBitNode(&(p -> lchild), data);
}
void PreOrderTraverse(BitTree T)
{
if (T)
{
cout << T -> data << " ";
PreOrderTraverse(T -> lchild);
PreOrderTraverse(T -> rchild);
}
}
int main() {
//建立排序二叉树
int i;
int n;
cin >> n;
//n表示二叉树结点的个数
BitTree *T;
cout << "输入的数为:" << endl;
for (i = 0; i < n; i++)
{
int a;
cin >> a;
//a表示当前要插入的数值
Insert_Bit(T, a);
}
cout << "先序遍历的结果为:" << endl;
PreOrderTraverse(*T);
cout << endl;
Insert_Bit(T,9);
cout << "插入9后先序遍历的结果为:" << endl;
PreOrderTraverse(*T);
cout << endl;
DeleteBitNode(T,15);
cout << "删除15后先序遍历的结果为:" << endl;
PreOrderTraverse(*T);
return 0;
}
运行结果
在本次实验中,我们设计并实现了一个二叉排序树,并对其进行了查找、插入和删除操作。通过输入一组数据(10, 7, 15, 20, 6, 8, 3),我们构建了一棵二叉排序树,并输出了先序遍历的结果。接着,我们在树中插入了数字9,并再次输出了先序遍历的结果。最后,我们删除了数字15,并展示了删除后的先序遍历结果。
实验结果显示,二叉排序树的建立过程顺利,各个节点按照二叉排序树的规则正确插入。在插入数字9后,新的节点被正确地插入到合适的位置,保持了二叉排序树的性质。删除操作也按预期执行,当删除具有两个子节点的节点15时,算法选择了右子树中的最小节点来替代被删除的节点,确保了树的结构仍然满足二叉排序树的要求。
从运行结果来看,程序能够正确处理各种情况下的插入和删除操作,验证了算法的正确性和有效性。通过非递归方式进行查找,我们能够高效地找到目标节点或确定其不存在。整个实验过程中,二叉排序树的操作均表现稳定,没有出现异常情况。
本文原文来自CSDN