二叉搜索树的插入和删除

题目:2叉搜索树的插入和删除 
要求
(1)任意选顶一个2叉搜索树用先序遍历 中序遍历 和后序遍历显示该2叉搜索树

(2)动态显示出在2叉搜索树中插入一个元素时树的变化过程 要求演示出所有可能的情况

(3)动态显示出 在2叉搜索树中删除一个元素时的变化过程要求演示出所有的可能的情况 

#include <iostream.h>
#define max 10
struct BinTreeNode                                                                             //二叉查找树的节点结构体
{
    int m_data;
    struct BinTreeNode *lchild, *rchild;
    BinTreeNode(int item, BinTreeNode *left = NULL, BinTreeNode *right = NULL)
        : m_data(item), lchild(left), rchild(right)  //构造函数默认的lchild,rchild为NULL
    {
    }
};

class  BinaryTree                                                                       //二叉搜索树类
{

private:
    BinTreeNode *root;   //根节点指针

public:
    BinaryTree()
    {
        root = NULL;
    }
    
 //迭带插入的方法建二叉搜索树
    void Insert(const int node)                                                
    {                                     
        BinTreeNode *currentpointer;        //当前节点指针  
        BinTreeNode *parentpointer;         //父亲节点指针    
        BinTreeNode *newpointer; 
        //ptr必须为根节点指针的引用
        BinTreeNode *ptr = root;
        newpointer = new BinTreeNode(node); //新动态分配一个节点

        if(root == NULL)    //如果此时树为空,返回新开辟的节点
        {
            root = newpointer;
        }
        else
        {
            currentpointer = ptr;        //保存root指针
   //一直移动到是使parentpointer指向叶子节点而currentpointer为NULL
            while(currentpointer != NULL)    //当当前节点不为空的情况下
            {
                parentpointer = currentpointer; //用指向父亲节点的指针保存当前指针

                if(currentpointer->m_data > node)
                {
                    currentpointer = currentpointer->lchild;
                }
                else
                {
                    currentpointer = currentpointer->rchild;
                }
            }
            //以下是将节点插入
            if(parentpointer->m_data > node)
            {
                parentpointer->lchild = newpointer;
            }
            else
            {
                parentpointer->rchild = newpointer;
            }
        }
    }

 //创建方法,依次插入
    BinTreeNode *Creat(int data[],int len) 
    {
        for(int i=0; i<len; i++)
        {
            Insert(data[i]);
        }
        return root;
    }
    
    void PreOrder()
    {
        cout<<"前序遍历的结果为:";
        PrePrint(root);
    }

    void InOrder()
    {
        cout<<"中序遍历的结果为:";
        InPrint(root);
    }

    void PostOrder()
    {
        cout<<"后序遍历的结果为:";
        PostPrint(root);
    }

    void Count()
    {
        cout<<endl;
        cout<<"叶子节点数为:"<<CountLeafs(root)<<endl;
    }

    void PrePrint(BinTreeNode *p) //前序遍历
    {
        if(p != NULL)
        {
            cout << p->m_data << ',';
            PrePrint(p->lchild);
            PrePrint(p->rchild);
        }
    }

    void InPrint(BinTreeNode *p)  //中序遍历
    {
        if(p != NULL)
        {
            InPrint(p->lchild);
            cout<< p->m_data<<',';
            InPrint(p->rchild);
        }
    }
    
    
    void PostPrint(BinTreeNode *p)  //后序遍历
    {
        if(p != NULL)
        {
            PostPrint(p->lchild);
            PostPrint(p->rchild);
            cout<< p->m_data<< ',';
        }
    }

    BinTreeNode * Find(const int &c)  //用迭带的方法寻找特定的节点
    {
        BinTreeNode *pCurrent = root;
        if(pCurrent  != NULL)
        {
            while(pCurrent  != NULL)
            {
                if(pCurrent->m_data == c)
                {
                    return pCurrent;
                }
                else 
                {
                    if(c > pCurrent->m_data)
                        pCurrent  = pCurrent->rchild;
                    else
                        pCurrent  = pCurrent ->lchild;
                }
            }
        }
        return NULL;
    }
    
