我们亲爱的项目经理真是有创意,他说你给我写得二叉树挺好的;

功能还算可以:插入节点,能够删除节点;

可是有时候我们只是需要查找树的某个节点是否存在;

所以我希望你能够给我一个find功能;

还有就是,我在跟BOSS交流的时候,他根本不相信你已经把链表写成树的结构啦;

他希望你能够更明显的把树的结构打印出来;

所以,你需要实现一个show功能;

这应该不难吧;

Problem

我们需要实现的其实是遍历的两个变体;

首先确定我们的思路,想到都是需要遍历的;

那么我们是不是又想到了有递归的方式和非递归的方式呢;

  1. int find_recursive(Node *root, int data)
  2. {
  3. //TODO
  4. }

我们首先实现的是递归的,大致的结构应该是这样的;

还记得吗?递归的前面几行一般是递归的结束条件;

因此,我们的代码应该是这样的:

  1. int find_recursive(Node *root, int data)
  2. {
  3. if(root == NULL)
  4. return ;
  5. }

其次,我们应当考虑找到目标的时候,应该是怎么确定的呢?

应该是root->data 与参数data相等的时候,我们希望程序返回啦;

因此,我们需要的代码可能会是这样的;

  1. int find_recursive(Node *root, int data)
  2. {
  3. if(root == NULL){
  4. return ;
  5. }else if(root->data == data){
  6. return ;
  7. }
  8. }

那,在当前的节点上如果没有找到目标呢;

我们需要的应该是确定往左找还是往右找;

所以需要把代码写成如下的形式;

  1. int find_recursive(Node *root, int data)
  2. {
  3. if(root == NULL){
  4. return ;
  5. }else if(root->data == data){
  6. return ;
  7. }else{
  8. int dir = root->data < data;
  9. return find_recursive(root->link[dir],data);
  10. }
  11. }

dir的值只能是0或者1,代表的意义是什么大家应该很清楚啦;

它的作用是什么也应该很清楚啦;

最后执行递归;

通常我们需要客户操作的是树,因此我们需要一个包装函数;

  1. int find(Tree *tree,int data)
  2. {
  3. return find_recursive(tree->root,data);
  4. }

好啦,我们可以测试一下啦;

我首先把需要用到得代码附上;

  1. #include <stdio.h>
    #include <stdlib.h>
  2. #include <time.h>
  3. typedef struct _node {
  4. int data;
  5. struct _node *link[];
  6. }Node;
  7. typedef struct _tree{
  8. struct _node *root;
  9. }Tree;
  10. Tree * init_tree()
  11. {
  12. Tree *temp = (Tree*)malloc(sizeof(Tree));
  13. temp->root = NULL;
  14. return temp;
  15. }
  16. Node * make_node(int data)
  17. {
  18. Node *temp = (Node*)malloc(sizeof(Node));
  19. temp->link[] = temp->link[] = NULL;
  20. temp->data = data;
  21. return temp;
  22. }
  23. int insert(Tree *tree, int data)
  24. {
  25. if(tree->root == NULL){
  26. tree->root = make_node(data);
  27. }else{
  28. Node * it = tree->root;
  29. int dir ;
  30. for(;;){
  31. dir = it->data < data;
  32. if(it->data == data){
  33. return ;
  34. }else if(it->link[dir] == NULL){
  35. break;
  36. }
  37. it = it->link[dir];
  38. }
  39. it->link[dir] = make_node(data);
  40. }
  41. return ;
  42. }

测试主函数代码如下:

  1. int main(void)
  2. {
  3. Tree * tree = init_tree();
  4. insert(tree,);
  5. insert(tree,);
  6. insert(tree,);
  7. insert(tree,);
  8. printf("looking for %d...%s\n",,find(tree,) ? "Got it":"Not exist");
  9. printf("looking for %d...%s\n",,find(tree,) ? "Got it":"Not exist");
  10. return ;
  11. }

运行结果如下:

