二叉树学习之二叉查找树 http://blog.csdn.net/callinglove/article/details/40707449

来源:互联网 发布:java分销微商城源码 编辑:程序博客网 时间:2024/06/06 04:00
 

二叉树学习之二叉查找树

标签: 二叉树二叉树图形化二叉查找树二叉树递归遍历
 1441人阅读 评论(0) 收藏 举报
 分类:
 

目录(?)[+]

写在前面的话

最近接到几个大学同学研究生毕业不是签华为就是签百度,本人取经得到:操作系统、数据结构与算法、网络编程与数据库是面试中利器。想想自己工作2.5年月薪还不到10K,过着苦逼的码农生活,而他们一出校门就是大放光芒(最起码进入的公司就让人觉得牛逼哄哄的).本人痛定思痛,决定下大功夫学习一下数据结构与算法,我想这应该是根本吧.
之前也看过数据结构,但是一看到那乱七八糟的关系,就觉得还是研究一下别的东西,结果就是好多东西都是浅尝辄止,知子皮毛.
本人只贴出学习过程中的代码,以及一些发杂算法函数的详细注释,还有就是学习过程中遇到过的好的讲解URL,以供自己理解和后续的复习巩固,有不对的地方还需指正.

学习二叉树之前总感觉很抽象,最近看到亚嵌一个关于红黑树讲解的视频用到一个命令,能够将二叉树转换成图形打印出来,感觉很神奇,这个工具在Linux C编程一站式学习 中有提到过,
http://www.essex.ac.uk/linguistics/external/clmt/latex4ling/trees/tree/
有关应用会在后面代码测试中有提到,我想这应该是学习二叉树的一大利器,在此提出来。

源码

binarytree.h
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #ifndef BINARYTREE_H  
  2. #define BINARYTREE_H  
  3.   
  4. typedef struct node *link;  
  5. /** 
  6.  *节点中的数据类型重定义 
  7.  */  
  8. typedef unsigned char TElemType;  
  9.   
  10. struct node {   
  11.     TElemType item;   
  12.     link lchild, rchild;  
  13. };  
  14.   
  15. link init(TElemType VLR[], TElemType LVR[], int n);  
  16.   
  17. void pre_order(link t, void (*visit)(link));  
  18. void in_order(link t, void (*visit)(link));  
  19. void post_order(link t, void (*visit)(link));  
  20. void pprint(link t);  
  21. int count(link t);  
  22. int depth(link t);  
  23. void destroy(link t);  
  24.   
  25.   
  26. /** 
  27. *http://www.cnblogs.com/bizhu/archive/2012/08/19/2646328.html 算法图解 
  28. * 
  29. *二叉排序树(Binary Sort Tree)又称二叉查找树(Binary Search Tree),亦称二叉搜索树, 
  30. *它或者是一棵空树;或者是具有下列性质的二叉树: 
  31. *(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值; 
  32. *(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值; 
  33. *(3)左、右子树也分别为二叉排序树; 
  34. *(4)排序二叉树的中序遍历结果是从小到大排列的. 
  35. * 
  36. *二叉查找树相比于其他数据结构的优势在于查找、插入的时间复杂度较低,为O(log n)。 
  37. *二叉查找树是基础性数据结构,用于构建更为抽象的数据结构,如集合、multiset、关联数组等。 
  38. * 
  39. *搜索,插入,删除的复杂度等于树高,期望O(log n),最坏O(n)(数列有序,树退化成线性表) 
  40. *改进版的二叉查找树可以使树高为O(logn),如SBT,AVL,红黑树等. 
  41. * 
  42. *程序来源于Linux C编程一站式学习 
  43. */  
  44. link bstSearch(link t, TElemType key);  
  45. link bstInsert(link t, TElemType key);  
  46. link bstDelete(link t, TElemType key);  
  47.   
  48. /** 
  49.  *http://baike.baidu.com/view/593144.htm?fr=aladdin 
  50.  *平衡二叉树 
  51.  */  
  52.   
  53. #endif  
