Day_20,二叉搜索树及常用相关函数的实现

二叉搜索树: 二叉树的一种,并且树中每个节点(x)左子树的关键字不大于x节点的关键字,右子树的关键字不小于x节点的关键字。
节点: 每个二叉搜索树的节点包含{left,right,p,key……}分别对应{左节点,右节点,父节点,关键字……[卫星数据]},在本文代码中,value代表key。
本文概要: 实现了如下二叉搜索树的一个封装类,分别包括
1、二叉搜索树的构建
2、前中后序遍历(前:p,left,right;中:left,p,right;后:left,right,p)
3、对应节点搜索
4、找到树中key最小/最大的节点
5、找到二叉搜索树中某个节点对应的前驱/后继(比其小的最大值/比其大的最小值)
6、二叉搜索树的插入
7、二叉搜索树的删除(这个较为复杂,后面有详解)

首先熟悉并实战一下:
Q:{6,5,2,5,7,8}构造成二叉搜索树;排列出其前中后序遍历的数组;6的前驱后继
在这里插入图片描述
A:
构造的二叉搜索树如上;
前序遍历:6,5,2,5,7,8
中序遍历:2,5,5,6,7,8
后序遍历:2,5,5,7,8,6
前驱:5
后继:7
Q: 再来一题难的,下图的前中后序遍历
在这里插入图片描述
A:
前序遍历:A,B,D,G,H,E,C,K,F,I,J
中序遍历:G,D,H,B,E,A,K,C,I,J,F
后序遍历:G,H,D,E,B,K,J,I,F,C,A

上代码(详解放在后面)

#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;

template<class T>
class TreeNode
{
public:
    TreeNode *left;//做孩子
    TreeNode *right;//右孩子
    TreeNode *p;//父亲
    T mValue;//该节点的值

    TreeNode(){}
    TreeNode(T value){
        mValue = value;
        left = NULL;
        right = NULL;
        p = NULL;
    }
    TreeNode(T value,TreeNode * left,TreeNode *right,TreeNode *parent){
        mValue = value;
        left = left;
        right = right;
        p = parent;
    }
    ~TreeNode(){
    }
};

template<class T>
class SearchTree
{
public:
    SearchTree();//创建空树
    SearchTree(TreeNode<T> a[]);//传入节点组创建树
    SearchTree(T a[],int length);//传入节点值组,创建树
    ~SearchTree();
    MidWalk();//中序遍历
    FrontWalk();//前序遍历
    BackWalk();//后序遍历
    TreeNode<T> * Search(T value);//找到值相等的节点
    TreeNode<T> * Minimum();//树中最小节点
    TreeNode<T> * Maximum();//树中最大节点
    TreeNode<T> * TreePredecessor(TreeNode<T> *node);//某节点的前任 狗头.jpg  小于该节点的 值最大节点
    TreeNode<T> * TreeSuccessor(TreeNode<T> *node);//某节点的后驱             大于该节点的 值最小节点
    string Insert(T value);//插入
    string Delete(T value);//删除
private:
    TreeNode<T> *root;
    InsertInner(TreeNode<T> *insertNode,TreeNode<T> *parentNode);
    MidWalkInner(TreeNode<T> *node);//中序遍历
    FrontWalkInner(TreeNode<T> *node);//前序遍历
    BackWalkInner(TreeNode<T> *node);//后序遍历
    TreeNode<T> * SearchInner(TreeNode<T> *node,T value);//搜索
    TreeNode<T> * MinimumInner(TreeNode<T> *node);//树中最小节点
    TreeNode<T> * MaximumInner(TreeNode<T> *node);//树中最大节点
    Transplant(TreeNode<T> *pNode,TreeNode<T> *subNode);//继承,subNode继承pNode原有的位置
    string strTrue;//用于返回true的字符串
    string strFalse;//用于返回false的字符串
    string strNull;//用于返回null的字符串
};

template<class T>
SearchTree<T>::SearchTree()
{
    strTrue = "true";
    strFalse = "false";
    strNull = "null";
}

template<class T>
SearchTree<T>::SearchTree(TreeNode<T> a[])
{
    strTrue = "true";
    strFalse = "false";
    strNull = "null";
}

