二叉排序树的应用(基于二叉排序树的个人通信录)

嵌入式 一个简单的个人通讯录(基于二叉排序树,带注释) TreeNode.h: [csharp] view plaincopyprint? #define N 50 typedef struct student { char name[N]; char studentID[N]; char brithday[N]; char tele[N]; }TreeData; typedef struct treenode { TreeData * 阅读详情
在日常生活中,个人通信录是我们不可少的,不管是纸式的个人通信录还是我们手机中的个人通信录,查寻是其最基本的操作,几乎所有的操作都是在查寻的基础上进行的,所以,查寻时间的快慢很大程度上决定了整个通信录的性能。所以,一个有着良好界面、查寻速快的通信录,是人们所追求的。

本设计应用折半查寻法的技术思想进行查寻,从本思想出发,可以有两种数据组织方式:一是应用链表进行组织数据,由于折半查寻法的特殊性,所要进行查寻的数据列必须是有序的数据列,这样要求对数据列进行排序。出于系统实时查寻的考虑,每次对通信录进行改变后都得进行重新排序,这样才能保证数据列是实时有序的。这样当操作量大时,排序所消耗的时间对整个系统有很大的影响。

二是应用二叉排序树来组织数据,由于二叉排序树是应用折半查寻法思想进行对数据进行存储的,所以,其左孩子大于双亲结点、右孩子小于双亲结点(或者左孩子小于双亲结点、右孩子大于双亲结点),这样就可以应用折半查寻法的思想进行查寻,从而减少对排序时所消耗的时间。

本设计采用第二种方法,即应用二叉排序树进行组织数据,在此基础上进行对个人通信录的各种操作。由于删除操作是本设计的重点,删除操作的成功与否直接影响到整个系统的成败,所以在此进行详细分析一下删除操作的实现。

此功能函数主要应用于删除将要进行删除的记录,此操作较其它几个操作难一点,同时也是此次设计的重点,所以,本函数的成败可以直接影响到本次设计的成败,同时,在进行二叉排序树进行组织时,如果不从系统的整体进行考虑,只想到简单地实现删除功能,将会出现错误。

在设计初期,由于没有考虑所有可能的情况,所以在进行删除最后一个结点时,总会出现内存不能引用的错误。最后想到应用浪费一个结点空间的技术进行处理此问题,就是根结点用来保存二叉排序树的某些信息,而不保存记录,与我们单链表中的头结点一样,这样做解决了上面所说的问题,同时在进行查寻双亲结点时也带来了很大的方便。

有关二叉排序树的删除的有关问题,请读者参考相关的参考文献,在此不再进行说明,本节重点在于说明本课程设计中有关删除的问题。

在本设计中,删除的首要条件是找到将要进行删除结点的双亲结点,由于根结点不用于存储记录,所以,可以不用进行判断根结点的情况,进行查寻双亲结点时,从根结点开始,首先进行判断根结点的左右子树是否为空,如果根结点的左右子树为空,则返回NULL,如果根结点的左子树(右子树)不为空,则将其左子树(右子树)的记录的学号与将要进行删除的学号进行比较,如果相等,则返回根结点;否则进行比较,如果左子树(右子树)不为空,且左子树(右子树)的学号大于(小于)要进行删除的学号,则进行递归在左子树(右子树)中进行查寻,直到查寻到或者当前结点的左右子树为空时结束。如果当前结点的学号与要进行删除的学号不相等,且当前结点的左右子树为空,则返回空,结束查寻过程。

经过对双亲结点的查寻,如果没有此记录,则进行提示,否则进行删除操作[1] [5],在进行删除时,有以下几种可能,以下操作中假设每次把要进行删除结点进行删除后,同时也释放了此结点所占用的内存空间,防止内存在运行过程中丢失。

第一:要进行删除的结点为叶结点,直接把其从二叉排序树中进行删除。

第二:此结点只有左子树或者右子树,这种情况下只需将只需把此结点的左子树或者右子树替换为双亲结点的左子树。

第三:此结点有左子树同时有也右子树,此种操作比较复杂,其中有两种方法进行删除,本课程设计中应用的方法是从某子树中找出一个结点(假设为Temp),将其值代替要进行删除结点的值,再把Temp结点进行删除。

这是 本人在大二的时候做的一个课程设计,见到论坛上有很多对二 叉树,特别是二叉排序树的不了解,所以,把它分享出来,如果需要每个功能模块的说明,设计文档,请给我发邮件或者到我的下载页面去下载,由于本人不在乎资 源分,所以下载页面所需资源分只1分就可以下载整个设计,包括详细的设计报告,不过本人把它转为PDF文档。同时,发表显示与编辑显示不太一样,本人对这玩意儿很少用,还是请看原版吧,有需要原版请与我联系。