binarytree.c
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /* binarytree.c */  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4. #include "binarytree.h"  
  5.   
  6. /** 
  7.  *生成节点 
  8.  *@param item is node value 
  9.  *@returns link point to new node 
  10.  */  
  11. static link make_node(TElemType item)  
  12. {  
  13.     link p = malloc(sizeof *p);  
  14.     p->item = item;  
  15.     p->lchild = p->rchild = NULL;  
  16.     return p;  
  17. }  
  18.   
  19. /** 
  20.  *释放节点 
  21.  *@param link to free 
  22.  */  
  23. static void free_node(link p)  
  24. {  
  25.     free(p);  
  26. }  
  27.   
  28. /** 
  29.  *根据前序与中序序列来初始化二叉树 
  30.  *@param VLR 前序序列 
  31.  *@param LVR 中序序列 
  32.  *@param n 序列中数值个数 
  33.  *@returns NULL when n <= 0 
  34.  *@returns link pointer to new binarytree 
  35.  */  
  36. link init(TElemType VLR[], TElemType LVR[], int n)  
  37. {  
  38.     link t;  
  39.     int k;  
  40.     if (n <= 0)  
  41.         return NULL;  
  42.     for (k = 0; VLR[0] != LVR[k]; k++);  
  43.     t = make_node(VLR[0]);  
  44.     t->lchild = init(VLR+1, LVR, k);  
  45.     t->rchild = init(VLR+1+k, LVR+1+k, n-k-1);  
  46.     return t;  
  47. }  
  48.   
  49. #ifdef RECU  
  50. /** 
  51.  *前序遍历(跟左右) 
  52.  *@param t to visit 
  53.  *@param visit point to a func 
  54.  */  
  55. void pre_order(link t, void (*visit)(link))  
  56. {  
  57.     if (!t)  
  58.         return;  
  59.     visit(t);  
  60.     pre_order(t->lchild, visit);  
  61.     pre_order(t->rchild, visit);  
  62. }  
  63.   
  64. /** 
  65.  *中序序遍历(左跟右) 
  66.  *@param t to visit 
  67.  *@param visit point to a func 
  68.  */  
  69. void in_order(link t, void (*visit)(link))  
  70. {  
  71.     if (!t)  
  72.         return;  
  73.     in_order(t->lchild, visit);  
  74.     visit(t);  
  75.     in_order(t->rchild, visit);  
  76. }  
  77.   
  78. /** 
  79.  *中序序遍历(左右跟) 
  80.  *@param t to visit 
  81.  *@param visit point to a func 
  82.  */  
  83. void post_order(link t, void (*visit)(link))  
  84. {  
  85.     if (!t)  
  86.         return;  
  87.     post_order(t->lchild, visit);  
  88.     post_order(t->rchild, visit);  
  89.     visit(t);  
  90. }  
  91. #endif  
  92.   
  93. /** 
  94.  *遍历二叉树,生成用于tree工具的字符串 
  95.  *@param root to visit 
  96.  */  
  97. void pprint(link root)  
  98. {  
  99.     printf("(");  
  100.     if (root != NULL) {  
  101.         printf("%d", root->item);  
  102.         pprint(root->lchild);  
  103.         pprint(root->rchild);  
  104.     }  
  105.     printf(")");  
  106. }  
  107.   
  108. int count(link t)  
  109. {  
  110.     if (!t)  
  111.         return 0;  
  112.     return 1 + count(t->lchild) + count(t->rchild);  
  113. }  
  114.   
  115. int depth(link t)  
  116. {  
  117.     int dl, dr;  
  118.     if (!t)  
  119.         return 0;  
  120.     dl = depth(t->lchild);  
  121.     dr = depth(t->rchild);  
  122.     return 1 + (dl > dr ? dl : dr);  
  123. }  
  124.   
  125. void destroy(link t)  
  126. {  
  127.     post_order(t, free_node);  
  128. }  
  129.   
  130.   
  131. /** 
  132.  *在bst中查找值为key的节点 
  133.  * 
  134.  *1、若b是空树,则搜索失败,否则; 
  135.  *2、若x等于b的根节点的数据域之值,则查找成功;否则; 
  136.  *3、若x小于b的根节点的数据域之值,则搜索左子树;否则; 
  137.  *4、查找右子树. 
  138.  * 
  139.  *@param t to search 
  140.  *@param key the value of link to find 
  141.  *@returns the link of the key 
  142.  */  
  143. link bstSearch(link t, TElemType key)  
  144. {  
  145.     if (t == NULL)  
  146.         return NULL;  
  147.   
  148.     if (t->item > key) {  
  149.         return bstSearch(t->lchild, key);  
  150.     } else if (t->item < key){  
  151.         return bstSearch(t->rchild, key);  
  152.     } else {  
  153.         return t;  
  154.     }  
  155. }  
  156.   
  157. /** 
  158.  *在bst中插入值为key的节点 
  159.  * 
  160.  *1、若t是空树,则将key作为根节点的值插入,否则; 
  161.  *2、若t->item大于key,则把key插入到左子树中,否则; 
  162.  *3、把key插入到左子树中. 
  163.  * 
  164.  *@param t 要插入的 bst 
  165.  *@param key 要插入的值 
  166.  *@returns 插入后的bst 
  167.  */  
  168. link bstInsert(link t, TElemType key)  
  169. {  
  170.     if (t == NULL) {  
  171.         return make_node(key);  
  172.     }  
  173.   
  174.     if (t->item > key) {  
  175.         t->lchild = bstInsert(t->lchild, key);  
  176.     } else {  
  177.         t->rchild = bstInsert(t->rchild, key);  
  178.     }  
  179.   
  180.     return t;  
  181. }  
  182.   
  183. /** 
  184.  *在bst中删除值为key的节点 
  185.  * 
  186.  *1、若t为空树,则直接返回NULL,否则; 
  187.  *2、若t->item大于key,bst左子树为bst左子树删除key后的bst,否则; 
  188.  *3、若t->item小于key,bst右子树为bst右子树删除key后的bst,否则; 
  189.  *4、若t->item == key: 
  190.  *      1.若其左右子树为NULL,返回NULL,即对其父节点赋值为NULL 
  191.  *      2.若其左子树不为NULL,则在其左子树中找到最大节点p, 
  192.           将p->item赋值给当前节点,还需要在其左子树中删除p->item, 
  193.         3.若其右子树不为NULL,则在其左子树中找到最小节点p, 
  194.           将p->item赋值给当前节点,还需要在其右子树中删除p->item, 
  195.  * 
  196.  *@param t 要插入的 bst 
  197.  *@param key 要插入的值 
  198.  *@returns 插入后的bst 
  199.  */  
  200. link bstDelete(link t, TElemType key)  
  201. {  
  202.     if (t == NULL)  
  203.         return NULL;  
  204.   
  205.     if (t->item > key)   
  206.         t->lchild = bstDelete(t->lchild, key);  
  207.     else if (t->item < key)  
  208.         t->rchild = bstDelete(t->rchild, key);  
  209.     else {  
  210.         link p;  
  211.         if (t->lchild == NULL && t->rchild == NULL) {  
  212.             free_node(t);  
  213.             t = NULL;  
  214.         } else if (t->lchild){  
  215.             for (p = t->lchild; p->rchild; p = p->rchild);  
  216.             t->item = p->item;  
  217.             t->lchild = bstDelete(t->lchild, t->item);  
  218.         } else {  
  219.             for (p = t->rchild; p->lchild; p = p->lchild);  
  220.             t->item = p->item;  
  221.             t->rchild = bstDelete(t->rchild, t->item);  
  222.         }  
  223.     }  
  224.   
  225.     return t;  
  226. }  
