[DemoCode下载] C语言的一个二叉树

[复制链接]
920|17
 楼主| 734774645 发表于 2017-1-25 22:11 | 显示全部楼层 |阅读模式
二叉树作为C语言算法的一个基本案例,经常被考的。
 楼主| 734774645 发表于 2017-1-25 22:12 | 显示全部楼层
一个最基本的二叉树~~
包括二叉树的一些基本操作的实现,学习一下~~~
头文件BiTree.h
  1. typedef int Item;  
  2. typedef struct node  
  3. {  
  4.     struct node * lchild;  
  5.     struct node * rchild;  
  6.     Item data;  
  7. }BiTNode,*BiTree;  
  8.   
  9. /*构造一棵新的二叉树*/  
  10. BiTree InitBiTree(BiTNode *root);  
  11.   
  12. /*生成节点*/  
  13. BiTNode *MakeNode(Item item,BiTNode *lchild,BiTNode *rchild);  
  14. /*释放节点*/  
  15. void FreeNode(BiTNode *pnode);  
  16.   
  17. /*清空一棵二叉树*/  
  18. void ClearBiTree(BiTree tree);  
  19.   
  20. /*销毁一棵二叉树*/  
  21. void DestroyBiTree(BiTree tree);  
  22.   
  23. /*判定是否为空*/  
  24. IsEmpty(BiTree tree);  
  25.   
  26. /*返回树的深度*/  
  27. GetDepth(BiTree tree);  
  28.   
  29. /*返回根*/  
  30. BiTree GetRoot(BiTree tree);  
  31.   
  32. /*返回节点值*/  
  33. Item GetItem(BiTNode *pnode);  
  34.   
  35. /*设置节点值*/  
  36. void SetItem(BiTNode *pnode,Item item);  
  37.   
  38. /*设置左子树*/  
  39. BiTree SetLChild(BiTree parent,BiTree lchild);  
  40.   
  41. /*设置右子树*/  
  42. BiTree SetRChild(BiTree parent,BiTree rchild);  
  43.   
  44. /*返回左子树*/  
  45. BiTree GetLChild(BiTree tree);  
  46.   
  47. /*返回右子树*/  
  48. BiTree GetRChild(BiTree tree);  
  49.   
  50. /*插入新子树*/  
  51. BiTree InsertChild(BiTree parent,int lr,BiTree child);  
  52.   
  53. /*删除子树*/  
  54. void DeleteChild(BiTree parent,int lr);  
  55.   
  56. /*先序遍历二叉树*/  
  57. PreOrderTraverse(BiTree tree,void(*visit)());  
  58.   
  59. /*中序遍历二叉树*/  
  60. InOrderTraverse(BiTree tree,void(*visit)());  
  61.   
  62. /*后序遍历二叉树*/  
  63. PostOrderTraverse(BiTree tree,void(*visit)());


 楼主| 734774645 发表于 2017-1-25 22:13 | 显示全部楼层
