二叉查找树的其他操作



二叉查找树的其他操作:

(1)判断一个二叉树是否为二叉查找树;

(2)二叉查找树中记录每个节点的出现次数;

---------------------

(1)判断一个二叉树是否为二叉查找树

1)分析:
二叉查找树的中序序列为递增序列,所以对一个二叉树进行中序遍历,如果始终保持当前节点的中序前驱节点pre的值小于当前节点的值,则是二叉查找树,否则不是。

2)代码实现:DataType pre=0;//pre为全局变量,保持的是当前节点的中序前序的值,初始值为一个很小的值。
int isBST(BSTNode* t){
     int judge1,judge2;
     if(t==NULL) 
        return 1;
     else {
          judge1=isBST(t->lchild);
          if(judeg1 == 0 || pre >= t->data)
            return 0;
          pre=t->data;  //更新前驱为当前节点
          judeg2=isBST(b->rchild);
          return judge2;
     }
}


或者:

/*
    目的:
        判断以t为根节点的二叉树是否是二叉查找树,如果是则judge=1,否则judge=0;
    注意:
        judge,pre均为引用型参数;
        pre为当前子树根结点t的中序前驱;
        调用时:
        t=root,pre=NULL,judge=1;
*/
void isBST(BSTNode* t ,BSTNode* & pre , int & judge)
{
    if(t!=NULL && judge==1) {
        isBST(t->lchild,pre,judge);//递归左子树判断;
        if(NULL==pre) {
            pre=t;
            judge=1; 
        }
        else {
            if(pre->data<t->data) {
                pre=t;
                judge=1;
            }
            else 
                judge=0;
        }

    if(judge)  
        isBST(t->rchild,pre,judge);
     }

}
-------

(2)二叉查找树的每个节点中含有四个字段,分别为data,count,lchild,rchild;
    count表示相同关键码的节点个数;当向二叉树中插入一个 节点时,如果已经存在则相应的count+1,
    否则,插入新节点,并且count=1;
    写出插入算法;

/*
    在以t为根节点的二叉查找树中插入值为x的节点;
    注意:
        t,father为引用型参数;
        father为插入的值为x的节点 父节点。
*/
void insert(BSTNode* &t ,BSTNode*& father, DataType x)
{
     BSTNode* pnode=t;
     //查找值为x的节点pnode,
     //如果查找到,则pnode非空,father为其父节点,count++;
     //如果没有找到,则pnode==NULL,father为值很靠近x的叶子节点。

     while(pnode!=NULL){
          if(pnode->data != x){
               father=pnode;
               if(x<pnode->data)
                   pnode=pnode->lchild;
               else
                   pnode=pnode->rchild;
          }
          else{
              pnode->count++;
              return ;
          }
     }

     BSTNode* newNode=new BSTNode;//创建一个新节点
     newNode->data=x;
     newNode->count=1;
     newNode->lchild=newNode->rchild=NULL;

     if(father==NULL) //即:根节点t==null
         t=newNode;
     else if(x < father->data)
         father->lchild=newNode;
     else
         father->rchild=newNode;
}

------

(3)二叉查找树可以对n个元素进行排序:
    1> 将n个不同值的元素A[n]插入到二叉排序树中;
    2> 中序遍历,然后将元素存入到数组A中;
    3> 删除二叉查找树中的最大值;

代码实现:
    1> 将n个不同值的元素A[n]插入到二叉排序树中
        略;


    2> 中序遍历,然后将元素存入到数组A中
    /*
        中序遍历以t为根节点的二叉查找树,结果存在数组A[n]中,
        n为排序后的数组长度。
        注:初始时调用n的值为0;
        n为引用型参数
    */

    void inorderTraversal(BSTNode* t , DataType A[], int & n)
    {
         if(t) {
             inorderTraversal(t->lchild,A,n);
             A[n++]=t->data;
             inorderTraversal(t->rchild,A,n);
         }
    }

    3> 删除二叉查找树中的最大值
    /*
        目的:删除二叉查找树中的最大值节点;成功则返回1,否则返回0.
            最大值节点是最右节点;
        注:root为引用型参数
    */

    int deleteMax(BSTNode* & root)
    {
     
         BSTNode* pnode=root;   //
         BSTNode* father=NULL;  //father为pnode的父节点,pnode为father的右孩子。

         if(NULL==root) 
             return 0;
         while(pnode->rchild!=NULL) {
             father=pnode;
             pnode=pnode->rchild;
         }  //循环结束时,pnode为最右节点,没有右孩子,pnode为father的右孩子。

         if(NULL==father) { //原二叉查找树没有右子树
             root=root->lchild;
             delete pnode;
         }
         else {
             father->rchild=pnode->lchild;
             delete pnode;
         }
        return 1;
    }

------

(4)已知一个递增的数组A[N],以哪个元素为根节点生成二叉查找树,使得树的平衡性最好?

1)分析:
    以递增数组的居中的元素为根节点,按照折半查找的生成方法构造二叉查找树,生存的二叉查找树的平衡性比较好。

2)代码实现:
    /*
        目的:以一个递增的序列生成一个平衡性较好的二叉查找树;
        注:root为引用型参数;
        low,high分别为有序序列的上界和下界;初始值分别为0,n-1;
        n为数组长度, array为递增的序列;
    */