测试程序
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /* main.c */  
  2. #include <stdio.h>  
  3. #include <time.h>  
  4. #include "binarytree.h"  
  5.   
  6. #define RANGE   50  
  7. #define N       15  
  8.   
  9. void print_item(link p)  
  10. {  
  11.     printf("%d\t", p->item);  
  12. }  
  13.   
  14. void testBst()  
  15. {  
  16.     int i;  
  17.     link root = NULL;  
  18.     srand(time(NULL));  
  19.     for (i=0; i<N; i++)  
  20.         root = bstInsert(root, rand()%RANGE);  
  21.   
  22.     printf("\\tree");  
  23.     pprint(root);  
  24.     printf("\n");  
  25.   
  26.     TElemType key = rand() % RANGE;  
  27.     if (bstSearch(root, key)) {  
  28.         bstDelete(root, key);  
  29.         printf("\n%d\n", key);  
  30.   
  31.         printf("\\tree");  
  32.         pprint(root);  
  33.         printf("\n");  
  34.     }  
  35. }  
  36.   
  37. void testInitByList()  
  38. {  
  39.     TElemType pre_seq[] = { 4, 2, 1, 3, 6, 5, 7 };  
  40.     TElemType in_seq[] = { 1, 2, 3, 4, 5, 6, 7 };  
  41.     link root = init(pre_seq, in_seq, 7);  
  42.   
  43.     printf("\\tree");  
  44.     pprint(root);  
  45.     printf("\n");  
  46.   
  47.     pre_order(root, print_item);  
  48.     putchar('\n');  
  49.     in_order(root, print_item);  
  50.     putchar('\n');  
  51.     post_order(root, print_item);  
  52.     putchar('\n');  
  53.     printf("count=%d depth=%d\n", count(root), depth(root));  
  54.     destroy(root);  
  55.     printf("+++++++++++++++++++++++++++++++++++++++++++++++++++\n\n");  
  56. }  
  57.   
  58. int main()  
  59. {  
  60.     //testInitByList();  
  61.     testBst();  
  62.     return 0;  
  63. }  

