基于二叉排序树的基本操作

来源:互联网 发布:qq三国79js单刷孟获 编辑:程序博客网 时间:2024/06/07 23:44
 二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于或等于它的根节点的值;
(2)若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
以下为二叉排序树的实例和结点结构

//二叉排序树的结点结构typedef struct Node{   ElemType val;   struct Node *LChild,*RChild;}Node;
二叉排序树的插入
1、找出被插结点的父亲结点。
2、判断被插结点是其父亲结点的左、右儿子。将被插结点作为叶子结点插入。
3、若二叉树为空。则首先单独生成根结点。
//在二叉排序树中插入一个关键字为value的结点int Insert(Node *root,int value){  Node *p=root,*q=NULL,*par=NULL;  int mark=0;  while(p!=NULL&&mark==0){//找到value应插入的父节点      par=p;      if(p->val==value){        mark=1;      }else if(p->val>value){        p=p->LChild;      }else if(p->val<value){        p=p->RChild;      }  }  if(mark==1)  return 0;//存在value则不插入  q=(Node *)malloc(sizeof(Node));  q->val=value;  q->LChild=q->RChild=NULL;  if(root==NULL){     root=q;  }else if(par->val>q->val){//判断插入其左右子树     par->LChild=q;  }else{     par->RChild=q;  }  return 1;}
二叉排序树的查找,像其他树的查找一样遍历结点
//查找关键字为key的结点,返回指向该结点的指针Node *Search(Node *root,int key){  Node *p=NULL;  if(root==NULL){    return NULL;  }  p=root;  while(p){    if(p->val==key){      return p;    }else if(p->val>key){//当前节点的值大于key则去结点的左子树查找      p=p->LChild;    }else{      p=p->RChild;    }  }  return p;}
二叉排序树的删除
1、若*p结点为叶子结点,即PL(左子树)和PR(右子树)均为空树。由于删去叶子结点不破坏整棵树的结构,则可以直接删除此子结点。
2、若*p结点只有左子树PL或右子树PR,此时只要令PL或PR直接成为其双亲结点*f的左子树(当*p是左子树)或右子树(当*p是右子树)即可,作此修改也不破坏二叉排序树的特性。
3、若*p结点的左子树和右子树均不空。在删去*p之后,为保持其它元素之间的相对位置不变,令*p的直接前驱(或直接后继)替代*p,然后再从二叉排序树中删去它的直接前驱(或直接后继)-即让*f的左子树(如果有的话)成为*p左子树的最左下结点(如果有的话),再让*f成为*p的左右结点的父结点。
//从二叉排序树中删除值为value的结点并重新连接它的左或右子树int Delete(Node *root,int value){  Node *s,*p,*q;  p=Search(root,value);//查找value的结点  if(p==NULL) return 1;//没有找到  if(!p->RChild){//右子树空则只需重接它的左子树    q=p;    p=p->LChild;    free(p);  }else if(!p->LChild){//左子树空则只需重接它的右子树    q=p;    p=p->RChild;    free(p);  }else{//左右子树均不空    q=p;    s=p->RChild;    while(s->LChild){//转右,然后向左到尽头      q=s;      s=s->LChild;    }    p->val=s->val;//s指向被删结点的前驱    if(q!=p){      q->LChild=s->RChild;    }else{      q->LChild=s->LChild;    }    free(s);  }  return 0;}

以下为完整程序
#include<stdio.h>#define N 100typedef int ElemType;//二叉排序树的结点结构typedef struct Node{   ElemType val;   struct Node *LChild,*RChild;}Node;Node *BitRepTr;//查找关键字为key的结点,返回指向该结点的指针Node *Search(Node *root,int key){  Node *p=NULL;  if(root==NULL){    return NULL;  }  p=root;  while(p){    if(p->val==key){      return p;    }else if(p->val>key){//当前节点的值大于key则去结点的左子树查找      p=p->LChild;    }else{      p=p->RChild;    }  }  return p;}//在二叉排序树中插入一个关键字为value的结点int Insert(Node *root,int value){  Node *p=root,*q=NULL,*par=NULL;  int mark=0;  while(p!=NULL&&mark==0){//找到value应插入的父节点      par=p;      if(p->val==value){        mark=1;      }else if(p->val>value){        p=p->LChild;      }else if(p->val<value){        p=p->RChild;      }  }  if(mark==1)  return 0;//存在value则不插入  q=(Node *)malloc(sizeof(Node));  q->val=value;  q->LChild=q->RChild=NULL;  if(root==NULL){     root=q;  }else if(par->val>q->val){//判断插入其左右子树     par->LChild=q;  }else{     par->RChild=q;  }  return 1;}//从二叉排序树中删除值为value的结点并重新连接它的左或右子树int Delete(Node *root,int value){  Node *s,*p,*q;  p=Search(root,value);//查找value的结点  if(p==NULL) return 1;//没有找到  if(!p->RChild){//右子树空则只需重接它的左子树    q=p;    p=p->LChild;    free(p);  }else if(!p->LChild){//左子树空则只需重接它的右子树    q=p;    p=p->RChild;    free(p);  }else{//左右子树均不空    q=p;    s=p->RChild;    while(s->LChild){//转右,然后向左到尽头      q=s;      s=s->LChild;    }    p->val=s->val;//s指向被删结点的前驱    if(q!=p){      q->LChild=s->RChild;    }else{      q->LChild=s->LChild;    }    free(s);  }  return 0;}//中序遍历二叉排序树void MidOrder(Node *root){  if(root!=NULL){     MidOrder(root->LChild);     printf("%d ",root->val);     MidOrder(root->RChild);  }}int main(){  Node *root,*p;  int k,i,val,n,num[N];  printf("首先建立二叉排序树\n");  printf("请输入结点个数\n");  scanf("%d",&n);  if(n<1){    return -1;  }  root=(Node *)malloc(sizeof(Node));  printf("输入各节点的关键字值,以空格间隔\n");  scanf("%d",&num[0]);  root->val=num[0];  root->LChild=NULL;  root->RChild=NULL;  for(i=1;i<n;i++){    scanf("%d",&num[i]);    Insert(root,num[i]);  }  printf("对二叉排序树进行的中序遍历结果如下:\n");  MidOrder(root);  printf("\n");  printf(" 1-----------查找\n");  printf(" 2-----------查找\n");  printf(" 3-----------查找\n");  printf("请选择(1-3):");  scanf("%d",&k);  switch(k){    case 1:      printf("选择了查找\n");      printf("请输入要查找的值:");      scanf("%d",&val);      if(Search(root,val)!=NULL){        printf("找到了\n");      }else{        printf("没有找到\n");      }     break;    case 2:      printf("选择了插入\n");      printf("请输入要插入的值:");      scanf("%d",&val);      if(Insert(root,val)!=0){        printf("插入成功\n");        printf("对新二叉排序树进行中序遍历的结果如下:\n");        MidOrder(root);        printf("\n");      }else{        printf("插入失败,值为%d的结点已存在\n",val);      }     break;    case 3:      printf("选择了删除\n");      printf("请输入要删除的值:");      scanf("%d",&val);      if(Delete(root,val)!=1){        printf("删除成功\n");        printf("对新二叉排序树进行中序遍历的结果如下:\n");        MidOrder(root);        printf("\n");      }else{        printf("删除失败,值为%d的结点不存在\n",val);      }     break;    default:        printf(" 1-----------查找\n");        printf(" 2-----------查找\n");        printf(" 3-----------查找\n");      break;  }}





0 0
原创粉丝点击