15二叉检索树

检索树

 

检索树的定义:

二叉检索树(或二叉排序树,二叉有序树)的简称,任一结点a,其左子树中结点的值均小于或等于a,右子树上结点值均大于a(左小右大)。

性质:中序序列是递增的有序序列。

 

1.检索树的构建方法:

创建一颗空树,通过遍历,进行有序插入,按照左小右大的原则。

 

检索树的构建算法:

Bptr  creat( )

   {   Bptr  root;   element_type x;

      root=NULL;  //开始时树为空

      scanf("%d",&x);  //读入元素序列

      while(x!=ZERO)  //ZERO是输入结束标记

          {

          insert(x,root);  //插入x

          scanf("%d",&x);  //读入下一个元素

           }

     return  root;  //构造完毕,返回根结点指针

   }

 

 

2.检索树的查找方法:

从根结点起,将要找的结点x与当前结点a比较:

如果遇到空树,表明x不在树中(查找失败)

若x=a,找到x (查找成功) ;

若x<a,则递归地查找左子树;

若x>a,则递归地查找右子树;

 

查找算法:

Bptr  search(element_type x,Bptr p)

   {

     if (p==NULL)

    return  NULL;   //遇到空树

     if (x==p->data)

    return p;  //找到x

   if (x<p->data)

          return search(x, p->Lson); //递归向左

   else

     return  search(x, p->Rson);  //递归向右

   }

主调语句:  p=search(x,root);

 

3. 检索树的插入方法:

从根结点起,将要插入的元素x与当前的结点比较,

如果x小于或等于当前结点值,就向左搜索;

如果x大于当前结点值,就向右搜索;

直至遇到空结点,就将x作为一片新叶插在这个空

位置上

 

插入算法:

void  insert(element_type x, Bptr &p)

   {

   if (p==NULL)       //遇到空树

{

   p=new  Bnode;   //申请新结点

       p->data=x;   //置新结点的值域

       p->Lson=p->Rson=NULL;  //新结点作叶子

       return;    //插入完毕,返回

    } //否则,尚未找到插入点,继续查找.

 if(x<=p->data)

   insert(x,p->Lson);  //递归的向左

else

   insert(x,p->Rson);   //递归的向右

}

主调语句为: insert( x, root);

 

检索树的删除方法:

要点:如何接好断枝,并保持“左小右大”

 

大体步骤如下:

步骤1)先用查找的方法找到要删除的结点x,并记住x的父亲f,再根据下列几种不同情况作出处理。

步骤2)若x是叶,只要把f指向x的那个链域(Lson或Rson)置空,就删除了x。

步骤3)若x只有一个儿子,只要将f指向x的那条链域(Lson或Rson)改为指向x的那个唯一的儿子。

步骤4)若x有两个儿子,就要找到x的中序前驱y,用y代替x,并删除y。这里“代替”指的是将结点y的值域复制到结点x中。

 

带监督元结点检索树的删除算法;

#define  SUCC  1

#define  NOTFOUND  0

根结点带带无穷小监督元