好啦!可能对于客户来说,这样把查询的数据写死啦,并把那么好;

别人可能想查某个数据就输入某个数据,可能更实用;

这是非常简单的功能,我不会去讲解,但是也附上一份简单的实现;

大家写的肯的能够更加漂亮;

  1. void tips(){
  2. time_t curTime;
  3. struct tm *ts;
  4. time_t testTime = time(&curTime);
  5. ts = localtime(&curTime);
  6. //struct tm *tsgm = gmtime(&curTime);
  7. puts("*************************************************************");
  8. printf("Date:%s",asctime(ts));
  9. puts("Please input right cmd");
  10. puts("1)Search");
  11. puts("2)Quit");
  12. puts("*************************************************************");
  13. }
  14.  
  15. int search(Tree *tree)
  16. {
  17. char cmd;
  18. int isExist;
  19. int target;
  20. tips();
  21. while((cmd=getchar())!=EOF){
  22. if(cmd==''){
  23. puts("-------------------------------------------------------------");
  24. printf("Please input the target:");
  25. scanf("%d",&target);
  26. isExist=find(tree,target);
  27. if(isExist){
  28. printf("Target %d is exists \n",target);
  29. puts("-------------------------------------------------------------");
  30. puts("\n");
  31. continue;
  32. //break;
  33. }else{
  34. puts("Target Not exitst");
  35. puts("-------------------------------------------------------------");
  36. puts("\n");
  37. continue;
  38. //break;
  39. }
  40. }else if(cmd==''){
  41. puts("bye~");
  42. break;
  43. }else{
  44. tips();
  45. }
  46. }
  47. return ;
  48. }

运行结果如下:

这个可能用户体验要较好些;

注意别忘记包涵头文件time.h

好啦查询工作算是完成啦;

接下来是下一个任务;

Problem

为啦更加形象的表明我们一直在写得是一棵树;

我想有必要show也就是秀秀我们的成果啦;

这次咱们先看要实现的效果,如下图;

我们的树根就是8,而~符合代表就是叶子啦;

这样旋转90°的树可能你不一定喜欢;

但是,如果你想再旋转90度的话你就自己想想吧;

好啦,接下来就是实现啦;

不管它咱们显示,咱们始终记住,我们需要遍历;

为简单,我们使用递归实现;

  1. void structure_recursive(Node *root,int level)
  2. {
  3. if(root == NULL){
  4. //TODO
  5. }else{
  6. //TODO;
  7. }
  8. }

这个遍历方式结构就怎么简单;

但是请思考思考,我们的输出到终端上得数据是先大的,然后是小的;

显然是只有中序遍历才能得到按正确的大小顺序输出;

所以我们需要记住这点哈;

  1. void structure_recursive(Node *root,int level)
  2. {
  3. if(root == NULL){
  4. //TODO
  5. }else{
  6. structure_recursive(root->link[],level + );
  7. printf("%d\n",root->data);
  8. structure_recursive(root->link[],level + );
  9. }
  10. }

你会发现,我首先写else部分,仔细看看else部分你会发现我们的中序遍历很明显啦;

可是呢!!它又有别于我们前面写得中序遍历方式,我们首先从右子树下手啦;

以前都是从左子树的,这就是为什么我们输出的结果是从大到小往下的啦;

好啦!TODO到底应该写成什么样子呢?

想想要是我们一直递归到最后要是递归一次我们就得增加一个level的计数;

到最后发现叶子是NULL我们就直接输出level个tab然后跟一个~表示叶子;

所以代码如下:

  1. void structure_recursive(Node *root,int level)
  2. {
       int i;
  3. if(root == NULL){
  4. for(i = ;i<level;i++){
  5. putchar('\t');
  6. }
  7. puts("~");
  8. }else{
  9. structure_recursive(root->link[],level + );
  10. printf("%d\n",root->data);
  11. structure_recursive(root->link[],level + );
  12. }
  13. }

