几类树的区别及二叉查找树的各项操作

首先小鱼介绍一下几类树的区别及性质:
:既是一种递归结构,也是一种层次结构。

二叉树:n个节点的有限集合,或为空树,或为由一个根节点及两棵(左右子树)互不相交的二叉树组成。

满二叉树:绝对的三角形,最后一层全为叶子结点
节点数与深度的关系:n=(2^k)-1
第i层的节点数:2^(i-1)
同时可以通过编号的序号来确定该节点的位置
eg:编号13的父节点为13/2=6;
且13编号的节点为编号6的右节点(奇数为右节点,偶数为左节点);
编号13的左节点为13*2;
编号13的右节点为13*2+1
正因为满二叉树的这一特点,所以一般采用顺序结构而不是链式结构存储满二叉树。

完全二叉树:特殊的满二叉树,因为其最后一层不要求完整
eg:堆为典型的完全二叉树
具有n个节点的完全二叉树深度为:log n +1(因为n=(2^k)-1)

二叉查找树(BST)(又称二叉排序树,二叉搜索树):构造二叉查找树的目的不是为了排序,而是为了提高查找和插入及删除的速度。

二叉平衡树:为一种二叉排序树,左子树和右子树都为平衡二叉树,且左子树和右子树的高度差的绝对值不会超过1。

BST的各项操作:节点插入、节点删除、节点值的查找:查找max,min及特定节点的前驱和后继

#include<stdio.h>
#include<stdlib.h>
using namespace std;

template<class T>
struct TreeNode
{
    T element;
    TreeNode<T> *parent, *lnode, *rnode;
    TreeNode() { parent = lnode = rnode = NULL };
    TreeNode(const T &key)
    {
        element = key;
        parent = lnode = rnode = NULL;
    }
};

template<class T>
class Bstree
{
public:
    Bstree():root(NULL){}
    //获取根节点
    TreeNode<T> *Getroot() { return root; }
    //中序遍历
    void Inorder(TreeNode<T> *node);
    //递归查找
    TreeNode<T> *TreeSearch(TreeNode<T> *node, T key);
    //迭代查找
    TreeNode<T> *IterativeTreeSearch(TreeNode<T> *node, T key);
    //插入元素
    void TreeInsert(T key);
    //最大值
    TreeNode<T> *TreeMax(TreeNode<T> *node);
    //最小值
    TreeNode<T> *TreeMin(TreeNode<T> *node);
    //查找前驱节点
    TreeNode<T> *TreePredecessor(T key);
    //查找后继节点
    TreeNode<T> *TreeSuccessor(T key);
    //用节点M代替节点N
    void TransPlant(TreeNode<T>*nodeM, TreeNode<T>*nodeN);
    //删除节点是key的元素
    void Delete(T key);

private:
    TreeNode<T>* root;
};

//中序遍历
template<class T>
void Bstree<T>::Inorder(TreeNode<T> *node)
{
    if (node==NULL)
    {
        return;
    }
    else
    {
        Inorder(node->lnode);
        cout << node->element << " ";
        Inorder(node->rnode);
    }
}

//递归查找
template<class T>
TreeNode<T>* Bstree<T>::TreeSearch(TreeNode<T> *node, T key)
{
    if (node==NULL||key==node->element)
    {
        if (node==NULL)
        {
            cout << "not exist" << endl;
        }
        else
        {
            cout << "exist" << endl;
        }
        return node;
    }
    if (key>node->element)
    {
        return TreeSearch(node->rnode, key);
    }
    else
    {
        return TreeSearch(node->lnode, key);
    }
}

//迭代查找
template<class T>
TreeNode<T>* Bstree<T>::IterativeTreeSearch(TreeNode<T> *node, T key)
{
    while (node!=NULL&&key!=node->element)
    {
        if (key<node->element)
        {
            node = node->lnode;
        }
        else
        {
            node = node->rnode;
        }
    }
    if (node==NULL)
    {
        cout << "not exist" << endl;
    }
    else
    {
        cout << "exist" << endl;
    }
    return node;
}