template<class T>
SearchTree<T>::SearchTree(T a[],int length)
{
    int i = 0;
    TreeNode<T> *rootNd = new TreeNode<T>(a[i]);
    root = rootNd;
    i++;
    //大体思路,循环遍历
      //小于找左孩子
      //大于找右孩子
      //孩子为空直接放置
      //如果i==0 将root指针指向该节点
    for (int i=1;i<length;i++)
    {
        Insert(a[i]);
    }
    strTrue = "true";
    strFalse = "false";
    strNull = "null";
}


template<class T>
SearchTree<T>::MidWalk()
{
    TreeNode<T> *node = root;
    MidWalkInner(node);
    cout<<endl;
}

template<class T>
SearchTree<T>::MidWalkInner(TreeNode<T> *node)
{
    if (node!=NULL)
    {
        MidWalkInner(node->left);
        cout<<node->mValue<<" ";
        MidWalkInner(node->right);
    }
}

template<class T>
SearchTree<T>::FrontWalk()
{
    TreeNode<T> *node = root;
    FrontWalkInner(node);
}

template<class T>
SearchTree<T>::FrontWalkInner(TreeNode<T> *node)
{
    if (node!=NULL)
    {
        cout<<node->mValue<<endl;
        FrontWalkInner(node->left);
        FrontWalkInner(node->right);
    }
}

template<class T>
SearchTree<T>::BackWalk()
{
    TreeNode<T> *node = root;
    BackWalkInner(node);
}

template<class T>
SearchTree<T>::BackWalkInner(TreeNode<T> *node)
{
    if (node!=NULL)
    {
        BackWalkInner(node->left);
        BackWalkInner(node->right);
        cout<<node->mValue<<endl;
    }
}

template<class T>
TreeNode<T> * SearchTree<T>::Search(T value)
{
    TreeNode<T> *node = root;
    TreeNode<T> *matchNode = SearchInner(node,value);
    return matchNode;
}

template<class T>
TreeNode<T> * SearchTree<T>::SearchInner(TreeNode<T> *node,T value)
{
    if (node==NULL || node->mValue == value)
    {
        if (node==NULL) //对于找不到的给一个-1以示空
            return new TreeNode<T>(-1);
        else
            return node;
    }
    if (value < node->mValue)
        SearchInner(node->left,value);
    else
        SearchInner(node->right,value);
}

template<class T>
string SearchTree<T>::Insert(T value)
{
    TreeNode<T> *node = new TreeNode<T>(value);
    InsertInner(node,root);
    return strTrue;
}

template<class T>
TreeNode<T> *  SearchTree<T>::Minimum()
{
    TreeNode<T> *node = root;
    while(node->left!=NULL)
        node = node->left;
    return node;
}

template<class T>
TreeNode<T> *  SearchTree<T>::MinimumInner(TreeNode<T> *node)
{
    while(node->left!=NULL)
        node = node->left;
    return node;
}

template<class T>
TreeNode<T> *  SearchTree<T>::Maximum()
{
    TreeNode<T> *node = root;
    while(node->right!=NULL)
        node = node->right;
    return node;
}

template<class T>
TreeNode<T> *  SearchTree<T>::MaximumInner(TreeNode<T> *node)
{
    while(node->right!=NULL)
        node = node->right;
    return node;
}

template<class T>
TreeNode<T> *  SearchTree<T>::TreePredecessor(TreeNode<T> *node)
{
    if(node->left !=NULL)
    {
        TreeNode<T> * temp = MaximumInner(node->left);
        return temp;
    }
    TreeNode<T> * temp = node->p;
    while( temp!=NULL && node == temp->left)
    {
        node = temp;
        temp = temp->p;
    }
    if (temp == NULL)
        temp = new TreeNode<T>(-1); //表示没有前驱
    return temp;
}

template<class T>
TreeNode<T> *  SearchTree<T>::TreeSuccessor(TreeNode<T> *node)
{
    if(node->right !=NULL)
    {
        TreeNode<T> * temp = MinimumInner(node->right);
        return temp;
    }
    TreeNode<T> * temp = node->p;
    while( temp!=NULL && node == temp->right)
    {
        node = temp;
        temp = temp->p;
    }
    if (temp == NULL)
        temp = new TreeNode<T>(-1); //表示没有后继
    return temp;
}

