二叉树的概念比较简单,但二叉树的概念背后的递归思想是更重要的。
1、空树
2、非空,由根节点、左子树、右子树组成。
本篇是二叉树的基础介绍,故不介绍非递归方式操作二叉树。
本篇以下图所表示的树演示各种二叉树操作。
本质:按照 根节点、左子树、右子树 的顺序访问节点。
按上图的遍历顺序为:1、2、3、4、5、6、7、8.
void PreOrder(BT* root)
{
if (!root)
return;
//以打印表示访问根节点
printf("%d ", root->d);
PreOrder(root->left);
PreOrder(root->right);
}
中序遍历
本质:按照 左子树、根节点、右子树 的顺序访问节点。
按上图的遍历顺序为:3、2、1、5、4、6、7、8.
void InOrder(BT* root)
{
if (!root)
return;
InOrder(root->left);
//以打印表示访问根节点
printf("%d ", root->d);
InOrder(root->right);
}
后序遍历
本质:按照 左子树、根节点、右子树 的顺序访问节点。
按上图的遍历顺序为:3、2、5、8、7、6、4、1.
void PostOrder(BT* root)
{
if (!root)
return;
PostOrder(root->left);
PostOrder(root->right);
//以打印表示访问根节点
printf("%d ", root->d);
}
层序遍历
层序遍历较为特殊,但不难,需要借助队列FIFO的性质。
添加Queue现有项
找到Queue.h和Queue.c文件
复制粘贴
更改QData的数据类型,
注意需要声明二叉树结构体类型,不然主文件里不认识struct binary_tree类型。
这样就能正常使用了。
void LevelOrder(BT* root)
{
//层序遍历需要利用队列
Queue q;
QueueInit(&q);
QueuePush(&q, root);
while (!QueueEmpty(&q))
{
BT* front = QueueFront(&q);
printf("%d ", front->d);
//出一个节点,带出来两个子节点
QueuePop(&q);
if (front->left)
{
//左子节点为空就不用入队,右子节点同理
QueuePush(&q, front->left);
}
if (front->right)
{
QueuePush(&q, front->right);
}
}
printf("n");
QueueDestroy(&q);
}
二叉树的一些函数
二叉树节点个数
int TreeSize(BT* root)
{
assert(root);
if (!root)
return 0;
return 1 + TreeSize(root->left) + TreeSize(root->right);
}
二叉树叶子节点个数
int TreeLeafSize(BT* root)
{
if (!root)
return 0;
if (root->left == NULL && root->right == NULL)
return 1;
return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}
二叉树第k层节点个数
int TreeKLevel(BT* root, int k)
{
if (!root)
return 0;
if (k == 1)
return 1;
else
{
return TreeKLevel(root->left, k - 1) +
TreeKLevel(root->right, k - 1);
}
}
二叉树查找值为x的节点
BT* TreeFind(BT* root, BTData d)
{
if (!root)
return NULL;
if (root->d == d)
return root;
//向左找
BT* ret = TreeFind(root->left, d);
if (ret)
return ret;
return TreeFind(root->right, d);
}
树的销毁
void TreeDestroy(BT* root)
{
if (!root)
return;
TreeDestroy(root->left);
TreeDestroy(root->right);
free(root);
}
一些题
单值二叉树
相同的树
对称二叉树
前序遍历,放数组里
中序遍历,放数组里
后序遍历,放数组里
另一颗树的子树
二叉树遍历



