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

10 篇文章 0 订阅
3 篇文章 0 订阅
 

二叉树学习之二叉查找树

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

目录(?)[+]

写在前面的话

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

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

源码

binarytree.h
[cpp]  view plain copy 在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 plain copy 在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 plain copy 在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 plain copy 在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 plain copy 在CODE上查看代码片 派生到我的代码片
  1. make recu=y debug=y  
运行结构如下:
[cpp]  view plain copy 在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 plain copy 在CODE上查看代码片 派生到我的代码片
  1. echo "\tree(15(6(0()())(7()(14(11(8()())())())))(41(36(18(16()())(23(22()())(29()())))())(41()())))" | tree -b2  
怎么样这个效果。


把b2改成b6
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值