对应的Makefie

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #if you want to use recursive func,please make recu=y  
  2. ifeq (y, $(recu))  
  3.     CFLAGS += -DRECU  
  4. endif  
  5.   
  6. ifeq (y, $(debug))  
  7.     CFLAGS += -g  
  8. endif  
  9.   
  10. all:  
  11.     gcc $(CFLAGS) main.c binarytree.c binarytree.h -o tree  
  12.   
  13. clean:  
  14.     $(RM) tree  

编译测试

在这里遍历二叉树只写了递归函数
在编译的时候用一下命令
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. make recu=y debug=y  
运行结构如下:
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. \tree(15(6(0()())(7()(14(11(8()())())())))(41(36(18(16()())(23(22()())(29()())))())(41()())))  
  2.   
  3. 22  
  4. \tree(15(6(0()())(7()(14(11(8()())())())))(41(36(18(16()())(23()(29()())))())(41()())))  
好了接下来就是用工具tree,把这些字符串图形化
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. echo "\tree(15(6(0()())(7()(14(11(8()())())())))(41(36(18(16()())(23(22()())(29()())))())(41()())))" | tree -b2  
怎么样这个效果。


把b2改成b6
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 用过的车票丢了怎么办 高铁票被水洗了怎么办 沈阳地铁卡丢了怎么办 火车票没写检票口怎么办 吃鸡听的脚步声距离太近怎么办 检票时车票丢了怎么办 高铁出站没检票怎么办 高铁来不及取票怎么办 被发现假的增值税发票怎么办 高铁票身份证验证失败怎么办 网上订的火车票查不到怎么办 已经参加工作想学个本科证怎么办 火车晚点耽误下一趟列车怎么办 门外装监控没有预留电线怎么办 框架柱主筋柱顶预留长度不够怎么办 遇到很嚣张的人怎么办 在地板砖上铺木地板卧室门怎么办 宝宝打预防针的本子丢了怎么办 宝宝打预防针本子丢了怎么办 打疫苗的本子丢了怎么办 麦客收割机麦秸里加麦粒怎么办 高铁乘务员身高不够怎么办 坐火车买到站票怎么办 买上车补票原票怎么办? 买的商务座补票怎么办 12306账号被别人登录怎么办 飞机不提供餐食怎么办 12306退票支付宝失败怎么办 12306重复支付怎么办支付宝 支付宝登的12306账号怎么办 没买儿童高铁票怎么办 网上订的机票怎么办托运 半夜买高铁票不出票怎么办 轻轨少买了一站怎么办 高铁火车票丢了怎么办 如果高铁票丢了怎么办 高铁票丢了怎么办 报销 高铁如果没赶上怎么办 高铁管家待核验怎么办 动车没有票了怎么办 12306取消订单3次怎么办