目录
链式二叉树的结构
二叉树的结构多种多样,顺序结构的二叉树只适合完全二叉树,非完全二叉树在顺序结构中会浪费空间,如下:
当二叉树中非末位节点没有数据时,就会浪费空间,所以非完全二叉树不适合顺序结构,更适合链式结构,那么链式结构的节点是怎么定义的呢?
如上图,链式结构中根节点定义两个指针分别指向子节点。
typedef int BinaryTreeDataType;
typedef struct BinaryTreeNode
{
BinaryTreeDataType val;
struct BinaryTreeNode * left;
struct BinaryTreeNode * right;
}BTNode;
二叉树的遍历
二叉树遍历的作用
二叉树的遍历是二叉搜索树的基础。
前序遍历
前序遍历思路
前序遍历是先访问根节点,再访问左子节点和右子节点。
对于二叉树的遍历,使用递归更方便,上图中可以将整个二叉树分化成只包含根节点,左子节点和右子节点的集合。对每一个节点只需要访问其数据之后,先调用左节点,再调用右节点,最终调用的顺序如下:
前序遍历实现
void preOrder(BTNode * root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
printf("%d ", root->val);
preOrder(root->left);
preOrder(root->right);
}
中序遍历
中序遍历思路
中序遍历的访问顺序是左节点,根节点,右节点。
中序遍历一定从最左边的节点开始访问,然后是根节点,右节点,最终调用顺序如下:
中序遍历实现
void InOrder(BTNode * root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
InOrder(root->left);
printf("%d ", root->val);
InOrder(root->right);
}
后续遍历
后序遍历思路
后序遍历的顺序是,左子节点->右子节点->根节点:
后序遍历实现
void PostOrder(BTNode * root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
PostOrder(root->left);
PostOrder(root->right);
printf("%d ", root->val);
}
实际递归问题
二叉树的节点个数
分析一:遍历全部节点非空节点用全局变量计数,全局变量可以重新赋值,但是需要在调用函数前进行重新赋值,但是这样的方法需要每次使用重新赋值,同时全局变量容易被修改,并不安全。
int count = 0;
void BTreeSize(BTNode * root)
{
if (root == NULL)
{
return;
}
++count;
BTreeSize(root->left);
BTreeSize(root->right);
}
int main()
{
BTNode * n1 = crearBinaryTree();
count = 0;
BTreeSize(n1);
printf("%d\n", count);
count = 0;
BTreeSize(n1);
printf("%d\n", count);
count = 0;
BTreeSize(n1);
printf("%d\n", count);
count = 0;
BTreeSize(n1);
printf("%d\n", count);
count = 0;
BTreeSize(n1);
printf("%d\n", count);
system("pause");
return 0;
}
分析二:分治法,就是把一个复杂的问题分化成若干个类型相同的小问题。
分治法实现:
int BTreeSize(BTNode*root)
{
if (root == NULL)
{
return 0;
}
return BTreeSize(root->left) + BTreeSize(root->right) + 1;
}
二叉树叶节点个数
分析:二叉树中没有子树的节点就是叶子节点,求二叉树叶子节点个数就是求没有左子树与右子树的根节点的个数。
二叉树中如果根节点是叶节点返回1,整个二叉树的叶节点由左子树的叶节点加上右子树的叶节点组成。
实现:
int BTreeLeaSize(BTNode*root)
{
if (root == NULL)
{
return 0;
}
if (root->left == NULL&&root->right == NULL)
{
return 1;
}
return BTreeLeaSize(root->left) + BTreeLeaSize(root->right);
}
二叉树的高度
分析:求取二叉树的高度,本质是左子树与右子树的高度进行比较,大于的一方加根节点的层数再返回。
代码实现:
int BTreeHeight(BTNode*root)
{
if (root == NULL)
{
return 0;
}
int left = BTreeHeight(root->left);
int right = BTreeHeight(root->right);
return left> right ? left + 1 : right + 1;
}
第K层节点个数
int BTreeKSize(BTNode*root, int k)
{
if (root == NULL)
return 0;
if (k == 1)
{
return 1;
}
return BTreeKSize(root->left, k - 1) + BTreeKSize(root->right, k - 1);
}
返回x所在的节点
BTNode * SearchX(BTNode * root, BinaryTreeDataType x)
{
if (root == NULL)
{
return NULL;
}
if (root->val == x)
{
return root;
}
BTNode * left = SearchX(root->left, x);
if (left)
{
return left;
}
BTNode * right = SearchX(root->right, x);
if (right)
{
return right;
}
return NULL;
}