int deleteT(element_type x, Bptr root)

   { 

 Bptr f,p,q,s,r;

    p=NULL;   //p将指向要删除结点

    f=root;    // f的初值指向虚根

    q=root->Rson;  //q搜索指针

 while(q!=NULL)  //循环查找x

 {

       if(x==q->data) 

 {

    p=q;

 q=NULL;} //找到x

     else//没找到x后,继续搜索

     if(x<q->data)

{

   f=q;

  q=q->Lson;

}  //向左搜索

     else

 {

  f=q;

  q=q->Rson;

}    //向右搜索

}

 if(p==NULL)

   return  NOTFOUND; //没找到x

// 以下是找到x(p指向x)后的具体删除操作步骤

     if (p->Rson==NULL)  // p无右儿子,用左儿子代替p

     {    if(p==f->Lson)

  {

    f->Lson=p->Lson;

    delete p;

  }

        else

  {

   f->Rson=p->Lson;

  delete p;

  }

}

else

{

  if (p->Lson==NULL)  //p无左儿子,用右儿子代替p

     {

                   if (p==f->Lson)

      {

        f->Lson=p->Rson;

         delete p;

        }

           else

       {

        f->Rson=p->Rson;

        delete p;

        }

}        

//以下是p有两个儿子情况的处理

//p有两个儿子,找p的中序前驱

else

  { 

s=p->Lson;   //s是p的左儿子

   if(s->Rson==NULL) //s没有右儿子,用s代替p

   {

   p->data=s->data; //用s的值域代换p的值域

        p->Lson=s->Lson;  //删去s

        delete  s;  

  }

 //以下是s有右儿子的情况

else

//s有右儿子,找p的左儿子的最右子孙r

    {  r=s->Rson; 

        while(r->Rson!=NULL)

   {

    s=r;

    r=r->Rson;

  }

        p->data=r->data;  //用r的值域代换p的值域

        s->Rson=r->Lson; //删去r

        delete r;

      }

}

   return  SUCC; //返回删除成功信息

 }

 

二叉检索树的源代码:
// Bitree.cpp : 定义控制台应用程序的入口点。
//
// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define MAXSIZE 100
#define NULL 0

typedef int keytype;
typedef int elemtype;

typedef struct node
{
    keytype key;    //关键字域 
    elemtype other;   //其他数据域 
    struct node *lchild, *rchild;        //左右子树
}bilist;   //二叉检索树的节点结构 


bilist * insert(bilist *t, bilist*s)   /* 将*s结点插入到一棵二叉检索树*r中*/
{
    bilist *f=NULL;            //双亲结点的指针
    bilist *p=NULL;            //临时指针
    p = t;
    while (p != NULL)
    {
        f = p;
        if (s->key == p->key)  //该数值已存在
            return t;

        //若该数值小于根结点,遍历左子树,否则遍历右子树
        if (s->key<p->key)        
            p = p->lchild;
        else 
            p = p->rchild;

    }
    //建树失败
    if (t == NULL)   
        return s;
    //若该数值小于双亲结点,作为左孩子,否则作为右孩子
    if (s->key<f->key) 
        f->lchild = s;
    else 
        f->rchild = s;
    return t;
}



bilist *creat(keytype r[], int n)  //二叉检索树的构造函数算法 
{
    int i;
    bilist *s, *t;
    t = NULL;
    for (i = 0; i<n; i++)
    {
        s = (bilist *)malloc(sizeof(bilist));        //动态分配字节为bilist的内存空间
        s->key = r[i];                                //把数组的元素存入新结点
        
        s->other = NULL;
        s->lchild = NULL;
        s->rchild = NULL;
        //insert(&t,s);

        t = insert(t, s);                        
    }
    return t;
}


/*
int search(bilist *t,keytype k)  //二叉检索树算法      递归算法
{
if((t==NULL) || (t->key==k)) return t;
else if(t->key<k) return(search(t->rchild,k));
else return(search(t->lchild,k));
}
*/


int search(bilist *t, keytype k)  /*二叉检索树检索算法*/
{
    while (t != NULL)
    {
        //寻找到了,返回该数值
        if (t->key == k) 
            return t->key;
        //若根结点大于查询数,遍历左子树,否则遍历右子树
        if (t->key>k) 
            t = t->lchild;
        else 
            t = t->rchild;
    }

    return -1;
}


//中序输出整棵二叉树
void Show(bilist *t)
{
    if(t!=NULL)
    {
        Show(t->lchild);
        printf("%d ",t->key);
        Show(t->rchild);
        }
};

int main()
{
    keytype A[MAXSIZE];
    int i, data, n = 11;
    
    bilist *root;            //实例化一个对象
    for (i = 0; i<n; i++)
    {
        scanf("%d", &A[i]);
    }
    
    printf("\n");
    root = creat(A, n);
    Show(root);
    
    //查询某数值
    printf("\nplease input the search key:");
    scanf("%d", &data);
    if (search(root, data) != NULL) 
        printf("search succed!\n");
    else 
        printf("search failed!\n");

    getchar();
    system("pause");
}

 

posted @ 2018-03-05 15:00  gd_沐辰  阅读(368)  评论(0编辑  收藏  举报