二叉排序树(二叉查找树)及C语言实现

曲目:二叉排序树(二叉查找树)及C语言实现
NJ:
时间:2019/06/08
发行:



后面的切开都是计划达到目标恒稳态查找表的。,从本条开端,绍介了另任何人顾及表格。--

静态查找表

在静态顾及表格中实行顾及调整时,以防搜索成,可以将其自成一格;以防搜索损失,更确切地说,表中缺席症结词。,可以将此症结词拔出表中。

静态查找表有多种表现方式,本条绍介了一种用法和解表现静态查找表的达到预期的目的--二叉排序树(也称为“二叉查找树”)。

是什么二叉排序树?

二叉排序树或是空

二叉树

,它或具下面是特点:

  • 二叉排序树中,以防它的根结节有左子树,这么左子树中拿结节的值都以内roo的值;
  • 二叉排序树中,以防其根结节具有右子树,这么,右子树上拿结节的值都是大部分的值;
  • 二叉排序树的摆布子树也需求都是二叉排序树;

譬如,

1 执意任何人二叉排序树:

图 1 二叉排序树

应用二叉排序树查找症结词

二叉排序树中查找某症结词时,搜索快速地流动相似地次优二叉树。,在二叉排序树不为空树的先决条件下,率先,将搜索值与树的根结节举行相对地。,会有 3 种形形色色的的算是:

  • 以防相当,找到成;
  • 以防相对地算是是根结节,则症结词值较大。,这表现症结词能够存取决于其左子树中。;
  • 以防相对地算是为根花结的症结词值较小,这表现症结词能够存取决于其右子树中。;

达到预期的目的效能是:(应用重新提起方式)

BiTree SearchBST(BiTree T,KeyType 症结)
    以防重新提起快速地流动 T 为空,找到算是,使恢复原状空值;或许找到成,使恢复原状读出症结词的伸出
    if (!T || key==T->data) {
        return T;
    }else 以防(密电码)唱片)
        他的左孩子的重新提起遍历
        return SearchBST(T->lchild, 症结)
    }else{
        重新提起遍历其右子级
        return SearchBST(T->rchild, 症结)
    }
}

二叉排序树中拔出症结词

二叉排序树自身是静态查找表的一种表现方式,间或在搜索快速地流动中会拔出或自成一格表达到目标元素,当鉴于搜索损失而需求拔出唱片元素时,该唱片元素的拔出职位必然位置二叉排序树的生叶花结,而且必须做的事是拜访结局任何人结节wh的左子结节或右子结节。。

譬如,在图 1 的二叉排序树中做查找症结词 1 的调整,找到症结词时 3 当叶结节位置,判别表中缺席症结词,此刻的症结词 1 拔出职位是症结词 3 的左孩子。

因而,二叉排序树表现静态查找表做拔出调整,您只需对下面的信号做某个更改就可以做到这点。,详细的达到预期的目的信号是:

BOOL SearchBST(BiTree T,KeyType key,BiTree f,BiTree *p){
    //以防 T 伸出为空,解说查找损失,令 p 伸出读出查找快速地流动达到目标结局任何人叶结节,并使恢复原状未检出的的要旨
    if (!T){
        *p=f;
        return false;
    }
    以防相当,令 p 伸出读出症结词,并使恢复原状找到成要旨
    else 以防(密电码)==T->唱片)
        *p=T;
        return true;
    }
    //以防 key 值比 T 根结节的值很小,查找其左子树;相反,找到它的优美的子树
    else 以防(密电码)唱片)
        return SearchBST(T->lchild,key,T,p);
    }else{
        return SearchBST(T->rchild,key,T,p);
    }
}
拔出职务
BOOL InsertBST(BiTree T,ElemType e){
    BiTree p=NULL;
    以防搜索损失,需求实行拔出调整
    if (!SearchBST(T, e,NULL,&p)) {
        设定初值拔出结节
        BiTree s=(BiTree)malloc(sizeof(BiTree));
        s->data=e;
        s->lchild=s->rchild=NULL;
        //以防 p 为空,阐明该二叉排序树为空树,此刻,拔出的结节是整棵树的根结节。
        if (!p) {
            T=s;
        }
        //以防 p 不为 NULL,则 p 读出结局任何人未检出的的叶结节,独一无二的经过相对地 p 和 e 的值决定 s 终于是 p 左孩子或者右孩子
        else 以防(e)唱片)
            p->lchild=s;
        }else{
            p->rchild=s;
        }
        return true;
    }
    //以防找到成,不需求拔出,拔出损失
    return false;
}