这里已经差不多完事啦,但是我们先去写一个包装函数;

  1. void structure(Tree *tree)
  2. {
  3. structure_recursive(tree->root,);
  4. }

注意包装函数里面的0表示是从最左边开始打印的;

我们先不去完善我们的structure_recursive函数,我们直接测试,看看结果;

这个可不是我们想看到的结果哈;

原因是什么呢;

我们还没有完善我们的函数呢;

  1. void structure_recursive(Node *root,int level)
  2. {
  3. int i;
  4. if(root == NULL){
  5. for(i = ;i<level;i++){
  6. putchar('\t');
  7. }
  8. puts("~");
  9. }else{
  10. structure_recursive(root->link[],level + );
  11. for(i = ;i < level;i++){
  12. putchar('\t');
  13. }
  14. printf("%d\n",root->data);
  15. structure_recursive(root->link[],level + );
  16. }
  17. }

好啦,我们的效果出来啦;

好啦!工作完成啦;

总结一下吧;

不,还没有到总结的时候;

明天的任务还有呢:

我们的树不能一直老想着用递归实现,在很多时候它是受限制的;

递归对空间要求特别多,所以我们下次想想有没有非递归的方法实现其他的函数;

最后附上我们今天所有代码吧:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4.  
  5. typedef struct _node {
  6. int data;
  7. struct _node *link[];
  8. }Node;
  9.  
  10. typedef struct _tree{
  11. struct _node *root;
  12. }Tree;
  13.  
  14. Tree * init_tree()
  15. {
  16. Tree *temp = (Tree*)malloc(sizeof(Tree));
  17. temp->root = NULL;
  18. return temp;
  19. }
  20.  
  21. Node * make_node(int data)
  22. {
  23. Node *temp = (Node*)malloc(sizeof(Node));
  24. temp->link[] = temp->link[] = NULL;
  25. temp->data = data;
  26. return temp;
  27. }
  28.  
  29. int insert(Tree *tree, int data)
  30. {
  31. if(tree->root == NULL){
  32. tree->root = make_node(data);
  33. }else{
  34. Node * it = tree->root;
  35. int dir ;
  36. for(;;){
  37. dir = it->data < data;
  38. if(it->data == data){
  39. return ;
  40. }else if(it->link[dir] == NULL){
  41. break;
  42. }
  43. it = it->link[dir];
  44. }
  45. it->link[dir] = make_node(data);
  46. }
  47. return ;
  48. }
  49. int remove_node(Tree *tree, int data)
  50. {
  51. if(tree->root != NULL)
  52. {
  53. Node *p = NULL;
  54. Node *succ;
  55. Node *it = tree->root;
  56. int dir;
  57. for(;;){
  58. if( it == NULL){
  59. return ;
  60. }else if(it->data == data){
  61. break;
  62. }
  63. dir = it->data < data;
  64. p = it;
  65. it = it->link[dir];
  66. }
  67. /***********************************************************************/
  68.  
  69. if(it->link[] != NULL && it->link[] != NULL){
  70. p = it;
  71. succ = it->link[];
  72. while(succ->link[] != NULL){
  73. p = succ;
  74. succ = succ->link[];
  75. }
  76. it->data = succ->data;
  77. p->link[p->link[] == succ] = succ->link[];
  78. free(succ);
  79. /***********************************************************************/
  80. }else{ /*it->link[0] == NULL || it->link[1] == NULL */
  81. dir = it->link[] == NULL;
  82. if( p == NULL){
  83. tree->root = it->link[dir];
  84. }else{
  85. p->link[p->link[] == it] = it->link[dir];
  86. }
  87. free(it);
  88. }
  89. }
  90.  
  91. return ;
  92. }
  93. int find_recursive(Node *root, int data)
  94. {
  95. if(root == NULL){
  96. return ;
  97. }else if(root->data == data){
  98. return ;
  99. }else{
  100. int dir = root->data < data;
  101. return find_recursive(root->link[dir],data);
  102. }
  103. }
  104.  
  105. int find(Tree *tree,int data)
  106. {
  107. return find_recursive(tree->root,data);
  108. }
  109.  
  110. void tips(){
  111. time_t curTime;
  112. struct tm *ts;
  113. time_t testTime = time(&curTime);
  114. ts = localtime(&curTime);
  115. //struct tm *tsgm = gmtime(&curTime);
  116. puts("*************************************************************");
  117. printf("Date:%s",asctime(ts));
  118. puts("Please input right cmd");
  119. puts("1)Search");
  120. puts("2)Quit");
  121. puts("*************************************************************");
  122. }
  123. int search(Tree *tree)
  124. {
  125. char cmd;
  126. int isExist;
  127. int target;
  128. tips();
  129. while((cmd=getchar())!=EOF){
  130. if(cmd==''){
  131. puts("-------------------------------------------------------------");
  132. printf("Please input the target:");
  133. scanf("%d",&target);
  134. isExist=find(tree,target);
  135. if(isExist){
  136. printf("Target %d is exists \n",target);
  137. puts("-------------------------------------------------------------");
  138. puts("\n");
  139. continue;
  140. //break;
  141. }else{
  142. puts("Target Not exitst");
  143. puts("-------------------------------------------------------------");
  144. puts("\n");
  145. continue;
  146. //break;
  147. }
  148. }else if(cmd==''){
  149. puts("bye~");
  150. break;
  151. }else{
  152. tips();
  153. }
  154. }
  155. return ;
  156. }
  157.  
  158. void structure_recursive(Node *root,int level)
  159. {
  160. int i;
  161. if(root == NULL){
  162. for(i = ;i<level;i++){
  163. putchar('\t');
  164. }
  165. puts("~");
  166. }else{
  167. structure_recursive(root->link[],level + );
  168. for(i = ;i < level;i++){
  169. putchar('\t');
  170. }
  171. printf("%d\n",root->data);
  172. structure_recursive(root->link[],level + );
  173. }
  174. }
  175.  
  176. void structure_recursive(Node *root,int level)
  177. {
  178. int i;
  179. if(root == NULL){
  180. for(i = ;i<level;i++){
  181. putchar('\t');
  182. }
  183. puts("~");
  184. }else{
  185. structure_recursive(root->link[],level + );
  186. for(i = ;i < level;i++){
  187. putchar('\t');
  188. }
  189. printf("%d\n",root->data);
  190. structure_recursive(root->link[],level + );
  191. }
  192. }
  193.  
  194. void structure(Tree *tree)
  195. {
  196. structure_recursive(tree->root,);
  197. }
  198.  
  199. int main(void)
  200. {
  201. Tree * tree = init_tree();
  202. insert(tree,);
  203. insert(tree,);
  204. insert(tree,);
  205. insert(tree,);
  206. insert(tree,);
  207. insert(tree,);
  208. structure(tree);
  209. return ;
  210. }