//插入元素
template<class T>
void Bstree<T>::TreeInsert(T key)
{
    TreeNode<T>* y = NULL;
    TreeNode<T>* x = root;
    TreeNode<T>* z = new TreeNode<T>(key);//将要插入的元素放入创建的新节点中
    while (x!=NULL)//找到要插入位置的双亲节点
    {
        y = x;
        if (z->element<x->element)
        {
            x = x->lnode;
        }
        else
        {
            x = x->rnode;
        }
    }
    z->parent = y;
    if (y==NULL)//判断要插入的是左还是右节点
    {
        root = z;
    }
    else if(z->element>y->element)
    {
        y->rnode = z;
    }
    else
    {
        y->lnode = z;
    }
}

//最大值(即一直遍历到节点的右子树)
template<class T>
TreeNode<T>* Bstree<T>::TreeMax(TreeNode<T> *node)
{
    while (node->rnode!=NULL)
    {
        node = node->rnode;
    }
    cout << "max is: " << node->element << endl;
    return node;
}

//最小值(即一直遍历到节点的左子树)
template<class T>
TreeNode<T>* Bstree<T>::TreeMin(TreeNode<T> *node)
{
    while (node!=NULL)
    {
        node = node->lnode;
    }
    cout << "min is:" << node->element << endl;
    return node;
}

//查找前驱节点
template<class T>
TreeNode<T>* Bstree<T>::TreePredecessor(T key)
{
    TreeNode<T>* x = TreeSearch(root, key);//查找关键字key对应的节点
    if (x->lnode!=NULL)
    {
        return TreeMax(x->lnode)//若x的左子树不为空,则返回左子树的最右边数
    }
    TreeNode<T>* y = x->parent;
    while (y!=NULL&&x==y->lnode)
    {
        x = y;
        y = y->lnode;//用while循环,一直到最左边
    }
    return y;
}

//查找前驱节点
template<class T>
TreeNode<T>* Bstree<T>::TreeSuccessor(T key)
{
    TreeNode<T>* x = TreeSearch(root, key);
    if (x->rnode!=NULL)
    {
        return TreeMin(x->rnode);
    }
    //若不存在右节点
    //1、if(x==x->parent->lnode),则x的后继为x的双亲节点
    //2、if(x==x->parent->rnode),则x的双亲都小于x,直到x的某一祖先yn为左节点时,yn的双亲为x的后继
    TreeNode<T>* y=x->parent;
    while (y!=NULL&&x==y->rnode)
    {
        x = y;
        y = y->parent;
    }
    return y;
}
//用结点 m 替换结点 n,不包括v的左右子树的更新
template<class T>
void Bstree<T>::TransPlant(TreeNode<T>* nodeM, TreeNode<T>* nodeN)
{
    if (nodeN->parent == NULL)
        root = nodeM;
    else if (nodeN == nodeN->parent->lnode)   // nodeN 是左结点,更新nodeN->parent 的左结点
        nodeN->parent->lnode = nodeM;
    else
        nodeN->parent->rnode = nodeM;
    if (nodeM != NULL)
        nodeM->parent = nodeN->parent;
}

//删除节点是key的元素
template<class T>
void Bstree<T>::Delete(T key)
{
    TreeNode<T>* z = IterativeTreeSearch(root, key);//z为要删除的节点
    if(z->lnode==NULL)
    {
        TransPlant(z->rnode, z);
    }
    else if (z->rnode==NULL)
    {
        TransPlant(z->lnode, z);
    }
    else
    {
        //找要删除结点的后继元素
        TreeNode<T>* y = TreeMin(z->rnode);//类的成员函数在调用成员函数(模板)时,直接写函数名,不需要<T>
        if (y->psrent != z)
        {
            TransPlant(y->rnode, y);         //用 y 的右结点替代 y
            y->rnode = z->rnode;             //y的右结点 = z的右结点
            y->rnode->parent = y;
        }
        TransPlant(y, z);              //用 y替代z
        y->lnode = z->lnode;
        y->lnode->parent = y;
    }
}

int main()
{
    return 0;
}

该代码参考:二叉排序树的各项操作

有问题请留言,小鱼会尽快回答的,一起加油,喜欢请点个赞哦

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值