BST

BST(Binary Search Tree):二叉查找树,也叫二叉搜索树,二叉排序树,其目的是为了提高查找的效率,其查找在平均和最坏的情况下都是logn级别,接近二分查找

BST性质:
若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
它的左、右子树也分别为二叉排序树

BST原理:
通常采取二叉链表作为二叉排序树存储结构中序遍历二叉排序树可得到一个关键字的有序序列,一个无序序列可以通过构造一棵二叉排序树变成一个有序序列,构造树的过程即为对无序序列进行排序的过程。每次插入的新的结点都是二叉排序树上新的叶子结点,在进行插入操作时,不必移动其它结点,只需改动某个结点的指针,由空变为非空即可。搜索,插入,删除的复杂度等于树高,O(log(n)).

查找算法
在BST中查找x的过程:
若b是空树,则搜索失败,否则:
若x等于b的根结点的数据域之值,则查找成功;否则:
若x小于b的根结点的数据域之值,则搜索左子树;否则:
查找右子树。

插入算法
向BST中插入一个结点s的过程:
若b是空树,则将s所指结点作为根结点插入,否则:
若s->data等于b的根结点的数据域之值,则返回,否则:
若s->data小于b的根结点的数据域之值,则把s所指结点插入到左子树中,否则:
把s所指结点插入到右子树中。

删除算法:
在二叉排序树删去一个结点,分三种情况讨论:
若p结点为叶子结点,即左右子树为空。删去叶子结点不会破坏BST的结构,更改双亲的指向即可。
若p结点只有左子树或只有右子树,令左子树或右子树成为其双亲的左子树或右子树即可,不破坏BST的结构。
若p结点的左右子树均不空,在删去p之后,为保持其它元素之间的相对位置不变,可按中序遍历保持有序进行调整,令p的直接前驱(或直接后继)替代p,然后再从BST中删去它的直接前驱(或直接后继)。

在具体实现时,为BST整体维护一个head结点,结点的左子树为BST整体的最小结点,右子树为BST整体放入最大结点,双亲节点指向BST的root,key域为随机值,用cursiez来记录BST的结点个数。

//BST结构定义:
typedef int KeyType;
typedef struct BstNode
{
    BstNode *leftchild;
    BstNode *parent;
    BstNode *rightchild;
    KeyType key;
}BstNode;

typedef struct
{
    BstNode *head;
    int cursize;
}BSTree;

//基础操作:
BstNode * Buynode(BstNode *pa = NULL)
{
    BstNode *s = (BstNode *)malloc(sizeof(BstNode));
    if(NULL == s)
    exit(1);
    memset(s,0,sizeof(BstNode));
    s->parent = pa;
    return s;
}
void Freenode(BstNode *p)
{
    free(p);
}
void InitBSTree(BSTree &myt)
{
    myt.head = Buynode();
    myt.cursize = 0;
}

//非递归查找
BstNode * FindValue(BSTree &myt,KeyType kx)
{
    BstNode * p = myt.head->parent;  //root
    while(p != NULL && p->key != kx)
    {
        p = kx < (p->key) ? p->leftchild p->rightchild;
    }
    return p;
}
//递归查找
BstNode * SearchValue(BSTree &myt,KeyType kx)

{
    return Search(myt.head->parent,kx);
}
BstNode * Search(BstNode *p,KeyType kx)
{
    if(p == NULL || p->key == kx)
    {
        return p;
    }
    else if(kx < p->key)
    {
        return Search(p->leftchild,kx);
    }
    else 
    {
        return Search(p->rightchild,kx);
    }
}