C语言实现二叉树-03版的更多相关文章

  1. C语言实现二叉树-02版

    ---恢复内容开始--- 昨天,提交完我们的二叉树项目后,今天早上项目经理早早给我打电话: 他说,小伙子干的不错.但是为什么你上面的insert是recusive的呢? 你难道不知道万一数据量大啦!那 ...

  2. C语言实现二叉树-04版

    二叉树,通常应当是研究其他一些复杂的数据结构的基础.因此,通常我们应该精通它,而不是了解:当然,可能并不是每个人都认同这种观点,甚至有些人认为理解数据结构就行了!根本没有必要去研究如何实现,因为大多数 ...

  3. C语言实现二叉树-01版

    故事是这样开始的,项目经理有一天终于还是拍拍我肩膀说: 无论你的链表写得多么的好,无论是多么的灵活,我也得费老半天才查找到想要的数据: 这让我的工作非常苦恼,听说有一种叫做二叉树的数据结构,你看能不能 ...

  4. 数据结构与抽象 Java语言描述 第4版 pdf (内含标签)

    数据结构与抽象 Java语言描述 第4版 目录 前言引言组织数据序言设计类P.1封装P.2说明方法P.2.1注释P.2.2前置条件和后置条件P.2.3断言P.3Java接口P.3.1写一个接口P.3. ...

  5. C语言实现二叉树-利用二叉树统计单词数目

    昨天刚参加了腾讯2015年在线模拟考: 四道大题的第一题就是单词统计程序的设计思想: 为了记住这一天,我打算今天通过代码实现一下: 我将用到的核心数据结构是二叉树: (要是想了解简单二叉树的实现,可以 ...

  6. 《C++程序设计语言(英文第四版)》【PDF】下载

    <C++程序设计语言(英文第四版)>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230382177 内容简介 本书是C++领域经典的参 ...

  7. Rust语言之HelloWorld Web版

    Rust语言之HelloWorld Web版 下面这篇文章值得仔细研读: http://arthurtw.github.io/2014/12/21/rust-anti-sloppy-programmi ...

  8. | C语言I作业03

    | C语言I作业03 标签: 18软件 李煦亮 问题 答案 这个作业属于那个课程 C语言程序设计I 这个作业要求在哪里 https://edu.cnblogs.com 我在这个课程的目标是 学会和掌握 ...

  9. R语言实战(第二版)-part 1笔记

    说明: 1.本笔记对<R语言实战>一书有选择性的进行记录,仅用于个人的查漏补缺 2.将完全掌握的以及无实战需求的知识点略去 3.代码直接在Rsudio中运行学习 R语言实战(第二版) pa ...

随机推荐

  1. 处理BOM

    [处理BOM]

  2. php 学习使用

    https://netbeans.org/kb/docs/php/wish-list-lesson1_zh_CN.html#register-mysql http://www.php100.com/h ...

  3. jQuery的append和appendTo

    这两个关键词,Insus.NET刚开始学习jQuery时,也被它弄得不好理解.现用得多了,运行与理解也不难了. 查了英文词典append的意思是“添加,附加”: 而后者appendTo意思是“ 添加至 ...

  4. 使用 RecyclerView

    使用 RecyclerView android RecyclerView tutorial 概述 与 ListView 的对比 RecyclerView 的组件 LayoutManager Recyc ...

  5. C# 程序间通信的各种途径及解析

    一.开篇 程序间通信的主要目的是实现多台计算机(也可以是同一台)中应用程序之间的数据共享与信息交换.在不同的计算机系统中,它们之间要通过网络之间的协议才能 实现数据共享与信息交换:在同一台计算机系统中 ...

  6. [刘阳Java]_Java程序员的成长路线_第3讲

    按照Java从业人员的职位晋升来说,Java程序成长路线大致如下 Java程序员 JavaEE初级软件工程师 JavaEE中级软件工程师 JavaEE高级软件工程师 Java架构师 按照职业发展方向, ...

  7. js 运算符优先级

    在看jquery源码,仔细看入口函数的时候,有点懵了.看到与或.多重三目,傻傻的分不清,就代码仔细的区分下运算符优先级,以前都是呼呼的飘过.看来任何一个细节都不能忽略,不然效率极低.. !functi ...

  8. protocol buffers的使用示例[z]

    [http://blog.csdn.net/zhu_xun/article/details/19397081] protocol buffers的使用示例 如果不了解protocol buffers, ...

  9. Samba服务器搭建配置

    本次环境: 服务端-centos6.8-192.168.2.200 客户端1-centos6.8-192.168.2.201 客户端2-Windows7-192.168.2.104 假设条件如下: 使 ...

  10. Having关键字

    Having关键字:用于对整组整组地过滤(对比,where仅仅是一行一行地过滤.) 查询每个住址各住多少人? 查询住址的会员人数超过2人的住址. 注意,出现顺序where>group by> ...