二叉排序树的基本操作

 //节点
typedef struct bsnode{
   int data;
   struct bstree *lchild;
   struct bstree *rchild;
}bsnode,*bstree;
 
------------------------------------------------------------------------------------
 
 创建二叉排序树:
 
1创建二叉树:
void createbstree(bstree &bt){ //调用插入函数逐个插入节点
    int key;
    scanf("%d",&key);
   if(key!=' '){
       insertnode(bt,key);
       scanf("%d",&key);
   }
}
 
2.插入节点:
 
bstree insertbsnode(bstree bt,char key){
    bstree p=bt;
    while(p){                //找到要插入的位置,当结束时p为空,pre为要插入节点的双亲
        pre=p;
        if(p->data==key)return bt;
        else if(keydata) p=p->lchild;
        else p=p->rchild;
    }
 
    q=(bstree)maliic(sizeof(bsnode));
    q->data=key;
    q->lchild=0;
    q->rchild=0;
 
    if(!bt)  bt=q;
    else{
        if(keydata)
            pre->lchild=q;
        else
            pre->rchild=q;
    }
    return bt;
}
 
3.删除树(调用删除函数逐个删除节点)
 
void deleteTree(BiTree T){
    if(!T)
        return OK;
    else{
        if(T->lchild)
            deleteTree(T->firstchild);
        if(T->lchild)
            deleteTree(T->nextsibling);
        free(T);
        T=NULL;
    }
}
 
4.删除节点:
 
bstree deletebsnode(bstree bt){
    bstree p=bt;
    while(p){
    pre=p;                     //标记其父节点以便删除
    if(key==p->data) break;      //找到要删除的节点
    else if(keydata)
        p=p->lchild;
    else
        p=p->rchild;
   }
    if(!bt||!p)  return bt;             // 树为空或者没有找到
    if(p->lchild==NULL||p->rchild==NULL)  //非空但要删除的节点没有左/右子树/没有孩子
        if(pre==NULL){              //要删除的节点为根节点
          if(!p->child)
            bt=p->rchild;
          else
            bt=p->lchild;
        }
       else{                       //要删除的节点不为根节点
         if(!p->lchild){
            if(p==pre->lchild)
               pre->lchild=p->rchild;
            else
               pre->rchild=p->rchild;
         }
         else{
            if(p==pre->lchild)
                pre->lchild=p->lchild;
            else
                pre->rchild=p->lchild;
        }
       }
    else{  //要删除的节点左右字数都存在。此时找出左子树的最大值,及左子树的最右孩子/根节点,将其复制到要删除的节点上,然后删除该孩子
        pre=p;       //保留p指针指向要删除的节点,用俩个指针分别指向前驱及后继
        q=pre->lchild;
        while(q->rchild){    //找出左子树的最右孩子
           pre=q;
           q=pre->rchild;
        }
        p->data=q->data;   //将左子树最右孩子或者左子数根节点的值赋予要删除的节点
        if(pre==p)           //左子树没有最右孩子
            pre->lchild=q->lchild;
        else                 //找到了最右孩子,此时最右孩子一定为其前驱的右孩子
            pre->rchild=q->lchild;
    }
}
 
-----------------------------------------------------------------------------------
二叉排序树的遍历(与二叉树遍历算法一样)
 
1.递归遍历
 
//先序遍历
void PreOrderTraverse(BsTree &T){
   if(T){
      visit(T->data);
      PreOrderTraverse(T->lchild);
      PreOrderTraverse(T->rchild);
   }
  return OK;
}
 
//中序遍历
void InOrderTraverse(BsTree &T){
  if(T){
    InOrderTraverse(T->lchild);
    visit(T->data);
    InOrderTraverse(T->lchild);
  }
  return OK;
}
 
//后序遍历
void PostOrderTraverse(BsTree &T){
  if(T){
    PostOrderTraverse(T->lchild);
    PostOrderTraverse(T->rchild);
    visit(T->data);
  }
}
 
 
2.非递归遍历,用栈辅助。
 