    bool DeleteBT(const int &key)   //删除节点的函数定义
    {
        BinTreeNode *q, *s;
        BinTreeNode *current = root; //找到要删除的节点
        BinTreeNode *prt = NULL;    //current的父亲节点

        while ((NULL != current) && (current->m_data != key))
                                   //通过查找找到值为key的节点和它的父亲节点
        {
            prt = current;
              
             if (current->m_data > key)
                     current = current->lchild;
             else
                     current = current->rchild;
        }

        if(current == NULL) //current为NULL说明节点不存在
        {
            cout<<"没有此节点!"<<endl;
            return false;
        }
        if(current->lchild == NULL && current->rchild == NULL)
                       //当找到的节点即没有左孩子也没有右孩子
        {
            if(current == root)
            {
                root = NULL;
            }
            else 
            {
                if(current == prt->lchild)
                {
                    prt->lchild = NULL;
                }
                else
                {
                    prt->rchild = NULL;
                }
            }
        }
        if(current->lchild == NULL && current->rchild != NULL)
                        //当找到的节点有右孩子而没有左孩子
        {
            if(current == root)
            {
                current = current->rchild;
            }
            else 
            {
                if(current == prt->lchild)  //如果当前节点是prt指向节点的左孩子
                {
                    prt->lchild = current->rchild;
                }
                else
                {
                    prt->rchild = current->rchild;
                }
            }
        }
        if(current->rchild == NULL && current->lchild != NULL) 
                                        //如果当前节点有左孩子而没有右孩子
        {
            if(current == root)
            {
                current = current->lchild;
            }
            else
            {
                if(current == prt->lchild)
                {
                    prt->lchild = current->lchild;
                }
                else
                {
                    prt->rchild = current->lchild;
                }
            }
        }

        if(current ->lchild != NULL && current->rchild != NULL)//当前节点左右孩子都有
        {
            q = current;    //用q保存current节点指针
            s = current;    //s是current的前驱指针

            current = current->lchild;
            //先向左走
            while(current->rchild) //然后向右走到尽头,其实就是寻找左子树当中最大的节点
            {                      //补充:寻找右子树当中最小的节点也是可以的
                s = current;       //s指向current的前驱
                current = current->rchild;
            }

            q->m_data = current->m_data;  //用找到的节点替换当前节点
        
            if(q != s)                    //将current节点从树中拆下来
                s->rchild = current->lchild;
            else
                q->lchild = current->lchild;
        }
        delete current;        //释放current指向的空间
        current = NULL;
        return true;
    }

    void destroy(BinTreeNode *current) //销毁二叉树
    {
        if(current != NULL)
        {
            destroy(current->lchild);
            destroy(current->rchild);
            delete current;
            current = NULL;
        }
    }

    int CountLeafs(BinTreeNode *current)
    {
        if(current == NULL)
        {
            return 0;
        }
        else 
        {
            if( current->lchild == NULL  &&  current->rchild == NULL )
            {
                return 1;
            }
            else
            {
                int num1 = CountLeafs(current->lchild);
                int num2 = CountLeafs(current->rchild);
                return (num1+num2);
            }
        }
    }

    virtual  ~BinaryTree() 
    {
        destroy(root);
    }
};
void main()
{
    BinaryTree myTree;
    int a[]={6, 3, 4, 7, 8, 2, 5, 9, 0, 1};
 //输出
 cout<<"(1)输出部分:"<<endl;
    myTree.Creat(a, max);  //创建二叉搜索树
    myTree.PreOrder();     //先序遍历
 cout<<endl;
    myTree.InOrder();      //中序遍历
 cout<<endl;
    myTree.PostOrder();    //后序遍历
 cout<<endl<<endl;
 //插入
 cout<<"(2)插入部分:"<<endl;
 int x;
 cout<<"输入你想要插入的节点:";
 cin>>x;
 myTree.Insert(x);
 myTree.InOrder();      //中序遍历
    cout<<endl<<endl;

 //删除
 cout<<"(3)删除部分:"<<endl;
    cout<<"输入一个你想删除的节点: ";
    cin>>x;
    if(myTree.DeleteBT(x))  //进行删除
        cout<<"删除成功!"<<endl;
    else
        cout<<"删除失败!"<<endl;
    myTree.InOrder();      //中序遍历
 cout<<endl<<endl;

 //查询
 cout<<"(4)查询部分:"<<endl;
 cout<<"输入你想要找的节点";
    cin>>x;
    if(myTree.Find(x))     //进行查找
        cout<<"查找成功!"<<endl;
    else
        cout<<"查找失败!"<<endl;
}

二叉搜索树: 二叉搜索树是一种特殊的二叉树,它的左子树中所有节点的值都小于它的根节点的值,而右子树中所有节点的值都大于它的根节点的值。二叉搜索树支持快速的插入、查找和删除操作,时间复杂度为O(logn)。 插入删除: 插入操作是将一个新节点插入二叉搜索树中,找到对应的位置并插入即可。删除操作比插入操作复杂一些,需要考虑到删除节点后二叉搜索树的结构是否仍然满足二叉搜索树的性质。如果需要删除的节点是叶子节点,直接删除即可。如果需要删除的节点只有一个子节点,可以将其子节点上移,删除该节点。如果需要删除的节点有两个子节点,可以找到该节点右子树中最小的节点,将其值复制到需要删除的节点中,然后删除该最小节点。 树遍历: 树的遍历是指按照某种顺序依次访问树中的所有节点。常用的树遍历方式有前序遍历、中序遍历和后序遍历。前序遍历是先访问根节点,然后访问左子树和右子树;中序遍历是先访问左子树,然后访问根节点和右子树;后序遍历是先访问左子树和右子树,然后访问根节点。 AVL树: AVL树是一种自平衡二叉搜索树,它保证了树的任意节点的左右子树高度差不超过1。当插入删除节点时,AVL树会通过旋转操作来保持树的平衡。AVL树的查找、插入删除操作的时间复杂度均为O(logn)。 红黑树: 红黑树也是一种自平衡二叉搜索树,它的插入删除操作比AVL树更快,但查找操作稍慢一些。红黑树通过染色和旋转操作来保持树的平衡,它要求树中任意一条从根到叶子的路径上,红色节点和黑色节点的个数相同。红黑树的时间复杂度也为O(logn)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值