首先通过一张图来认识树:
树:由N(N>=0)个结点构成的集合。对N>1的树,有:
1.有一个特殊的结点,称为根结点,根结点没有前驱结点
2.除根结点外,其余结点被分为M(M>0)个互不相交的集合T1、T2…..Tm,其中每一个集合Ti(1<=i<=m)有是一颗结构与树类似的子树。每棵子树的根结点有且只有一个前驱,可以有0个或多个后继。,因此,树是递归定义的。代码实现多采用递归的思想。
二叉树的遍历:
遵循某种次序,遍历二叉树中的所有结点,使得每个结点被访问一次,而且仅访问一次。“访问”:即对根结点施行某些操作。
前序遍历:先访问根结点,再前序遍历根结点的左子树,最后前序遍历根结点的右子树。
中序遍历:先中序遍历根结点的左子树,再访问根结点,最后中序遍历根结点的右子树。
后序遍历:先后序遍历根结点的左子树,再后序遍历根结点的右子树,最后访问根结点。
层序遍历:按照二叉树的层序次序(即从根结点层到叶结点层),同一层中按先左子树再右子树的次序遍历二叉树。
例如:如下一棵树,它的前序、中序、后序、层序遍历
代码实现:
bin_tree.h
1 #pragma once
2 #include <stdio.h>
3 typedef char TreeNodeType;
4 //使用孩子表示法来表示一棵树
5 typedef struct TreeNode {
6 TreeNodeType data;
7 struct TreeNode* lchild;
8 struct TreeNode* rchild;
9 }TreeNode;
10
11 //对于链表来说,使用链表的头节点指针来表示一个链表
12 //对于二叉树来说,使用跟结点的指针来表示一棵树
13 //树的初始化
14 void TreeInit(TreeNode** pRoot);
15 //前序遍历
16 void TreePreOrder(TreeNode* root);
17 //中序遍历
18 void TreeInOrder(TreeNode* root);
19 //后序遍历
20 void TreePostOrder(TreeNode* root);
21 //层序遍历
22 void TreeLevelOrder(TreeNode* root);
23
24 //输入一个数组(数组中的每个元素就是树上的结点),根据数组的内容
25 //构建出一颗树,数组中元素的内容符合树的先序遍历结果(包含所有空结点)
26 TreeNode* TreeCreate(TreeNodeType arry[],size_t size,char null_node);
27
28 //求二叉树中结点的个数
29 size_t TreeSize(TreeNode* root);
30 //求二叉树中叶子结点的个数
31 size_t TreeLeafSize(TreeNode* root);
32 //求二叉树中第K层结点的个数
33 size_t TreeKLevelSize(TreeNode* root,int K);
34
35 //求二叉树的高度/深度
36 size_t TreeHeight(TreeNode* root);
37
38 void TreeDestroy(TreeNode* root);
39
40 //在二叉树中查找结点,给定一个数值,求出对应结点的指针
41 //假设二叉树中的结点是不重复的
42 TreeNode* TreeFind(TreeNode* root,TreeNodeType to_find);
43
44 //求出child的父节点
45 TreeNode* FindParent(TreeNode* root,TreeNode* child);
46
47 //求出当前节点的左子树和右子树
48 TreeNode* LChild(TreeNode* node);
49 TreeNode* RChild(TreeNode* n