实现文件BiTree.c如下
  1. #include"BiTree.h"  
  2. #include<malloc.h>  
  3. #include<stdlib.h>  
  4.   
  5. /*构造一棵新的二叉树*/  
  6. BiTree InitBiTree(BiTNode *root)  
  7. {  
  8.     BiTree tree = root;  
  9.     return tree;  
  10. }  
  11.   
  12. /*生成节点*/  
  13. BiTNode *MakeNode(Item item,BiTNode *lchild,BiTNode *rchild)  
  14. {  
  15.     BiTNode * pnode = (BiTNode *)malloc(sizeof(BiTNode));  
  16.     if(pnode)  
  17.     {  
  18.         pnode->data = item;  
  19.         pnode->lchild = lchild;  
  20.         pnode->rchild = rchild;  
  21.     }  
  22.     return pnode;     
  23. }  
  24.   
  25. /*释放节点*/  
  26. void FreeNode(BiTNode *pnode)  
  27. {  
  28.     if(pnode!=NULL)  
  29.         free(pnode);  
  30. }  
  31.   
  32. /*清空一棵二叉树*/  
  33. void ClearBiTree(BiTree tree)  
  34. {  
  35.     BiTNode * pnode = tree;  
  36.     if(pnode->lchild!=NULL)  
  37.         ClearBiTree(pnode->lchild);  
  38.   
  39.     if(pnode->rchild!=NULL)  
  40.         ClearBiTree(pnode->rchild);  
  41.   
  42.     FreeNode(pnode);  
  43. }  
  44.   
  45. /*销毁一棵二叉树*/  
  46. void DestroyBiTree(BiTree tree)  
  47. {  
  48.     if(tree)  
  49.         ClearBiTree(tree);   
  50. }  
  51.   
  52. /*判定是否为空*/  
  53. IsEmpty(BiTree tree)  
  54. {  
  55.     if(tree==NULL)  
  56.         return 0;  
  57.     else  
  58.         return 1;  
  59. }  
  60.   
  61. /*返回树的深度*/  
  62. int GetDepth(BiTree tree)  
  63. {  
  64.     int cd,ld,rd;  
  65.     cd = ld = rd = 0;  
  66.     if(tree)  
  67.     {  
  68.         ld = GetDepth(tree->lchild);  
  69.         rd = GetDepth(tree->rchild);  
  70.         cd = (ld > rd ? ld : rd);  
  71.         return cd+1;  
  72.     }  
  73.     else  
  74.         return 0;  
  75. }  
  76.   
  77. /*返回根*/  
  78. BiTree GetRoot(BiTree tree)  
  79. {  
  80.     return tree;  
  81. }  
  82.   
  83. /*返回节点值*/  
  84. Item GetItem(BiTNode *pnode)  
  85. {  
  86.     return pnode->data;  
  87. }  
  88.   
  89. /*设置节点值*/  
  90. void SetItem(BiTNode *pnode,Item item)  
  91. {  
  92.     pnode->data = item;  
  93. }  
  94.   
  95. /*设置左子树*/  
  96. BiTree SetLChild(BiTree parent,BiTree lchild)  
  97. {  
  98.     parent->lchild = lchild;  
  99.     return lchild;  
  100. }  
  101.   
  102. /*设置右子树*/  
  103. BiTree SetRChild(BiTree parent,BiTree rchild)  
  104. {  
  105.     parent->rchild = rchild;  
  106.     return rchild;  
  107. }  
  108.   
  109. /*返回左子树*/  
  110. BiTree GetLChild(BiTree tree)  
  111. {  
  112.     if(tree)  
  113.         return tree->lchild;  
  114.     return NULL;  
  115. }  
  116.   
  117. /*返回右子树*/  
  118. BiTree GetRChild(BiTree tree)  
  119. {  
  120.     if(tree)  
  121.         return tree->rchild;  
  122.     return NULL;  
  123. }  
  124.   
  125. /*插入新子树*/  
  126. BiTree InsertChild(BiTree parent,int lr,BiTree child)  
  127. {  
  128.     if(parent)  
  129.     {  
  130.         if( lr == 0 && parent->lchild == NULL)  
  131.         {  
  132.             parent->lchild = child;  
  133.             return child;  
  134.         }     
  135.         if( lr == 1 && parent->rchild == NULL)  
  136.         {  
  137.             parent->rchild = child;  
  138.             return child;  
  139.         }     
  140.     }  
  141.     return NULL;      
  142. }  
  143.   
  144. /*删除子树*/  
  145. void DeleteChild(BiTree parent,int lr)  
  146. {  
  147.     if(parent)  
  148.     {  
  149.         if( lr == 0 && parent->lchild != NULL)  
  150.         {  
  151.             parent->lchild = NULL;  
  152.             FreeNode(parent->lchild);  
  153.         }     
  154.         if( lr == 1 && parent->rchild != NULL)  
  155.         {  
  156.             parent->rchild = NULL;  
  157.             FreeNode(parent->rchild);  
  158.         }     
  159.     }  
  160. }  
  161.   
  162. /*先序遍历二叉树*/  
  163. PreOrderTraverse(BiTree tree,void(*visit)())  
  164. {  
  165.     BiTNode * pnode = tree;  
  166.     if(pnode)  
  167.     {  
  168.         visit(pnode->data);  
  169.         PreOrderTraverse(pnode->lchild,visit);  
  170.         PreOrderTraverse(pnode->rchild,visit);  
  171.     }  
  172. }  
  173.   
  174. /*中序遍历二叉树*/  
  175. InOrderTraverse(BiTree tree,void(*visit)())  
  176. {  
  177.     BiTNode * pnode = tree;  
  178.     if(pnode)  
  179.     {  
  180.         InOrderTraverse(pnode->lchild,visit);  
  181.         visit(pnode->data);  
  182.         InOrderTraverse(pnode->rchild,visit);  
  183.     }  
  184. }  
  185.   
  186. /*后序遍历二叉树*/  
  187. PostOrderTraverse(BiTree tree,void(*visit)())  
  188. {  
  189.     BiTNode * pnode = tree;  
  190.     if(pnode)  
  191.     {  
  192.         PostOrderTraverse(pnode->lchild,visit);        
  193.         PostOrderTraverse(pnode->rchild,visit);  
  194.         visit(pnode->data);  
  195.     }  
  196. }  


 楼主| 734774645 发表于 2017-1-25 22:13 | 显示全部楼层