经过应用二叉排序树对静态查找表做查找和拔出的调整,同时在中序遍历二叉排序树时,可以获得拿症结词的统治序列。。

譬如,补助金原二叉排序树为空树,在静态顾及表格中 {3,5,7,2,1} 实行查找和拔出调整时,可以结构出任何人进口商品表中拿症结词的二叉排序树,工艺过程如图所示。 2 所示:

图 2 二叉排序树拔出快速地流动

经过不休的查找和拔出调整,终极结构的二叉排序树如图 2(5) 所示。当应用中序遍历算法遍历二叉排序树时,算是序列是:

1 2 3 5 7

,为统治序列。


任何人无序的序列可以经过结构一棵二叉排序树,因而它增加了任何人统治的序列。。

二叉排序树中自成一格症结词

在搜索快速地流动中,以防在应用二叉排序树表现的静态查找表中自成一格某个唱片元素时,您需求同时成自成一格结节,不断地使这棵树为二叉排序树。

补助金要自成一格结节 p,则朝一个方向的二叉排序树来说,需求由于结节 p 在形形色色的的职位实行形形色色的的调整,下面是 3 种能够:

1、花结 p 朝一个方向的叶结节,此刻,您只需求自成一格结节。,修正父结节的伸出。;
2、花结 p 独一无二的左子树或右子树,此刻,只需求交换左子树或右子树 p 父结节左子树;
3、花结 p 有左子树和右子树。,处置这种产生影响有两种方式。:

1)定货单结节 p 树左子树是其父结节左子树;花结 p 右子树是它自己连续的前体结节的右子树。,如图 3 所示;

图 3 二叉排序树中自成一格花结(1)


2)应用结节 p 连续的原本(或连续的争吵)交换结节 p,同时在二叉排序树中对其连续的原本(或连续的争吵)做自成一格调整。如图 4 用连续的先兆交换结节 p:

图 4 二叉排序树中自成一格花结(2)

图 4 中,在左图的位于正中的阶遍历中,算是结节 p 连续的前体结节是结节 s,因而连续的应用结节。 s 洒上结节 p,因结节 s 并且右边的孩子。,理性第 2 条统治,将其连续的交换为父结节的右子结节。

详细进行信号:(可调整)