算法思想:把根节点及所有做孩子依次压入栈,再依次取出把其右孩子压入栈,再依次探查其左右孩子
 
//先序遍历
void PreOrderTraver(BsTree &T){
    Stack S;
    IniyStack(S);
    BsTree p=T;
    while(p||!emptyStack(S)){
       if(p){
        visit(p->data);
        Push(S,p);
        p=p->lchild;
       }
       else{
        Pop(S,p);
        p=p->rchild;
       }
    }
    return OK;
}
 
//中序遍历
void InOrderTraverse(Bstree &T){
  Stcak S;
  InitStack(S);
  BsTree p=T;
  while(p||!emptyStqck(S)){
    if(p){
        Push(S,p);
        p=p->lchild;
    }
    else{
        Pop(S,p);
        visit(p->data);
        p=p->rchild;
    }
  }
  return OK;
}
 
//后序遍历
void PostOrderTraver(BsTree &T){
   Stack S;
   InitStack(S);
   BsTree p=T;
   while(p||!emptyStack(S)){
      if(p){
        push(S,p);
        p=p->lchild;
      }
      else{
        if(p->rchild==NULL||pre==p->rchild){
            visit(T->data);
            pre=p;
            p=NULL;
        }
        else{
            p=p->rchild;
        }
      }
   }
   return OK;
}
 
//层次遍历二叉树,借助队列
void LevelOrderTreaverse(BsTree &T){
   Queue Q;
   InitQueue(Q);
   BsTree p=T;
   Enqueu(Q,p);
   while(!emptyQueue(Q)){
      DeQueue(Q,p);
      if(p){
        visit(p->data);
        EnQueue(Q,p->lchild);
        EnQUeue(Q,p->rchild);
      }
   }
   return OK;
}
 
 
 
---------------------------------------------------------------------------------
 
查找某个节点x
 
查找某个信息是否在二叉树中(先序递归遍历)
void searchch(BsTree T,char ch){
   BsTree p=T;
   if(p){
    if(p->data==ch)
        return p;
    else{
        searchch(T->lchild,ch);
        searchch(T->rchild,ch);
    }
   }
}
 
---------------------------------------------------------------------------------
 
插入节点,删除节点,交换左右子树
 
1.插入节点
 
在遍历的基础上找到其父节点再插入。
 
2.删除节点
 
在遍历的基础上找该节点再删除。
 
3.交换左右子树
 
//递归法
void exchange(BsTree T){
   BsTree item;
   if(T){
     exchange(T->lchild);
     exchange(T->rchild);
 
     item=T->lchild;
     T->lchild=T->rchild;
     T->rchild=item;
   }
}
//非递归法
利用非递归遍历交换
 
 
------------------------------------------------------------------------------------
求节点个数/叶子节点个数,树的深度
 
1.树的结点个数
 
//递归求解
void NodeNum(BsTree T)
{
    if(!T)
        return 0;
    else
        return NodeNum(T->lchild)+NodeNum(T->rchild)+1;
}
 
//非递归求解
 
利用非递归遍历方法求解
 
---------------------------------
 
2.求叶子节点个数:
 
//递归求解
void leavenum(BsTree T){
   if(T){
      if(T->lchild==NULL&&T->rchild==NULL)
        return 1;
      else
        return leavenum(T-lchild)+leavenum(T->rchild);
   }
}
 
//非递归求解
利用非递归遍历求解
 
 
-----------------------------------
 
3.求二叉树的深度
 
void depth(BsTree T){
   BsTree P=T;
   int lh=0,rh=0;
   if(!p)
      return 0;
   else{
      lh=depth(T->lchild);
      rh=depth(T->rchild);
      return (lh>rh?lh:rh)+1;
   }
}
 
---------------------------------------------------------------------------------------------
原文地址:https://www.cnblogs.com/yujon/p/5467599.html