//插入
bool InsertBST(BSTree &myt,KeyType kx)
{
    BstNode *pa = myt.head ;       //head;
    BstNode *p = myt.head->parent;     //root;
    while(p != NULL && (p->key) != kx)   //递归查找判断结点是否已经存在,并确认插入的位置
    {
        pa = p;
        p =  kx < (p->key) ? p->leftchild p->rightchild;
    }
    if(p != NULL)  return false;     //结点已存在
    p = Buynode(pa);                  //新结点
    p->key = kx;                          //赋值
    if(pa == myt.head)                //为空BST插入结点
    {
        myt.head->leftchild = p;
        myt.head->rightchild = p;
        myt.head->parent = p;
    }
    else                                     //为非空BST插入结点
    {
        if( (p->key) < (pa->key) )            //左子树插入
        {
            pa->leftchild = p;
            if(p->key < myt.head->leftchild->key)
            {
                myt.head->leftchild = p;
            }
        }
        else                                            //右子树插入
        {
            pa->rightchild = p;
            if( (p->key) > (myt.head->rightchild->key) )
            {
                myt.head->rightchild = p;
            }
        }
    }
    myt.cursize+=1;
    return true;
}

//删除结点
bool RemoveBST(BSTree &myt,KeyType kx)
{
    BstNode *pa = myt.head;    // head
    BstNode *p = myt.head->parent;    // root;
    while(p != NULL && p->key != kx)       //查找要删除的结点是否存在,并确认要删除的位置
    {
        pa = p;
        p = kx < p->key? p->leftchild:p->rightchild;
    }
    if(p == NULL) return false;          //结点不存在
    if(p->leftchild != NULL && p->rightchild != NULL)   //删除的结点为双分支结点,用它的后继结点替代,后继结点必为叶子结点
    {
        BstNode *nt = Next(myt,p->rightchild);
        p->key = nt->key;
        p = nt;
    }

    BstNode * child = p->leftchild != NULL? p->leftchild p->rightchild;   
    if(child != NULL) child->parent = pa;      
    if(pa == myt.head)                  //删除的结点为根节点
    {
        myt.head->parent = child;
    }
    else                                       //左子树
    {
        if(p == pa->leftchild)      
        {
            pa->leftchild = child;
        }
        else                                   //右子树
        {
            pa->rightchild = child;
        }
    }
    Freenode(p);
    myt.cursize-=1;
    return true;
}

//查找最小结点:
BstNode * First(BstNode *ptr)  
{
    while(ptr != NULL && ptr->leftchild != NULL)
    {
        ptr = ptr->leftchild;
    }
    return ptr;
}
//查找最大节点
BstNode *Last(BstNode *ptr) 
{
    while(ptr != NULL && ptr->rightchild != NULL)
    {
        ptr = ptr->rightchild;
    }
    return ptr;
}

//给定结点的下一个结点
BstNode * Next(BSTree &myt,BstNode *ptr)
{
    if(ptr == NULL || ptr == myt.head) return NULL;
    if(ptr->rightchild != NULL)
    {
        return First(ptr->rightchild);
    }
    else
    {
        BstNode *pa = ptr->parent;
        while(pa != myt.head && pa->leftchild != ptr)
        {
            ptr = pa;
            pa = pa->parent;
        }
        if(pa == myt.head)
        {
            pa = NULL;
        }
        return pa;
    }
}
//给定结点的前一个结点
BstNode * Prev(BSTree &myt,BstNode *ptr)
{
    if(ptr == NULL || ptr == myt.head) return NULL;
    if(ptr->leftchild != NULL)
    {
        return Last(ptr->leftchild);
    }
    else
    {
        BstNode *pa = ptr->parent;
        while(pa != myt.head && pa->rightchild != ptr)
        {
            ptr = pa;
            pa = pa->parent;
        }
        if(pa == myt.head)
        {
            pa = NULL;
        }
        return pa;
    }
}

//非递归中序遍历
void NiceInOrder(BSTree &myt)
{
    for(BstNode *p = First(myt.head->parent);p !=NULL; p = Next(myt,p))
    {
        cout<<p->key<<" ";
    }
    cout<<endl;
}
//非递归中序反向遍历
void ResNiceInOrder(BSTree &myt)
{
    for(BstNode *p = Last(myt.head->parent);p != NULL; p = Prev(myt,p))
    {
        cout<<p->key<<" ";
    }
    cout<<endl;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值