二叉排序树(二叉搜索树)

知识点总结报告

知识点:

二叉排序树

(原理)二叉排序树又称二叉搜索树。其定义为二叉排序树或者空树或者满足以下性质的二叉树。

性质1

若根节点的左子树非空,则左子树上的所有结点关键字均小于根结点关键字

性质2

若根节点的右子树非空,则右子树上的所有结点关键字均大于根结点关键字

性质3

根结点的左、右子树本身又各是一棵二叉排序树

 二叉排序树结点类型

typede fstruct node      //元素类型

{  KeyType key;      //关键字项

  Info Type data;      //其他数据域

  struct node *lchild,*rchild;  //左、右孩子指针

}BSTNode;

二叉排序树的插入和创建

  插入的递归算法InsertBST( )

bool InsertBST(BSTNode *&bt,KeyType k)  //在二叉排序树bt中插入一个关键字为k的结点,若插入成功返回真,否则返回假

{  if (bt==NULL)             //原树为空,新插入的结点为根结点

  {  bt=(BSTNode *)malloc(sizeof(BSTNode));

    bt->key=k;bt->lchild=bt->rchild=NULL;

    return true;

  }

  else if(k==bt->key)          //树中存在相同关键字的结点,返回假

    return false;

  else if(k<bt->key)

    return InsertBST(bt->lchild,k);     //插入到左子树中 

  else     

    return InsertBST(bt->rchild,k);      //插入到右子树中

}

  创建二叉排序树CreateBST( )

BSTNode *CreateBST(KeyType A[ ],int n)      //创建二叉排序树  返回BST树根结点指针

{  BSTNode *bt=NULL;              //初始时bt为空树

  int i=0;

  while(i<n)

  {  InsertBST(bt,a[i]);              //将关键字a[i]插入二叉排序树bt中

    i++;

  }

  return bt;                    //返回建立的二叉排序树的根指针

}

  二叉排序树的查找(在二叉排序树bt上查找关键字为k的元素,成功时返回该结点指针,否则返回NULL)

BSTNode *SearchBST(BSTNode *bt,KeyType k)      //二叉排序树查找

{  if(bt==NULL||bt->key==k)               //递归结束条件

    return bt;                    

  if(k<bt->key)

    return SearchBST(bt->lchild,k);           //在左子树中递归查找

  else

    return SearchBST(bt->rchild,k);            //在右子树中递归查找

}

  如果不仅要找到关键字为k的结点,还要找到双亲结点,采用递归算法如下:

BSTNode *SearchBST1(BSTNode *bt,KeyType k,BSTNode *f1,BSTNode *&f)/*在二叉排序树bt上查找关键字为k的结点,若查找成功,该函数返回该结点指针,f返回其双亲结点,否则,该函数返回NULL,调用方法如下SearchBST1(bt,x,NULL,f);  这里的第3个参数f1仅作中间参数,用于求f,初始设为NULL*/

{  if(bt==NULL)

  {  f=NULL;

    return (NULL);

  }

  else if(k==bt->key)

  {  f=f1;

    return(bt);

  }

  else if(k<bt->key)

    return SearchBST1(bt->lchild,k,bt,f);        //在左子树中递归查找

  else

    return SearchBST1(bt->rchild,k,bt,f);        //在右子树中递归查找

}

  二叉排序树的删除

删除过程分为以下几种情况:(删除操作必须首先进行查找,设在查找结束时p指向要删除的结点)

(1)若p结点是叶子结点,直接删去该结点。这是最简单的删除结点情况。

(2)若p结点只有左子树没有右子树。根据二叉排序树的特点,可以直接将其左孩子替代结点p(结点替换)。

(3)若p结点只有右子树没有左子树。根据二叉排序树的特点,可以直接将其右孩子替代结点p(结点替换)。

(4)若p结点同时存在左、右子树。根据二叉排序树的特点,可以从左子树中选择关键字最大的结点r,用结点r的值替代结点p的值(结点值替换),并删除结点r(由于r结点一定没有右孩子,删除它属于情况(2)),原理是用中序前驱替代被删结点。

  也可以从其右子树中选择关键字最小的结点r,用结点r的值替代结点p的值(结点值替换),而且将它删除(由于r结点一定没有左子树,删除它属于情况(3))。原理是用中序后继结点替代被删结点。

  首先查找关键字为k的被删结点p.

bool deletek(BSTNode *&bt,KeyType k)

{  if (bt!=NULL)

  {  if(k==bt->key)}        //查找到了被删结点bt

    {  deletep(bt);        //调用deletep删除结点bt

      return true;        //成功删除,返回真

    }

    else if(k<bt->key)

      deletek(bt->lchild,k);      //在左子树中查找

    else

      deletek(bt->rchild,k);      //在右子树中查找

  }

  else return false;            //未查找到,返回假

}

  删除结点p(结点p仅有右子树)

void deletep(BSTNode *&p)

{  BSTNode *q;

  q=p;        //让q指向结点p

  p=p->rchild;      //让p指向它的右孩子

  free(q);        //释放结点q的空间

}

  删除二叉排序树bt中关键字为k的结点

bool DeleteBST(BSTNode *&bt,KeyType k)        //在bt中删除关键字为k的结点

{  if(bt==NULL)

    return false;                  //空树删除失败,返回假

   else

  {  if(k<bt->key)

      return DeleteBST(bt->lchild,k);        //递归在左子树中删除为k的结点

    else if (k>bt->key)

      return DeleteBST(bt->rchild,k);        //递归在右子树中删除为k的结点

    else                      //找到了要删除的结点bt

      {  Delete(bt);              //调用Delete(bt)函数删除结点bt

        return true;              //删除成功,返回真

      }

   }

}

 void  Delete(BSTNode *&p)          //从二叉排序树中删除结点p

{  BSTNode *q;

  if(p->rchild==NULL)            //结点p没有右子树(含为叶子结点)的情况

  {  q=p;

    p=p->lchild;              //用结点p的左孩子替代它

    free(q);

  }

  else if(p->lchild==NULL)          //结点p没有左子树的情况

  {  q=p;

    p=p->rchild;              //用结点p的右孩子替代它

    free(q);

  }

  else Delete1(p,p->lchild);          //结点p既没有左子树又没有右子树的情况

}

 void Delete1(BSTNode *p,BSTNode *&r)    //被删结点p有左、右子树,r指向其左孩子

{  BSTNode *q;

  if(r->rchild!=NULL)            //递归找结点r的最右下结点

    Delete1(p,r->rchild);

  else                  //找到了最右下结点r(它没有右子树)

  {  p->key=r->key;          //将结点r的值存放到结点p中(结点值替代)

    p->data=r->data;

    q=r;              //删除结点r

    r=r->lchild;            //即用结点r的值存放到结点p中(结点值替代)

    free(q);             //释放结点q的空间

  }

}

 

 

posted @ 2018-01-31 14:48  珎珍  阅读(556)  评论(0编辑  收藏  举报