void createBST(BSTNode* & root, int low ,int high ,DataType []array)
{
     if(low > high) 
          root=NULL;
     else {
          int mid=(high-low)/2 + low;
          root=new BSTNode;     //创建根节点
          root->data=array[mid];
          createBST(root->lchild, low, mid-1, array);
          createBST(root->rchild, mid+1, high, array)
     }
}

--------

(5)求二叉查找树中某个节点p的层次;

1.方法一:层次遍历
2.方法二:利用二叉查找树的特性:
/*
    在二叉查找树root中查找节点pnode的层次,如果找到则返回层次,否则返回0;
    规定:根节点的层次为1;
*/
int level_count(BSTNode* root , BSTNode* pnode)
{
     int level=0;
     BSTNode* tempNode=root;
     if(tempNode != NULL) {
      level++;  //非空,则根结点对应的层次为1;

      while(tempNode!=NULL && tempNode->data!=pnode->data){
           if(pnode->data<tempNode->data)
               tempNode=tempNode->lchild;
           else 
               tempNode=tempNode->rchild;
           level++;
      }

      if(tempNode==NULL) 
            level=0;    //没找到pnode,则level=0;
     }
     return level;
}


------

(6)判定一个给定的关键码序列是否为二叉查找树的查找序列:

1)分析:
由二叉查找树,查找路径的特点:

1。查找路径只可能沿着某个节点逐层向下,不可能往上回溯;
2.查找范围在关键码上下波动,且不断接近关键码;
3.在关键码左子树的查找序列小于关键码,为递增数组;
在关键码右子树的查找序列大于关键码,为递减数组;

举例:
给定一个值60,在二叉查找树上查找关键值为60的节点时,访问的关键码序列为S={20,30,90,80,40,50,70,60}.将S分为两个序列,S1为小于等于查找值60的数据,所以S1={20,30,40,50,60};
S2为大于查找值的数据,所以S2={90,80,70}.
因为S1中数据为递增,且每个元素小于等于待查数据,S2为递减数据,且每个数据大于待查数据,所以,S为查找序列。

2)代码实现:

#define Maxsize 20
typedef struct {  //待认定的查找序列
 DataType eleArray[Maxsize];
 int len;//序列中实际的数据个数
}Sequence;

/*
将序列S划分为两个序列s1,s2;
注:s,s1,s2为引用型参数;
*/
void devision(Sequence &s ,Sequence &s1, Sequence & s2){
 int i=0,i1=0,i2=0;

 do{
  while(i+1<=s.len-1 && s.eleArray[i]<s.eleArray[i+1])
  s1.eleArray[i1++]=s.eleArray[i];//将s中有递增趋势的元素放到s1中;

  while(i+1<=s.len-1 && s.eleArray[i]>s.eleArray[i+1])
  s2.eleArray[i2++]=s.eleArray[i];//将s中有递减趋势的元素放到s2中;

 }while(i+1<=s.len-1)//因为循环内i+1为下标

 //上例中,s1={20,30,40,50},s2={90,80,70};
 s1.len=i1;
 s2.len=i2;

}

/*
判断s1是否为递增序列,且所有元素小于x;s2是否为递减序列,且所有元素大于x
*/
int judge(Sequence& s1, Sequence & s2, int x){
 int flag=1;
 int i=0;

 while(flag && i+1<=s1.len-1){
  if(s1.eleArray[i]>s1.eleArray[i+1] || s1.eleArray[i]>x)
  flag=0;

  else i++;
 }

 i=0;
 while(flag && i+1<=s2.len-1){
  if(s2.eleArray[i]<s2.eleArray[i+1] || s2.eleArray[i]<x )
  flag=0;
  else i++;
 }

 return flag;
}

/*判断是否为查找序列*/
int isBSTsearchSequence(Sequence& s,int x){
 Sequence s1,s2;
 division(s,s1,s2);
 return judge(s1,s2,x);
}

-------
(7)删除二叉查找树中值小于等于x的所有节点;

1)分析:

1.若节点pnode的值data<=x,则删除pnode以及pnode的左子树,用pnode的右子树代替pnode,
然后重复此操作,直至pnode->data>x;

2.若节点pnode->data>x,则沿着pnode的左分支搜索,直至pnode->data<=x,然后回到1删除。

2)代码实现:

/*
后序遍历,删除以p为根节点子树。
*/
void deleteSubTree(BSTNode* p){
 if(p){
  deleteSubTree(p->lchild);//删除左子树;
  deleteSubTree(p->rchild);//删除右子树
  delete p;
 }
}

/*
删除小于等于x的节点
*/
void delete_LQ_x(BSTNode* & root, DataType x){
 BSTNode* pnode=root,*father=NULL;
 BSTNode* tempNode;
 while(pnode!=NULL && pnode->data<=x){
   tempNode=pnode;
   pnode=pnode->rchild;//用右子树取代当前节点
   deleteSubTree(tempNode->lchild);//将pnode的左子树删除
   delete tempNode;
   if(father!=NULL) father->lchild=pnode;
   //因为father节点为大于x的,pnode作为father的左孩子被删除后,
      // father的lchild就找不到了。所以需更新。

   if(pnode->data>x){//用右子树替换后的pnode的值如果大于x
    while(pnode!=NULL && pnode->data>x){
     father=pnode;
     pnode=pnode->lchild;
    }
   }
 }

}

-------

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值