我的 邮箱:sw_2006.1230@163.com     443120079@qq.com

下面为详细代码,希读者能看懂,由于本人一直专注于嵌入式底层驱动程序开发,所以,对数据结构与算法只能做为加强自己C语言的一个途径,也许在算法上与数据结构的组织上不太合理,请原谅。

  1. /**********************************************************************************
  2. *                            基于二叉排序树的个人通信录                                   
  3. *                               
  4. *                                   
  5. *
  6. *                                    
  7. *
  8. * 文    件: 基于二叉排序树树的个人通信录.C
  9. * 作    者: soon
  10. * 部    门: 长沙理工大学 
  11. * 编写日期: 2009.9.10
  12. * 模块版本: 
  13. * 修改记录:
  14. * ================================================================================
  15. * 版 本|  日  期  | 修改人 |                 
  16. * ================================================================================
  17. *      |          |        |
  18. *      |          |        |
  19. *      |          |        |
  20. * ================================================================================
  21. *
  22. *
  23. *          
  24. **********************************************************************************/ 
  25. #include <stdio.h> 
  26. #include <stdlib.h> 
  27. #include <assert.h> 
  28. #include <string.h> 
  29. FILE *input;                                     /*定认读取文件指针*/ 
  30. FILE *output;                                    /*定义保存文件指针*/ 
  31. /********************定义个人记录结构**********************/ 
  32. typedef struct Node 
  33. { 
  34.     char name[30];                               /*用于保存姓名*/ 
  35.     char code[30];                               /*用于保存学号*/ 
  36.     int age;                                     /*用于保年龄*/ 
  37. }NODE; 
  38. /************************定义二叉树结构体******************/ 
  39. typedef struct Tree 
  40. { 
  41.     NODE *student;                               /*个人通信记录*/ 
  42.     struct Tree *lchild; 
  43.     struct Tree *rchild; 
  44. }TREE; 
  45. static int TREESIZE=sizeof(TREE);                /*进行求二叉树所占的内存空间*/ 
  46. static int NODESIZE=sizeof(NODE);                /*进行求个人记录结构的内存空间*/ 
  47. TREE *Create_Tree(void );                         /*声明创建空二叉树的函数*/ 
  48. void Insert_Information(TREE *root,NODE *node);          /*声明进行插入函数*/ 
  49. void Look_Through_Information(TREE *root);                       /*声明浏览函数*/ 
  50. void Save_Information(TREE *root);                        /*声明保存函数*/ 
  51. int Find_Information(TREE *root,char *code);                 /*声明查寻函数*/ 
  52. int Rework_Information(TREE *root,char *code);               /*声明修改函数*/ 
  53. void Menu(void );                                 /*声明界面函数*/ 
  54. TREE *Find_Father_Node(TREE *root,char *code);           /*声明查寻双亲结点的函数*/ 
  55. void Delete_Information(TREE *root,char *code);          /*声明删除函数*/ 
  56. void Free_EMS_memory(TREE *root);                        /*声明释放内存空间函数*/ 
  57. /**********************主函数******************************/ 
  58. void main(void ) 
  59. { 
  60.     TREE *root; 
  61.     NODE *node; 
  62.     TREE *temp; 
  63.     char b[30]; 
  64.     int a; 
  65.     printf("*************************基于排序二叉树的个人通信录*****************************/n/n/n"); 
  66.     root = Create_Tree(); 
  67.     input = fopen("shuwen.txt","r");               /*打开文件*/ 
  68.     assert(input != NULL); 
  69.     if(!feof(input))                            /*文件不空,进行读取一条记录*/ 
  70.     { 
  71.         node = (NODE *)malloc(NODESIZE); 
  72.         assert(node != NULL); 
  73.         fscanf(input,"%s %s %d",node->code,node->name,&node->age);/*进行读取*/ 
  74.         temp=(TREE *)malloc(TREESIZE); 
  75.         assert(temp != NULL); 
  76.         temp->rchild = NULL; 
  77.         temp->lchild = NULL; 
  78.         temp->student = node; 
  79.         root->lchild = temp; 
  80.     } 
  81.     node = (NODE *)malloc(NODESIZE); 
  82.     assert(node != NULL); 
  83.     while((fscanf(input,"%s %s %d",node->code,node->name,&node->age))!=EOF)/*读取文件中所有的记录,只到文件为空*/ 
  84.     { 
  85.         Insert_Information(root->lchild,node);           /*将读取的文件进行插入*/ 
  86.         node=(NODE *)malloc(NODESIZE); 
  87.         assert(node!=NULL);  
  88.     } 
  89.     fclose(input);                               /*关闭读取文件指针*/ 
  90.     while(1) 
  91.     { 
  92.         Menu(); 
  93.         /*输入选择*/ 
  94.         printf("/n"); 
  95.         printf("请进行选择:"); 
  96.         scanf("%d",&a); 
  97.         printf("/n/n"); 
  98.         switch(a)                                /*进行选择*/ 
  99.         { 
  100.         case 1:                                  /*插入*/ 
  101.             { 
  102.                 printf("请输入要进行添加信息的学号,姓名,年龄/n"); 
  103.                 node=(NODE *)malloc(NODESIZE); 
  104.                 assert(node!=NULL); 
  105.                 scanf("%s %s %d",node->code,node->name,&node->age); 
  106.                 if(root->lchild==NULL)           /*如果记录为空时*/ 
  107.                 { 
  108.                     temp=(TREE *)malloc(TREESIZE); 
  109.                     assert(temp!=NULL); 
  110.                     temp->rchild=NULL; 
  111.                     temp->lchild=NULL; 
  112.                     temp->student =node; 
  113.                     root->lchild =temp; 
  114.                 } 
  115.                 else                             /*记录不为空*/ 
  116.                 { 
  117.                   Insert_Information(root->lchild,node); /*进行插入*/ 
  118.                 } 
  119.                 printf("/n/n添加成功/n"); 
  120.             }break; 
  121.         case 2:                                  /*浏览*/ 
  122.             { 
  123.                 if(root->lchild ==NULL)          /*为空不能进行浏*/ 
  124.                     printf("记录为空,不能进行浏览!/n"); 
  125.                 else                             /*进行浏览*/ 
  126.                 { 
  127.                    Look_Through_Information(root->lchild); 
  128.                 } 
  129.             }break; 
  130.         case 3:                                  /*保存*/ 
  131.             { 
  132.                 if(root->lchild ==NULL)          /*记录为空不能进行保存*/ 
  133.                     printf("记录为空,不能进行保存!/n"); 
  134.                 else 
  135.                 { 
  136.                    output=fopen("shuwen.txt","w");/*打开文件*/ 
  137.                    Save_Information(root->lchild);        /*进行保存*/ 
  138.                    printf("保存成功!"); 
  139.                    fclose(output);               /*关闭文件*/ 
  140.                 } 
  141.             }break; 
  142.         case 4:                                  /*查寻*/ 
  143.             { 
  144.                 if(root->lchild==NULL)           /*为空不能进行查寻*/ 
  145.                     printf("记录为空,不能进行查寻!/n"); 
  146.                 else 
  147.                 { 
  148.                    printf("请输入你要进行查找的学号:"); 
  149.                    scanf("%s",b); 
  150.                    printf("/n/n"); 
  151.                    if((Find_Information(root->lchild ,b))==0)/*没有找到进行提示*/ 
  152.                      printf("没有找到你要进行查找的记录!/n"); 
  153.                 } 
  154.             }break;  
  155.         case 5:                                  /*修改*/ 
  156.             { 
  157.                 if(root->lchild==NULL)           /*为空不能进行修改*/ 
  158.                     printf("记录为空,不能进行修改!/n"); 
  159.                 else                             /*进行查寻*/ 
  160.                 { 
  161.                    printf("请输入你要进行修改的学号:"); 
  162.                    scanf("%s",b); 
  163.                    printf("/n/n"); 
  164.                    if((Rework_Information(root->lchild ,b))==0)/*没有查寻到提示*/ 
  165.                       printf("没有找到你要进行修改的记录!/n"); 
  166.                 } 
  167.             }break; 
  168.         case 6:                                  /*删除*/ 
  169.             { 
  170.                 if(root->lchild ==NULL)          /*为空不能进行删除*/ 
  171.                     printf("记录为空,不能进行删除"); 
  172.                 else 
  173.                 { 
  174.                    printf("请输入你要进行删除的学号:"); 
  175.                    scanf("%s",b); 
  176.                    Delete_Information(root,b);         /*进行删除*/ 
  177.                 } 
  178.             }break; 
  179.         case 7: exit(0);break; 
  180.         } 
  181.         printf("/n/n"); 
  182.     } 
  183.     Free_EMS_memory(root); 
  184. } 
  185. /**********************************************************************************
  186. *                               菜单函数
  187. *描述:该函数用于对屏幕进行初始化。
  188. *
  189. *参数:  无
  190. *
  191. *返回值:无
  192. *
  193. *注意事项:
  194. **********************************************************************************/ 
  195. void Menu(void ) 
  196. { 
  197.     printf("*************   1 添加  *************/n"); 
  198.     printf("*************   2 浏览  *************/n"); 
  199.     printf("*************   3 保存  *************/n"); 
  200.     printf("*************   4 查寻  *************/n"); 
  201.     printf("*************   5 修改  *************/n"); 
  202.     printf("*************   6 删除  *************/n"); 
  203.     printf("*************   7 结束  *************/n"); 
  204. } 
  205. /**********************************************************************************
  206. *                              创建空二叉树函数
  207. *描述:该函数用于创建空二叉树。
  208. *
  209. *参数:  无
  210. *
  211. *返回值:根结点
  212. *
  213. *注意事项:该结点不进行保存数据。
  214. **********************************************************************************/ 
  215. TREE *Create_Tree(void ) 
  216. { 
  217.     /*根结点不进行保存记录,只用于做为真正的根结点*/ 
  218.     TREE *root; 
  219.     root=(TREE *)malloc(TREESIZE); 
  220.     assert(root !=NULL); 
  221.     root->student=NULL; 
  222.     root->rchild=NULL; 
  223.     root->lchild=NULL; 
  224.     return root; 
  225. } 
  226. /**********************************************************************************
  227. *                               插入个人信息函数
  228. *描述:该函数用于插入个人信息。
  229. *
  230. *参数:  根结点、记录有个人信息的结点
  231. *
  232. *返回值:无
  233. *
  234. *注意事项:
  235. **********************************************************************************/ 
  236. void Insert_Information(TREE *root,NODE *node) 
  237. { 
  238.     TREE *Node; 
  239.     if((strcmp(root->student->code,node->code))>0)/*插入到左子树*/ 
  240.     { 
  241.         if(root->lchild==NULL)                   /*左孩子为空,直接插入*/ 
  242.         { 
  243.             Node=(TREE *)malloc(TREESIZE); 
  244.             assert(Node !=NULL); 
  245.             Node->rchild=NULL; 
  246.             Node->lchild=NULL; 
  247.             Node->student=node; 
  248.             root->lchild=Node; 
  249.         } 
  250.         else                                     /*进行递归插入*/ 
  251.            Insert_Information(root->lchild,node); 
  252.     } 
  253.     else                                         /*插入到右子树*/ 
  254.     { 
  255.         if(root->rchild==NULL)                  /*为空直接插入*/ 
  256.         { 
  257.             Node=(TREE *)malloc(TREESIZE); 
  258.             assert(Node!=NULL); 
  259.             Node->rchild=NULL; 
  260.             Node->lchild=NULL; 
  261.             Node->student=node; 
  262.             root->rchild=Node; 
  263.         } 
  264.         else                                     /*递归插入*/ 
  265.             Insert_Information(root->rchild,node); 
  266.     } 
  267. } 
  268. /**********************************************************************************
  269. *                               浏览函数
  270. *描述:该函数用于进行浏览所有的个人记录。
  271. *
  272. *参数:  根结点
  273. *
  274. *返回值:无
  275. *
  276. *注意事项:
  277. **********************************************************************************/ 
  278. void Look_Through_Information(TREE *root)                        /*中序遍历法输出*/ 
  279. { 
  280.     if(root!=NULL) 
  281.     { 
  282.         Look_Through_Information(root->lchild); 
  283.         printf("%s %s %d/n",root->student->code,root->student->name,root->student->age); 
  284.         Look_Through_Information(root->rchild); 
  285.     } 
  286. } 
  287. /**********************************************************************************
  288. *                               保存函数
  289. *描述:该函数用于将所要进行保存的记录进行保存。
  290. *
  291. *参数:  根结点
  292. *
  293. *返回值:无
  294. *
  295. *注意事项:本处应用前序遍历法进行遍历二叉树,防止再次进行初始化时产生斜树
  296. **********************************************************************************/  
  297. void Save_Information(TREE *root) 
  298. { 
  299.     if(root!=NULL) 
  300.     { 
  301.         fprintf(output,"%s %s %d/n",root->student->code,root->student->name,root->student->age); 
  302.         Save_Information(root->lchild); 
  303.         Save_Information(root->rchild); 
  304.     } 
  305. } 
  306. /**********************************************************************************
  307. *                               查寻函数
  308. *描述:该函数用于进行查寻记录。
  309. *
  310. *参数:  根结点、学号
  311. *
  312. *返回值:是否找到进行查寻的记录
  313. *        1:表找到     0:表没有找到
  314. *
  315. *注意事项:
  316. **********************************************************************************/ 
  317. int Find_Information(TREE *root,char *code) 
  318. { 
  319.     if(root==NULL) 
  320.         return 0; 
  321.     else if((strcmp(root->student ->code ,code))==0)/*找到*/ 
  322.     { 
  323.         printf("找到你要进行查录的记录,记录如下/n"); 
  324.         printf("%s %s %d/n",root->student ->name ,root->student ->code ,root->student ->age ); 
  325.         return 1; 
  326.     } 
  327.     else if((strcmp(root->student ->code ,code))>0)/*在左子树中进行查找*/ 
  328.         Find_Information(root->lchild ,code); 
  329.     else                                         /*在右子树中进行查寻*/ 
  330.         Find_Information(root->rchild,code); 
  331. } 
  332. /**********************************************************************************
  333. *                               修改函数
  334. *描述:该函数用于修改要进行修改的记录。
  335. *
  336. *参数:  根结点、学号
  337. *
  338. *返回值:是否修改成功
  339. *        1:修改成功     0:没有该记录
  340. *
  341. *注意事项:
  342. **********************************************************************************/ 
  343. int Rework_Information(TREE *root,char *code) 
  344. { 
  345.     if(root==NULL)                               /*没有找到要进行修改的结点*/ 
  346.        return 0; 
  347.     else if((strcmp(root->student ->code ,code))==0)/*找到*/ 
  348.     { 
  349.         char name[30]; 
  350.         int age; 
  351.         printf("请输入你要进行修改的姓名,年龄:"); 
  352.         scanf("%s %d",name,&age); 
  353.         /*进行修改*/ 
  354.         root->student ->age =age; 
  355.         strcpy(root->student ->name ,name); 
  356.         printf("修改成功/n"); 
  357.         return 1; 
  358.     } 
  359.     else if((strcmp(root->student ->code ,code))>0)/*在左子树中进行查寻*/ 
  360.         Rework_Information(root->lchild ,code); 
  361.     else                                         /*在右子树中进行查寻*/ 
  362.        Rework_Information(root->rchild ,code); 
  363. } 
  364. /**********************************************************************************
  365. *                               查寻要进删除结点的双亲结点
  366. *描述:该函数用于查寻将要进行删除结点的双亲结点。
  367. *
  368. *参数:  根结点、学号
  369. *
  370. *返回值:双亲结点
  371. *
  372. *注意事项:
  373. **********************************************************************************/ 
  374. TREE *Find_Father_Node(TREE *root,char *code) 
  375. { 
  376.     if(root->rchild==NULL && root->lchild==NULL) /*没有找到*/ 
  377.         return NULL; 
  378.     else if((root->lchild!=NULL)&&((strcmp(root->lchild->student ->code,code))==0))/*找到为左结点*/ 
  379.         return root; 
  380.     else if((root->rchild!=NULL) &&((strcmp(root->rchild->student ->code,code))==0))/*找到为右结点*/ 
  381.         return root; 
  382.     else 
  383.     { 
  384.         if((root->lchild!=NULL) &&((strcmp(root->student ->code,code))>0))/*在左子树中进行查寻*/ 
  385.             return (Find_Father_Node(root->lchild,code)); 
  386.         else if((root->rchild!=NULL) &&((strcmp(root ->rchild->student ->code,code))<0))/*在右子树中进行查寻*/ 
  387.             return (Find_Father_Node(root->rchild,code)); 
  388.         else 
  389.             return NULL; 
  390.     } 
  391. } 
  392. /**********************************************************************************
  393. *                               删除个人记录
  394. *描述:该函数用于删除个人记录。
  395. *
  396. *参数:  根结点、学号
  397. *
  398. *返回值:无
  399. *
  400. *注意事项:
  401. **********************************************************************************/ 
  402. void Delete_Information(TREE *root,char *code) 
  403. { 
  404.     TREE *node; 
  405.     TREE *per; 
  406.     TREE *p; 
  407.     TREE *s;  
  408.     if((strcmp(root->lchild ->student ->code ,code))==0)                          /*是根结点情况*/ 
  409.     { 
  410.         if(root->lchild ->lchild ==NULL && root->lchild ->rchild  ==NULL) 
  411.         { 
  412.             node=root->lchild ; 
  413.             root->lchild =NULL; 
  414.             free(node); 
  415.         } 
  416.         else if(root->lchild ->lchild ==NULL && root->lchild ->rchild !=NULL) 
  417.         { 
  418.             node=root->rchild ; 
  419.             root->lchild=root->lchild ->rchild ; 
  420.             free(node); 
  421.         } 
  422.         else if(root->lchild ->rchild ==NULL && root->lchild ->lchild !=NULL) 
  423.         { 
  424.             node=root->lchild ; 
  425.             root->lchild=root->lchild ->lchild ; 
  426.             free(node); 
  427.         } 
  428.         else 
  429.         { 
  430.             node=root->lchild ; 
  431.             s=node ->rchild ; 
  432.             if(s->lchild ==NULL) 
  433.                 node->rchild =s->rchild ; 
  434.             else 
  435.             { 
  436.               per=node; 
  437.               while(s->lchild !=NULL) 
  438.               { 
  439.                per=s; 
  440.                s=s->lchild ; 
  441.               } 
  442.               per->lchild =s->rchild ; 
  443.             } 
  444.             node->student  =s->student ;  
  445.             free(s); 
  446.         } 
  447.         printf("删除成功!"); 
  448.     } 
  449.     else 
  450.     { 
  451.         node=Find_Father_Node(root->lchild ,code);                 /*得到要进行删除结点的父结点*/ 
  452.         if(node==NULL)                                     /*没有找到*/ 
  453.             printf("没有找到你要进行删除的数据!/n"); 
  454.         else 
  455.         { 
  456.             if(node->lchild!=NULL && (strcmp(node->lchild->student ->code,code))==0)/*在父结点的左子树*/ 
  457.             { 
  458.                 p=node->lchild; 
  459.                 if(p->lchild ==NULL && p->rchild ==NULL)/*叶子情况*/ 
  460.                 { 
  461.                     node->lchild=NULL; 
  462.                     free(p); 
  463.                 } 
  464.                 else if(p->lchild !=NULL && p->rchild ==NULL)/*只有左孩子*/ 
  465.                 { 
  466.                     node->lchild =p->lchild ; 
  467.                     free(p); 
  468.                 } 
  469.                 else if(p->rchild !=NULL && p->lchild ==NULL)/*只有右孩子*/ 
  470.                 { 
  471.                     node->lchild =p->rchild ; 
  472.                     free(p); 
  473.                 } 
  474.                 else                                      /*有左右孩子*/ 
  475.                 { 
  476.                     per=p; 
  477.                     s=p->rchild ; 
  478.                     while(s->lchild !=NULL) 
  479.                     { 
  480.                         per=s; 
  481.                         s=s->lchild ; 
  482.                     } 
  483.                     p->student  =s->student ; 
  484.                     if(per==s) 
  485.                         per->rchild =s->rchild ; 
  486.                     else 
  487.                         per->lchild =s->rchild ; 
  488.                     free(s); 
  489.                 }  
  490.             } 
  491.             else                                 /*在右子树*/ 
  492.             { 
  493.                 p=node->rchild; 
  494.                 if(p->lchild ==NULL && p->rchild ==NULL) 
  495.                 { 
  496.                     node->rchild=NULL; 
  497.                     free(p); 
  498.                 } 
  499.                 else if(p->lchild !=NULL && p->rchild ==NULL) 
  500.                 { 
  501.                     node->rchild =p->lchild ; 
  502.                     free(p); 
  503.                 } 
  504.                 else if(p->rchild !=NULL && p->lchild ==NULL) 
  505.                 { 
  506.                     node->rchild =p->rchild ; 
  507.                     free(p); 
  508.                 } 
  509.                 else 
  510.                 { 
  511.                     per=p; 
  512.                     s=p->rchild ; 
  513.                     while(s->lchild !=NULL) 
  514.                     { 
  515.                         per=s; 
  516.                         s=s->lchild ; 
  517.                     } 
  518.                     p->student  =s->student  ; 
  519.                     if(per==s) 
  520.                         per->rchild =s->rchild ; 
  521.                     else 
  522.                         per->lchild =s->rchild ; 
  523.                     free(s); 
  524.                 }  
  525.             }  
  526.             printf("删除成功!");  
  527.         } 
  528.     } 
  529. } 
  530. /**********************************************************************************
  531. *                              释放内存函数
  532. *描述:该函数用于释放内存。
  533. *
  534. *参数:  根结点
  535. *
  536. *返回值:无
  537. *
  538. *注意事项:
  539. **********************************************************************************/ 
  540. void Free_EMS_memory(TREE *root) 
  541. { 
  542.     if(root!=NULL) 
  543.     { 
  544.         Free_EMS_memory(root->lchild); 
  545.         Free_EMS_memory(root->rchild); 
  546.         free(root); 
  547.     } 
  548. } 