简单测试程序如下
  1. #include"BiTree.h"  
  2. #include<stdio.h>  
  3. void print(Item item)  
  4. {  
  5.     printf("%d ",item);  
  6. }  
  7. main()  
  8. {     
  9.     BiTNode * n1 = MakeNode(10,NULL,NULL);  
  10.     BiTNode * n2 = MakeNode(20,NULL,NULL);  
  11.     BiTNode * n3 = MakeNode(30,n1,n2);  
  12.     BiTNode * n4 = MakeNode(40,NULL,NULL);  
  13.     BiTNode * n5 = MakeNode(50,NULL,NULL);  
  14.     BiTNode * n6 = MakeNode(60,n4,n5);  
  15.     BiTNode * n7 = MakeNode(70,NULL,NULL);  
  16.   
  17.     BiTree tree = InitBiTree(n7);  
  18.     SetLChild(tree,n3);  
  19.     SetRChild(tree,n6);  
  20.   
  21.     printf("树的深度为:%d",GetDepth(tree));  
  22.       
  23.     printf("\n先序遍历如下:");  
  24.     PreOrderTraverse(tree,print);  
  25.   
  26.     printf("\n中序遍历如下:");  
  27.     InOrderTraverse(tree,print);  
  28.   
  29.     printf("\n后序遍历如下:");  
  30.     PostOrderTraverse(tree,print);  
  31.   
  32.     DeleteChild(tree,1);  
  33.     printf("\n后序遍历如下:");  
  34.     PostOrderTraverse(tree,print);  
  35.   
  36.     DestroyBiTree(tree);  
  37.     if(IsEmpty(tree))  
  38.      printf("\n二叉树为空,销毁完毕\n");  
  39. }  


 楼主| 734774645 发表于 2017-1-25 22:14 | 显示全部楼层
在计算机科学中,二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。
二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。二叉树的第i层至多有2^{i-1}个结点;深度为k的二叉树至多有2^k-1个结点;对任何一棵二叉树T,如果其终端结点数为n_0,度为2的结点数为n_2,则n_0=n_2+1。
一棵深度为k,且有2^k-1个节点称之为满二叉树;深度为k,有n个节点的二叉树,当且仅当其每一个节点都与深度为k的满二叉树中,序号为1至n的节点对应时,称之为完全二叉树。
 楼主| 734774645 发表于 2017-1-25 22:15 | 显示全部楼层
二叉树在图论中是这样定义的:二叉树是一个连通的无环图,并且每一个顶点的度不大于3。有根二叉树还要满足根结点的度不大于2。有了根结点之后,每个顶点定义了唯一的父结点,和最多2个子结点。然而,没有足够的信息来区分左结点和右结点。如果不考虑连通性,允许图中有多个连通分量,这样的结构叫做森林。
 楼主| 734774645 发表于 2017-1-25 22:16 | 显示全部楼层
(1)完全二叉树——若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第h层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树。
(2)满二叉树——除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树。
(3)平衡二叉树——平衡二叉树又被称为AVL树(区别于AVL算法),它是一棵二叉排序树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
 楼主| 734774645 发表于 2017-1-25 22:16 | 显示全部楼层
树的结点:包含一个数据元素及若干指向子树的分支;
孩子结点:结点的子树的根称为该结点的孩子;
双亲结点:B 结点是A 结点的孩子,则A结点是B 结点的双亲;
兄弟结点:同一双亲的孩子结点; 堂兄结点:同一层上结点;
祖先结点: 从根到该结点的所经分支上的所有结点子孙结点:以某结点为根的子树中任一结点都称为该结点的子孙
结点层:根结点的层定义为1;根的孩子为第二层结点,依此类推;
树的深度:树中最大的结点层
结点的度:结点子树的个数
树的度: 树中最大的结点度。
叶子结点:也叫终端结点,是度为 0 的结点;
分枝结点:度不为0的结点;
有序树:子树有序的树,如:家族树;
无序树:不考虑子树的顺序;
 楼主| 734774645 发表于 2017-1-25 22:17 | 显示全部楼层
1)顺序存储方式

typenode=record
data:datatype
l,r:integer;
end;
vartr:array[1..n]ofnode;
(2)链表存储方式,如:

typebtree=^node;
node=record
data:datatye;
lchild,rchild:btree;
end;
 楼主| 734774645 发表于 2017-1-25 22:17 | 显示全部楼层
遍历是对树的一种最基本的运算,所谓遍历二叉树,就是按一定的规则和顺序走遍二叉树的所有结点,使每一个结点都被访问一次,而且只被访问一次。由于二叉树是非线性结构,因此,树的遍历实质上是将二叉树的各个结点转换成为一个线性序列来表示。
mintspring 发表于 2017-1-25 22:29 | 显示全部楼层
树形的搜索让系统变得非常简单。
天灵灵地灵灵 发表于 2017-1-25 22:37 | 显示全部楼层
巩固一下这些数据结构的知识。
643757107 发表于 2017-1-26 10:27 | 显示全部楼层
/*生成节点*/  
BiTNode *MakeNode(Item item,BiTNode *lchild,BiTNode *rchild);  
/*释放节点*/  
void FreeNode(BiTNode *pnode);  
643757107 发表于 2017-1-26 10:40 | 显示全部楼层
还有什么堆栈,FIFO的应用也是要学的。
dongnanxibei 发表于 2017-1-27 15:25 | 显示全部楼层
树的操作特别考研一个程序员的基本功。
天灵灵地灵灵 发表于 2017-1-27 16:55 | 显示全部楼层
满二叉树——除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树
天灵灵地灵灵 发表于 2017-1-27 16:55 | 显示全部楼层
根据这个可不可以有多叉子树
zhuotuzi 发表于 2017-1-28 10:27 | 显示全部楼层
不过不理解树的操作,单独看程序实在是难懂。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

211

主题

3588

帖子

15

粉丝
快速回复 在线客服 返回列表 返回顶部