特点= =//
没有重复的元素
每个节点左侧的数都小于该节点,该节点右侧的数都大于该节点
每棵子树都是一颗二叉搜索树
好处= =//
使用时消耗的时间取决于树的高度= =//
但是如果树退化成单枝树= =//耗子尾汁哈
操作= =//
中序遍历
中序遍历二叉树,从小到大打印
若想从大到小输出,只要把两次递归的顺序调换即可= =或者你也可以自己用个mode控制
//中序遍历二叉树,从小到大打印
//若想从大到小输出,只要把两次递归的顺序调换即可= =或者你也可以自己用个mode控制
void InOder(BSTree ptr)
{
if (ptr != nullptr)
{
InOder(ptr->lchild);
cout << ptr->key << " ";
InOder(ptr->rchild);
}
}
插入节点
插入时要注意,重复的数据在插入时会自动排除= =//
同时如果想的话,你也可以自己记录一下节点个数
//购买一个节点供自己使用(奢侈脸)
BSTree BuyNode()
{
BSTree t = (BstNode*)malloc(sizeof(BstNode));
if (nullptr == t) exit(1);
memset(t, 0, sizeof(BstNode)); //初始化节点
return t;
}
//给大树造根
BSTree MakeRoot(KeyType kx)
{
BSTree s = BuyNode();
s->key = kx;
return s;
}
//插入节点
BSTree Insert(BSTree ptr, KeyType kx)
{
if (ptr == nullptr) //无根就造一个根出来
{
ptr = MakeRoot(kx);
return ptr;
}
BSTree par = nullptr; //记录上一个节点(父节点)
BSTree p = ptr;
while (p != nullptr && p->key != kx) //寻找位置并排查数据
{
par = p;
p = kx < p->key ? p->lchild : p->rchild;
}
if (p != nullptr && p->key == kx) return ptr; //如果发现数据有重复
p = BuyNode(); //奢侈一下
p->key = kx;
p->parent = par; //连接节点
if (p->key < par->key) par->lchild = p; //反向连接
else par->rchild = p;
return ptr;
}
寻找某树的最大最小值
最小值在左下角,最大值在右下角
//寻找树中的最小值
BSTree FindMin(BSTree ptr)
{
BSTree t = ptr;
//最小值一定在左下角
while (t != nullptr && t->lchild != nullptr)
t = t->lchild;
return t;
}
//寻找树中的最大值
BSTree FindMax(BSTree ptr)
{
BSTree t = ptr;
//最大值一定在右下角
while (t != nullptr && t->rchild != nullptr)
t = t->rchild;
return t;
}
寻找前驱和后继
就是刚好比他大又或刚好比他小的了。。
刚好比他大:将树中数据排序后,比他大且离他最近
BSTree Prev(BSTree pt)
{
BSTree ptr = pt;
if (ptr == nullptr) return nullptr;
//如果有左子树就在左子树里找
if (ptr->lchild != nullptr) return FindMax(ptr->lchild); //比它小的数里找最大
else
{
//没有左子树就顺藤摸瓜向上找
BSTree par = ptr->parent;
while (par != nullptr && par->rchild != ptr)
{
ptr = par;
par = ptr->parent;
}
return par;
}
}
//寻找当前节点的后继节点
//就是数据比它大且离他最近
BSTree Next(BSTree pt)
{
BSTree ptr = pt;
if (ptr == nullptr) return nullptr;
if (ptr->rchild != nullptr) return FindMin(ptr->rchild); //比它大的数里找最小
else
{
BSTree par = ptr->parent;
while (par != nullptr && par->lchild != ptr)
{
ptr = par;
par = ptr->parent;
}
return par;
}
}
删除节点
因为该类二叉树没有重复的元素
所以只要指定要删除的数据,即可删除其对应的节点
(先找到该数据的位置,然后进行删除= =//)
如果树中没有这个数据,直接开溜= =//
重要的是,
我们要删除的节点会分为三种类型:无孩子(叶子),有一个孩子,有两个孩子
无孩子的节点,我们找到其位置直接删除即可
有一个孩子的节点,直接帮助其儿子谋权篡位,顶替他的父亲即可
至于有两个孩子的节点(幸福美满)= =//
我们就要找一个数据刚好比它小,或者刚好比它大的节点,我们称之为该节点的前驱和后继,
然后使用其前驱或后继的数据代替父节点的数据,然后删除刚才用来替换的羔羊= =//
//删除节点
BSTree Delete(BSTree pt,KeyType kx)
{
BSTree ptr = pt;
BSTree temp = nullptr;
//寻找要删除的节点的位置↓
if (!ptr)
cout << "无此元素" << endl;
else if (kx < ptr->key) ptr->lchild = Delete(ptr->lchild, kx); //切记更新指针
else if (kx > ptr->key) ptr->rchild = Delete(ptr->rchild, kx);
else //锁定要删除的节点位置
{
//如果有两个好大儿
if (ptr->lchild && ptr->rchild)
{
//找它的后继代替他
temp = FindMin(ptr->rchild);
ptr->key = temp->key;
//删掉用来替换的节点
ptr->rchild = Delete(ptr->rchild, ptr->key);
}
else //如果有一个好大儿或者没有
{
temp = ptr;
//孩子直接代替它爹的位置
if (!ptr->lchild)
ptr = ptr->rchild;
else if (!ptr->rchild)
ptr = ptr->lchild;
free(temp); //彻底删除
}
}
return ptr;
}
全部= =//
#include <iostream>
#include <cstdlib>
#define T true
#define F false
typedef int KeyType; //为了方便切换种类
using namespace std;
typedef struct node {
KeyType key;
struct node* lchild; //左子树
struct node* rchild; //右子树
struct node* parent; //它老爹
}BstNode,*BSTree;
//购买一个节点供自己使用(奢侈脸)
BSTree BuyNode()
{
BSTree t = (BstNode*)malloc(sizeof(BstNode));
if (nullptr == t) exit(1);
memset(t, 0, sizeof(BstNode)); //初始化节点
return t;
}
//给大树造根
BSTree MakeRoot(KeyType kx)
{
BSTree s = BuyNode();
s->key = kx;
return s;
}
//中序遍历二叉树,从小到大打印
//若想从大到小输出,只要把两次递归的顺序调换即可= =或者你也可以自己用个mode控制
void InOder(BSTree ptr)
{
if (ptr != nullptr)
{
InOder(ptr->lchild);
cout << ptr->key << " ";
InOder(ptr->rchild);
}
}
//插入节点
BSTree Insert(BSTree ptr, KeyType kx)
{
if (ptr == nullptr) //无根就造一个根出来
{
ptr = MakeRoot(kx);
return ptr;
}
BSTree par = nullptr; //记录上一个节点(父节点)
BSTree p = ptr;
while (p != nullptr && p->key != kx) //寻找位置并排查数据
{
par = p;
p = kx < p->key ? p->lchild : p->rchild;
}
if (p != nullptr && p->key == kx) return ptr; //如果发现数据有重复
p = BuyNode(); //奢侈一下
p->key = kx;
p->parent = par; //连接节点
if (p->key < par->key) par->lchild = p; //反向连接
else par->rchild = p;
return ptr;
}
//寻找树中的最小值
BSTree FindMin(BSTree ptr)
{
BSTree t = ptr;
//最小值一定在左下角
while (t != nullptr && t->lchild != nullptr)
t = t->lchild;
return t;
}
//寻找树中的最大值
BSTree FindMax(BSTree ptr)
{
BSTree t = ptr;
//最大值一定在右下角
while (t != nullptr && t->rchild != nullptr)
t = t->rchild;
return t;
}
//寻找当前节点的前驱节点
//就是数据比它小且离他最近
BSTree Prev(BSTree pt)
{
BSTree ptr = pt;
if (ptr == nullptr) return nullptr;
//如果有左子树就在左子树里找
if (ptr->lchild != nullptr) return FindMax(ptr->lchild); //比它小的数里找最大
else
{
//没有左子树就顺藤摸瓜向上找
BSTree par = ptr->parent;
while (par != nullptr && par->rchild != ptr)
{
ptr = par;
par = ptr->parent;
}
return par;
}
}
//寻找当前节点的后继节点
//就是数据比它大且离他最近
BSTree Next(BSTree pt)
{
BSTree ptr = pt;
if (ptr == nullptr) return nullptr;
if (ptr->rchild != nullptr) return FindMin(ptr->rchild); //比它大的数里找最小
else
{
BSTree par = ptr->parent;
while (par != nullptr && par->lchild != ptr)
{
ptr = par;
par = ptr->parent;
}
return par;
}
}
//删除节点
BSTree Delete(BSTree pt,KeyType kx)
{
BSTree ptr = pt;
BSTree temp = nullptr;
//寻找要删除的节点的位置↓
if (!ptr)
cout << "无此元素" << endl;
else if (kx < ptr->key) ptr->lchild = Delete(ptr->lchild, kx); //切记更新指针
else if (kx > ptr->key) ptr->rchild = Delete(ptr->rchild, kx);
else //锁定要删除的节点位置
{
//如果有两个好大儿
if (ptr->lchild && ptr->rchild)
{
//找它的后继代替他
temp = FindMin(ptr->rchild);
ptr->key = temp->key;
//删掉用来替换的节点
ptr->rchild = Delete(ptr->rchild, ptr->key);
}
else //如果有一个好大儿或者没有
{
temp = ptr;
//孩子直接代替它爹的位置
if (!ptr->lchild)
ptr = ptr->rchild;
else if (!ptr->rchild)
ptr = ptr->lchild;
free(temp); //彻底删除
}
}
return ptr;
}
int main()
{
int i;
BSTree root = nullptr; //初始化根节点,必须写nullptr
for (i = 10; i >= 0; --i)
root = Insert(root, i); //插入
for (i = 20; i >= 0; --i)
root = Insert(root, i); //插入
root = Delete(root, 5); //删除
root = Delete(root, 15);
InOder(root); //打印
system("pause");
return 0;
}
至于这个二叉搜索树会退化成单枝树的问题。。我们可以使用平衡二叉树和它融合来解决= =//
再见= =//