二叉排序树问题 数据结构课设要求说明书,里面有要求,查阅的相关书籍 立即下载

相关推荐

SPI模式下的SD卡读写,为什么你的数据总出错?详解时序与状态机避坑指南

本文深入探讨SPI模式下SD卡读写数据出错的根本原因,提供时序优化与状态机设计的实战指南。针对时钟周期计数、状态机跳转和忙检测等核心问题,详解命令时序细节、状态机同步策略及高级避坑技巧,帮助开发者提升SD卡在SPI模式下的稳定性和性能。

weixin_30514745的博客 261

【数据结构】-二叉树的应用(二叉排序树)

二叉排序树BST1.头文件及类型定义2.二叉排序树结点类型定义3.函数声明4.基本操作4.1 查找操作4.1.1 非递归查找4.1.2 递归查找4.2 插入操作4.2.1 非递归插入4.2.2 递归插入4.3 构造二叉排序树4.4 删除操作4.4.1 寻找最左下结点4.4.2 寻找最右下结点4.4.3 删除操作-用右子树中最左下结点填充4.4.4 删除操作-用左子树中最右下结点填充4.5 中序遍历4.6 main函数4.7 测试结果5.小结 1.头文件及类型定义 #include<stdio.h&gt

RunningSnail的博客 3432

