二叉查找树

1 二叉查找树类的定义

//建立集合
template <class KEY,class OTHER>
struct SET
{
    KEY key;
    OTHER other;
};
//建立动态查找表的类
template<class KEY,class OTHER>
class dynamicSearchTable
{
public:
    virtual SET<OTHER,KEY>*find(const KEY&x)const=0;
    virtual void insert(const SET<OTHER,KEY>&x)=0;
    virtual void remove(const KEY&x)=0;
    virtual ~dynamicSearchTable(){};
};
template<class KEY,class OTHER>
class BinarySearchTree:public dynamicSearchTable<KEY,OTHER>
{
private:
    struct binaryNode
    {
        SET<KEY,OTHER> data;
        binaryNode*left;
        binaryNode*right;

        binaryNode(const SET<KEY,OTHER>&data1,binaryNode*left1=NULL,binaryNode*right1=NULL):data(data1),left(left1),right(right1){}
        ~binaryNode(){}
    };
    binaryNode*root;
public:
    BinarySearchTree(){root=NULL;};
    ~BinarySearchTree(){makeEmpty(root);};

    SET<KEY,OTHER>*find(const KEY&x)const{find(x,root);};//const在结尾表示这个函数不改变这个类
    void insert(const SET<KEY,OTHER>&x){insert(x,root);};
    void remove(const KEY&x){remove(x,root);};

private:
    SET<KEY,OTHER>*find(const KEY&x,binaryNode*t)const;
    void insert(const SET<KEY,OTHER>&x,binaryNode*&t);
    void remove(const KEY&x,binaryNode*&t);
    void makeEmpty(const binaryNode*&t);

};

注意区分引用&与取地址*

2 二叉查找树功能实现

2.1 find函数的实现

2.1.1 递归方法
template<class KEY,class OTHER>
SET<KEY,OTHER>* BinarySearchTree<KEY,OTHER>:://注意所属于类后如果有模板,也要带上
    find(const KEY&x,binaryNode*t)const
{
//无法返回结构体,因此只能返回结构体指针,这样才能通过序号索引到一些对应内容
  if(t==NULL) return NULL;
  if(t->data==x)  return &(t->data);//返回结构体元素的地址,区分t指向节点地址,通过节点地址找到节点,访问节点得到结构体地址
    //上一行写return t是不对的,因为t是binaryNode地址
  //要返回的是SET<KEY,OTHER>*,但t指向的是一个SET结构体
  //因此要强制类型转换,如return (SET<KEY,OTHER>*)t
  else
  {
      if(t->data<x)return find(x,t->left);
      else return find(x,t->right);
  }
}
2.1.2 非递归方法
template<class KEY,class OTHER>
SET<KEY,OTHER>* BinarySearchTree<KEY,OTHER>::
    find(const KEY&x)const
{
//无法返回结构体,因此只能返回结构体指针,这样才能通过序号索引到一些对应内容
  if(root==NULL) return NULL;
  binaryNode*p=root;
  while(p)//二叉树到叶子后面停止
  {
     if(p->data==x) return &(t->data);//取地址运算符&
     if(p->data<x) p=p->left;
     else p=p->right;

  }
  return NULL;
}

注意非递归结尾没有找到时中止标志,到叶子会自动退出,要自己输入NULL,递归在判断结点是否为空时,就已经可以输出NULL表示结束没有找到了

2.2 insert函数

大体理论是任何被插入的结点最后一定可以成为叶子结点
从上到下比较

template<class KEY,class OTHER>
void BinarySearchTree<KEY,OTHER>::insert(const SET<KEY,OTHER>&x,binaryNode*&t)
{
    if(t==NULL)
    {t=new binaryNode(x);
    return;}//为结构体新建一个结点
    if(t->data==x.key) return;//已经存在则结束插入,无需调用find
    if(x.key>t->data) insert(t->right,x);
    else insert(t->left,x);
    //注意此处x为结构体,要访问key比大小
}

由insert构建可知,左子树的最大值小于右子树的根结点值
右子树的最小值大于左子树的根结点值

2.3 remove函数

void BinarySearchTree<KEY,OTHER>::remove(const KEY&x,binaryNode*&t)
{
   //先进行查找
    if(t==NULL) return;
    if(t->data.key<x) remove(x,t->left);
    else
    {
        if(t->data.key>x) remove(x,t->right);
        else
        {
            if(t->left&&t->right)
            {
                binaryNode*tmp=t->left;
                while(tmp->right) tmp=tmp->right;//找到左子树中的最大值
                t->data=tmp->data;//用左子树最大值替换被删结点
                //但这样就很难删掉t,if(tmp->left)tmp=tmp->left;//或者remove(x,tmp->left)
                //将替换结点左子树放到替换节点位置
                remove(t->data.key,tmp->left);//删除左子树最大值,用下面else删掉,妙!
            }
            else
            {
                binaryNode*OldNode=t;//*****
                if(t->left) t=t->left;
                if(t->right) t=t->right;
                delete OldNode;
            }

        }
    }
}

比较巧妙或者易错的有删除操作

*时间复杂度

如果树接近完全二叉树,时间复杂度O(logN)
最差情况是退化为一个单链表,时间复杂度O(n)
由此引入下一章节内容,AVL平衡二叉树,改变二叉树结构,避免退化成单链表情况

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值