#include
#include
#define TRUE 1
#define FALSE 0
#define ElemType int
#define  KeyType int
/* 二叉排序树的结节和解限界 */
typedef struct BiTNode
{
    int data;
    struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;

//二叉排序树查找算法
int SearchBST(BiTree T,KeyType key,BiTree f,BiTree *p){
    //以防 T 伸出为空,解说查找损失,令 p 伸出读出查找快速地流动达到目标结局任何人叶结节,并使恢复原状未检出的的要旨
    if (!T){
        *p=f;
        return FALSE;
    }
    以防相当,令 p 伸出读出症结词,并使恢复原状找到成要旨
    else 以防(密电码)==T->唱片)
        *p=T;
        return TRUE;
    }
    //以防 key 值比 T 根结节的值很小,查找其左子树;相反,找到它的优美的子树
    else 以防(密电码)唱片)
        return SearchBST(T->lchild,key,T,p);
    }else{
        return SearchBST(T->rchild,key,T,p);
    }
}
int InsertBST(BiTree *T,ElemType e){
    BiTree p=NULL;
    以防搜索损失,需求实行拔出调整
    if (!SearchBST((*T), e,NULL,&p)) {
        设定初值拔出结节
        BiTree s=(BiTree)malloc(sizeof(BiTree));
        s->data=e;
        s->lchild=s->rchild=NULL;
        //以防 p 为空,阐明该二叉排序树为空树,此刻,拔出的结节是整棵树的根结节。
        if (!p) {
            *T=s;
        }
        //以防 p 不为 NULL,则 p 读出结局任何人未检出的的叶结节,独一无二的经过相对地 p 和 e 的值决定 s 终于是 p 左孩子或者右孩子
        else 以防(e) < p->唱片)
            p->lchild=s;
        }else{
            p->rchild=s;
        }
        return TRUE;
    }
    //以防找到成,不需求拔出,拔出损失
    return FALSE;
}
//自成一格职务
int 自成一格(bitree *p)
{
    BiTree q, s;
    //产生影响 1,花结 p 自身朝一个方向的叶结节,连续的自成一格那就够了。
    if(!p)->l孥 && !(*p)->rchild){
        *p = NULL;
    }
    else if(!p)->l孥){ 左子树为空,只应用结节 p 右子树的根结节交换该结节 p 那就够了;
        q = *p;
        *p = (*p)->rchild;
        释放(Q)
    }
    else if(!p)->rchild//右子树为空,只应用结节 p 左子树的根结节交换该结节 p 那就够了;
        q = *p;
        *p = p)->l孥;//喂发生断层伸出 *p 读出左子树,相反,记忆力在左子树达到目标结节地址被分养家费t p
        释放(Q)
    }
    以此类推//左、右子树不为空,经过 2 种方式
        q = *p;
        s = p)->l孥;
        //遍历,查找结节 p 连续的前体
        while(s->rchild)
        {
            q = s;
            s = s->rchild;
        }
        连续的更改结节 p 的值
        P)->唱片 = s->data;
        //判别花结 p 左子树 s 有优美的的子树吗?,在两个窥测中议论
        if( q != *p ){
            q->rchild = s->lchild;//以防是,自成一格连续的前体结节时,将前体的左子结节更反而 q 读出结节的子结节
        }else{
            q->lchild = s->lchild;//不同的,连续的动摇左子树。
        }
        收费
    }
    return TRUE;
}
int DeleteBST(BiTree *T, int 症结)
{
    if( !t)//缺席症结词同样的人键的唱片元素
        return FALSE;
    }
    else
    {
        if( key == t)->唱片 ){
            自成一格(T)
            return TRUE;
        }
        else if( key < (*T)->唱片)
            应用重新提起方式
            return 自成一格bst(&(*t)->lchild, 症结)
        }
        else{
            return DeleteBST(&(*T)->rchild, 症结)
        }
    }
}
void 挨次(Bitree t)//位于正中的序列出口
{
    以防(t) == 空)
        return ;
    }
    order(t->lchild);
    printf(%d) ", t->data);
    order(t->rchild);
}
int main()
{
    int i;
    int A〔5〕 = {3,4,2,5,9};
    BiTree T = NULL;
    for( i = 0; i < 5; i++ ){
        InsertBST(&T, a[i]);
    }
    printf("中序遍历二叉排序树:
");
    order(T);
    printf("
");
    printf("自成一格3后,中序遍历二叉排序树:
");
    DeleteBST(&T,3);
    order(T);
}

运转算是:

中序遍历二叉排序树:
2 3 4 5 9
自成一格3后,中序遍历二叉排序树:
2 4 5 9

总结

应用二叉排序树在查找表中做查找调整的

工夫复杂的事物

它与二叉树自身的和解公司或企业。。倘若顾及表格达到目标唱片元素能与之比拟的东西,但挨次形形色色的,结构出的二叉排序树大不能与之比拟的东西。

譬如:查找表

{45,24,53,12,37,93}

和表

{12,24,37,45,53,93}

各自结构的二叉排序树图下图所示:

图 5 形形色色的组织的二叉排序树

应用二叉排序树达到预期的目的静态查找调整的快速地流动,实际的执意从二叉排序树的根花结到查找元素花结的快速地流动,到这地步,工夫不同类与元素到哪里树的吃水公司或企业。。

为了化妆二叉排序树组织时发生如图 5 产生影响右舷所示算法能力的相等,需求对二叉排序树做“抵消化”处置,把它增加树抵消二叉树

抵消二叉树是达到预期的目的静态查找表的备选的方式,下一节有力绍介。

点击查看原文:二叉排序树(二叉查找树)及C语言实现


以下文章推荐了类似的好听歌曲

产品介绍
下一篇:没有了