onnxruntime-gpu版本选择与CUDA环境配置实战指南

本文是onnxruntime-gpu版本选择与CUDA环境配置的实战指南。针对AI模型部署中常见的GPU无法调用问题,核心在于确保onnxruntime-gpu版本与系统CUDA Toolkit版本严格匹配。文章详细讲解了如何精准确定CUDA版本、查找官方对应关系、执行正确安装命令,并通过完整测试脚本验证GPU是否成功启用,最后提供了常见问题排查与生产环境调优建议。

weixin_29164091的博客 522

数据结构基础之二叉排序树的应用

设计算法以构造有n个元素(下标范围从1到n)的二分查找判定树 void bstFromArr(btNode *&T, elementType A[],int low, int high){ int mid; //先应用二叉查找的算法 if (low < high){ mid = (low + high) / 2; T = new btNode; T->data = A[mid]; T->lChild = NULL; T->rChild

明净止水以澄心的博客 1257

KV260-从开箱到人脸识别(小白入门)

波特率选择115200,数据为8位,停止位1位,无奇偶校验,点击链接即可完成通讯。空白的盘格式化之后及进行挂载,这时会被我们的操作系统接手管理,这时就具有了操作系统的属性,复制文件就是在操作系统下的文件系统基础上进行的操作,这个过程是相对的地址进行操作,因此,复制文件是在操作系统环境下完成的更高级的操作模式。空白的盘相当于一整块空白的存储单元,因为没有格式化也不具有文件系统的属性,只有当外部的硬件或者软件写进空白的区域,这种方式是对绝对物理地址进行的操作,因此,烧录文件是独立于操作系统的更低级的写入方式。

qq_53252845的博客 3814

Unity UGUI高斯模糊背景效果 简易解决方案

UnityUI背景模糊效果简易解决方案1.功能描述简易界面框架搭建合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 1.功能描述 在我们玩游戏的时候,经常会看到一些游戏会对UI做这样的处理: 可以看到,新开的上层UI界面会以下层UI界面的模糊

SaberZG的博客 1万+

数据结构-二叉查找树的应用

中序遍历inorder traversal是指按照先左节点,再根节点,最后右节点的次序访问二叉树中所有的节点,使得每个节点被访问且仅被访问一次。二叉排序树:即一个二叉树,它的每一个结点的左孩子的data值比当前结点的data值小,而右孩子结点的data值比当前结点的data值大。依次将后面的无序序列依次插入二叉排序树,若比根节点值小,则递归插入左子树,否则递归插入右子树。平台将自动编译补全后的代码,并生成若干组测试数据,接着根据程序的输出判断程序是否正确。在InOrder中,实现二叉排序树的中序遍历。

2301_77225918的博客 993

详解如何用爬虫工具批量采集阿里巴巴批发网商品数据

本文主要介绍如何使用后羿采集器的智能模式,免费采集阿里巴巴批发网商品的批发价格、发货时间、是否代发等信息。 采集字段: 商品标题、商品链接、图片链接、标签1、标签2、标签3、价格、30天成交数、 评价、店铺 功能点目录: 如何对采集字段进行配置 如何采集列表+详情页类型网页 采集结果预览: 下面我们来详细介绍一下如何免费采集1688批发网的商品数据,我们以“羽绒服女”为例,具体步骤如下: 步骤一...

weixin_43777427的博客 1万+

头歌数据结构实训参考---二叉查找搜索树的应用

【代码】头歌数据结构实训参考---二叉查找搜索树的应用。

m0_73938966的博客 940

Windows下用RKDevTool解包update.img的完整流程(含常见错误排查)

本文详细介绍了在Windows系统下使用RKDevTool工具解包update.img固件的完整流程。从工具准备、环境搭建到逐步解包操作,重点解析了输出文件结构,并提供了修改分区后重新打包的实战方法。文章还针对解包失败、打包错误等常见问题提供了详细的排查与解决方案,旨在帮助嵌入式开发者和爱好者高效完成固件分析与定制工作。

aa123的博客 715

在 SAP 资产模块跨 2024 和 2025 两个年度操作后,运行 AFAB 测试无数据,大概率是折旧已完全过账、跨期配置异常或资产数据异常等原因

SAP资产模块跨年度操作AFAB测试无数据的排查方案:首先检查折旧是否已完全计提,确认资产主数据价值;其次验证跨年度配置是否合规,包括全局配置、折旧范围和账期状态;然后重新执行AFAR折旧计算刷新数据;排查资产主数据异常或业务操作冲突;最后核对AFAB运行参数是否正确设置,包括会计年度、期间范围和运行模式等。

金牌架构师 865

【数据结构】(二叉树)二叉树删除结点值为x的子树

删除结点值为x的子树 方法一递归:

你好丶下一秒 2万+

Unity GameObject 核心机制深度解析:从底层结构到工程实践

从底层机制讲透 Unity GameObject:托管壳加原生芯的双层对象模型如何制造假 null 陷阱、Transform 层级与组件通信的原理、生命周期回调的确切顺序。文章同时给出 Instantiate 成本分析与对象池等高频场景的工程实践。

游戏人生 40

一个简单的个人通讯录(基于二叉排序树)(加注释版~~~~)

TreeNode.h: /********************************************************************************** * 基于二叉排序树的个人通信录 * * * * * * 文 件: Treenode.h * 作 者: 邹亚鹏 * 部 门: 南京工程学...

yuanlanjun 1191

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

基于二叉排序树的个人通信录

长沙理工大学/********************定义个人记录结构**********************/typedef struct Node{char name[30]; /*用于保存姓名*/char code[30]; /*用于保存学号*/int age; /*用于保年龄*/}NODE;/************************定义二叉树结构体**************...

guoyiqi 779

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

《数据结构》第七章 查找学习指南

 第七章  查找 学习指南       本书的前几章,讲完了几种数据结构的存储和常规操作实现。本章节专门讨论一查找技术。       查找操作在生产生活中常见,如搜索引擎,在自己个人通信录中查找一个电话号码等。 一、学习目的         本章学习,在前面的各种数据结构知识基础上,讨论几种查找结构的查找技术。 二、学习目标       本章节学习目标,具体地

明哥的专栏 1530

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

二叉排序树(BST)的概念及其基本操作详细教程(C++)

二叉排序树的概念及其相关操作详细教程

smart_jackli的博客 1424

数据结构之树的应用梳理(一)二叉排序树

一、二叉排序树二叉排序树也称二叉查找树,是学习数据结构树的第一步,其主要性质如下: (1)若左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值; (2)若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值; (3)左、右子树也分别为二叉排序树 (4)无等值节点对二叉排序树的操作包括: 1.树的创建(节点插入) 2.树的遍历(前序,中序,后序) 3.树中节点的删除树的

SuperFierceBigKK的博客 1050

二叉排序树的应用

问题描述:    利用二叉排序树对顺序表进行排序。 基本要求:    (1)生成一个顺序表L;    (2)对所生成的顺序表L构造二叉排序树;    (3)利用栈结构实现中序遍历二叉排序树;    (4)中序遍历所构造的二叉排序树将记录由小到大输出。 测试数据:     用伪随机数产生程序产生,表长不小于20。 选作内容:    实现二叉排序树的插入和删除操

ccsu_wyw的专栏 3317

二叉树的应用——二叉排序树、选择树、判定树

堆

筱羊冰冰 6311

删除二叉树的子树:递归算法删除根结点值为x的子树

对于当前节点,依次递归删除其左子树和右子树中值为子树根节点值的子树。如果当前节点为空或者当前节点的值不等于子树根节点的值,则直接返回当前节点的指针。如果当前节点的左子树或右子树中存在值为子树根节点的节点,则将该节点的左子树或右子树置为空,并释放该节点的空间。根据输入的节点值创建二叉树根据用户输入的节点值(-1表示空节点),使用递归的方式创建二叉树。用户输入要删除的子树的根节点的值,程序在二叉树中查找值为该值的节点,并返回该节点的指针。使用中序遍历的方式遍历二叉树,输出删除子树后的节点值序列。

m0_62550609的博客 1695

二叉排序树实现简单的通讯录

头文件#ifndef TOU_H_INCLUDED #define TOU_H_INCLUDED #include<stdio.h> #include<stdlib.h> #include<iostream> using namespace std; typedef struct { char Name[20]; char PhoneNumber[20]; char Adre

蜕变中的Programmer 1845
上一篇: 写给想成为Linux 高手的人们
下一篇: 基于二叉排序树写的通讯录
zhouxf_cn
博客等级 码龄14年 54粉丝 24原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值