template<class T>
SearchTree<T>::InsertInner(TreeNode<T> *insertNode,TreeNode<T> *parentNode)
{
    if (parentNode->left==NULL && parentNode->right==NULL)
    {
        if (insertNode->mValue < parentNode->mValue)
        {
            parentNode->left = insertNode;
            insertNode->p = parentNode;
        }
        else
        {
            parentNode->right = insertNode;
            insertNode->p = parentNode;
        }
    }
    else
    {
        if (insertNode->mValue < parentNode->mValue)
        {
            if (parentNode->left!=NULL)
                InsertInner(insertNode,parentNode->left);
            else
            {
                parentNode->left = insertNode;
                insertNode->p = parentNode;
            }
        }
        else
        {
            if (parentNode->right!=NULL)
            InsertInner(insertNode,parentNode->right);
            else
            {
                parentNode->right = insertNode;
                insertNode->p = parentNode;
            }
        }
    }
}

template<class T>
string SearchTree<T>::Delete(T value)
{
    TreeNode<T> *node = SearchInner(root,value);//找到要删除的节点
    if(node->left==NULL)
        Transplant(node,node->right);
    else if(node->right==NULL)
        Transplant(node,node->left);
    else
    {
    	//找到后继节点
        TreeNode<T> *temp = MinimumInner(node->right);
        if (temp->p != node)
        {
            Transplant(temp,temp->right);
            temp->right = node->right;
            temp->right->p = temp;
        }
        Transplant(node,temp);
        temp->left = node->left;
        temp->left->p = temp;
    }
    return strTrue;
}

template<class T>
SearchTree<T>::Transplant(TreeNode<T> *pNode,TreeNode<T> *subNode)
{
    if(pNode->p ==NULL) //pNode是根节点,则subNode继承到root
        root = subNode;
    else if (pNode == pNode->p->left)//下面两步,根据pNode是左还是右节点,则subNode继承到对应的节点
        pNode->p->left = subNode;
    else
        pNode->p->right = subNode;
    if (subNode !=NULL)//设置subNode的父节点
        subNode->p = pNode->p;
}


int main()
{
    int a[11] = {6,5,2,5,7,8,1,3,9,4,11};
    SearchTree<int> *tr = new SearchTree<int>(a,11);
    tr->MidWalk();
    TreeNode<int> *node = tr->Search(10);
    cout<<"node value is "<<node->mValue<<endl;
    node = tr->Minimum();
    cout<<"min value is "<<node->mValue<<endl;
    node = tr->Maximum();
    cout<<"max value is "<<node->mValue<<endl;
    node = tr->Search(8);
    node = tr->TreeSuccessor(node);
    cout<<"successor value is "<<node->mValue<<endl;
    node = tr->Search(2);
    node = tr->TreePredecessor(node);
    cout<<"predecessor value is "<<node->mValue<<endl;
    node = tr->Search(2);
    cout<<"2 node value is "<<node->mValue<<endl;
    tr->Delete(2);
    node = tr->Search(2);
    cout<<"delete 2 node value is "<<node->mValue<<endl;
    tr->MidWalk();
    tr->Insert(2);
    node = tr->Search(2);
    cout<<"insert 2 node value is "<<node->mValue<<endl;
    tr->MidWalk();
}



节点插入: 利用递归函数及二叉搜索树的性质(左节点≤父节点≤右节点),找到对应的位置插入即可;
二叉树的构造: 将传入的节点依次调用 节点插入 的方法
前中后序遍历: 利用递归函数,以中序遍历为例;1、优先输出父节点2、递归左节点3、递归右节点
节点搜索: 递归遍历每个节点,找到value相等的值 PS. 其实应该对比一下value值,大于等于value的搜索右节点,小于value的搜索左节点,就交给你们去完成了。
最大最小节点: 没什么好讲的,一直找右/左节点到底就是了
前驱后继:
前驱,在左子树的最大值中 或者 父节点中并且该节点必须在父节点的右子树中
后继,在右子树的最小值中 或者 父节点中并且该节点必须在父节点的左子树中
删除:
1、没有孩子,则直接删去就好
2、删除的节点x仅有一个孩子y(只存在左节点/只存在右节点),将y替代原来的x
3、删除的节点x存在两个孩子,
①就要找到x节点的后继节点y
②将y节点的右节点替代y节点(ps,没有y左节点相关处理的原因在补充知识点内),
y节点顶替x节点原有的位置
PS.记得要修改yy右节点左右指针的指向

补充知识点: 在一棵二叉搜索树中,有双孩子节点x的后继节点没有左孩子;节点的前驱没有右孩子。
证明: 反证法—>后继节点如果有左孩子,则在节点的左子树中存在更靠近x.key的节点;前驱节点同理

删除的书内详解:
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值