zoukankan      html  css  js  c++  java
  • 二叉排序树-C语言

    一、 实验目的

    理解二叉排序树与平衡二叉树的概念,掌握二叉排序树的构造方法,实现二叉排序树的插入、删除与查找算法。

    二、 实验内容

    通过编写程序,实现二叉排序树的查找算法。
    具体步骤如下:

    1. 创建二叉排序树的查找函数、插入函数和删除函数;
    2. 在主函数中,创建二叉排序树,输入要查找的关键字,调用相应的子函数,实现二叉排序树的相关算法。

    三、 实验工具

    Dev - C++

    四、实验代码

    //Authors:xiaobei
    
    //算法1 二叉排序树的递归查找
    //算法2 二叉排序树的插入
    //算法3 二叉排序树的创建
    //算法4 二叉排序树的删除
    #include<stdio.h>
    #include<stdlib.h>
    #define ENDFLAG '#'
    #define OK 1
    #define OERROR 0
    //二叉树存储表示
    typedef struct ElemType{ 
     char key;
    }ElemType;
    typedef struct BSTNode{
     ElemType data; //结点数据域
     BSTNode *lchild,*rchild; //左右孩子指针
    }BSTNode,*BSTree;
    //函数二叉排序树的递归查找
    BSTree SearchBST(BSTree T,char key){
      //在根指针T所指二叉排序树中递归地查找某关键字等于key的数据元素
      //若查找成功,则返回指向该数据元素结点的指针,否则返回空指针
      if((!T)|| key==T->data.key) return T;                     //查找结束
      else if (key<T->data.key)  return SearchBST(T->lchild,key); //在左子树中继续查找
      else return SearchBST(T->rchild,key);             //在右子树中继续查找
    }
    //函数二叉排序树的插入
    int InsertBST(BSTree &T,ElemType e){
      //当二叉排序树T中不存在关键字等于e.key的数据元素时,则插入该元素
     BSTree S;
     if(!T){                     //找到插入位置,递归结束
       S = (BSTNode*)malloc(sizeof(BSTNode));            //生成新结点*S
             S->data = e;                    //新结点*S的数据域置为e   
             S->lchild = S->rchild = NULL;  //新结点*S作为叶子结点
             T = S;                 //把新结点*S链接到已找到的插入位置
             return 1;
     }
     else if(e.key< T->data.key)
      InsertBST(T->lchild,e);    //将*S插入左子树
     else if(e.key> T->data.key) 
      InsertBST(T->rchild,e);    //将*S插入右子树
     else
      return 0;
    }
    //函数二叉排序树的创建
    int CreateBST(BSTree &T){
      //依次读入一个关键字为key的结点,将此结点插入二叉排序树T中
      T=NULL;
      ElemType e;
      printf("
    【请依次输入二叉排序树元素】
    ");
      scanf("%c",&e.key);
      while(e.key!=ENDFLAG){        //ENDFLAG为自定义常量,作为输入结束标志
        InsertBST(T, e);              //将此结点插入二叉排序树T中
        scanf("%c",&e.key);
      }//while
      return OK;
    }
    //函数二叉排序树的删除
    void DeleteBST(BSTree &T,char key){
      //从二叉排序树T中删除关键字等于key的结点
       BSTree p = T;
       BSTree f = NULL;                       //初始化
       BSTree q;
       BSTree s;
     /*------------下面的while循环从根开始查找关键字等于key的结点*p-------------*/
       while(p){                  
        if (p->data.key == key)
         break;               //找到关键字等于key的结点*p,结束循环
        f = p;                                //*f为*p的双亲结点
        if(p->data.key> key)
         p=p->lchild;          //在*p的左子树中继续查找
        else
         p=p->rchild;                      //在*p的右子树中继续查找
       }//while
      if(!p){
       printf("
    【待删除的元素不存在!】
    ");
       return;                          //找不到被删结点则返回
      }
    /*―考虑三种情况实现p所指子树内部的处理:*p左右子树均不空、无右子树、无左子树―*/
     if ((p->lchild) && (p->rchild)){       //被删结点*p左右子树均不空
       q = p;
       s = p->lchild;
       while (s->rchild){                  //在*p的左子树中继续查找其前驱结点,即最右下结点
        q = s;
        s = s->rchild;
       }                 //向右到尽头
       p->data = s->data;                 //s指向被删结点的“前驱”
       if(q!=p){
        q->rchild = s->lchild;       //重接*q的右子树
       }
       else 
        q->lchild = s->lchild;          //重接*q的左子树
       delete s;
       }//if
     else{
      if(!p->rchild) {                  //被删结点*p无右子树,只需重接其左子树
         q = p; p = p->lchild; 
        }//else if
      else if(!p->lchild) {                //被删结点*p无左子树,只需重接其右子树
        q = p; p = p->rchild;
        }//else if
      /*――――――――――将p所指的子树挂接到其双亲结点*f相应的位置――――――――*/
        if(!f) T=p;                        //被删结点为根结点
        else if (q==f->lchild) f->lchild = p; //挂接到*f的左子树位置
        else f->rchild = p;                  //挂接到*f的右子树位置
        delete q;
     }
    }
    //二叉树中序遍历
    void InOrderTraverse(BSTree &T){
     if(T)
     {
     InOrderTraverse(T->lchild);
     printf("%c",T->data.key);
     InOrderTraverse(T->rchild);
     }
    }
    //函数打印菜单
    void Menu(){
     printf("
    ************菜单***********
    ");
     printf("1.创建二叉排序树;
    ");
     printf("
    2.二叉排序树的查找;
    ");
     printf("
    3.二叉排序树的插入;
    ");
     printf("
    4.二叉排序树的删除;
    ");
     printf("
    0.退出;
    ");
     printf("***************************
    ");
     printf("【请输入你的选择】
    >>>");
    }
    //主函数 
    int main(){
     BSTree T,result;
     ElemType e;
     int user;
     char key;
     while(true){
      Menu();
      scanf("%d",&user);
      switch(user){
      case 1:{
       if(CreateBST(T))
        printf("
    【二叉排序树创建成功!】
    ");
       printf("当前有序二叉树中序遍历结果为:");
       InOrderTraverse(T);
       break;
          }
      case 2:{
       printf("
    【请输入待查找元素】
    ");
       getchar();
       scanf("%c",&key);
       result = SearchBST(T,key);
       if(result)
        printf("【查找成功!】
    该元素%c地址为:%d
    ",result->data,result);
       else
        printf("【查找失败!】
    该元素%c可能不存在
    ",key);
       break;
          }
      case 3:{
       printf("
    【请输入待插入元素】
    ");
       getchar();
       scanf("%c",&e.key);
       if(InsertBST(T,e))
        printf("
    【%c插入成功!】",e.key);
       else
        printf("
    【%c插入失败!可能待插入元素已存在!
    】",e.key);
       printf("当前有序二叉树中序遍历结果为:");
       InOrderTraverse(T);
       break;
          }
      case 4:{
       printf("
    【请输入待删除元素】
    ");
       getchar();
       scanf("%c",&key);
       DeleteBST(T,key);
       printf("当前有序二叉树中序遍历结果为:");
       InOrderTraverse(T);
       break;
          }
      case 0:exit(0);
      }
     }
     return 0;
    }
    
    

    五、 实验结果

    1. 创建二叉排序树
      1
    2. 二叉排序树查找
      2
    3. 二叉排序树插入
      3
    4. 二叉排序树删除
      4
    5. 退出
      5

    六、 总结与思考

    1. 二叉排序树是递归定义的,得到一个重要性质:中序遍历二叉排序树,可以得到结点值递增的有序序列。

    2. 当先后插入二叉排序树有序时,生成单支树,单支树的查找性能较差。

    3. 二叉排序树的查找与折半查找类似,但就维护表的有序性而言,二叉排序树更加有效,,对于需要经常进行插入、删除和查找运算操作的表,采用二叉排序树较好。

    4. 最好的情况下,平均查找长度与折半查找判定树相似,与 log 2n 成正比。

  • 相关阅读:
    结对第二次作业
    结对项目第一次作业
    2017 软工第二次作业
    2017软工实践--第一次作业
    软工--最后的作业
    软件产品案例分析
    个人技术博客—作业向
    软工结队第二次作业
    软工第二次作业---数独
    软工实践第一次作业----阅读有感
  • 原文地址:https://www.cnblogs.com/slz99/p/12527726.html
Copyright © 2011-2022 走看看