typedef char BTDataType;
typedef struct BinaryTreeNode
{
BTDataType _data;
struct BinaryTreeNode* _left;
struct BinaryTreeNode* _right;
}BTNode;
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi);
// 二叉树销毁
void BinaryTreeDestory(BTNode** root);
// 二叉树节点个数
int BinaryTreeSize(BTNode* root);
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root);
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k);
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
// 二叉树前序遍历
void BinaryTreePrevOrder(BTNode* root);
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root);
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root);
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root);
// 判断二叉树是否是完全二叉树
bool BinaryTreeComplete(BTNode* root);
目的:通过模拟二叉树的实现加深对函数递归的理解
二叉树的初始化
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi)
{
if (n <= 0)//或者可以通过pi对应的下标来判断
{
return NULL;
}
n--;
BTNode*tmp = (BTNode*)malloc(sizeof(BTNode));
if (a[*pi] == '#')
{
(*pi)++;
return NULL;
}
else
{
tmp->_data = a[*pi];
(*pi)++;
tmp->_left = BinaryTreeCreate(a, n, pi);
tmp->_right = BinaryTreeCreate(a, n, pi);
}
return tmp;
}
因为根据数组的数据实现栈,所以第一个参数是数组,第二个参数是是数组大小,用来实现递归停止条件,第三个参数是数组的下标,用于确定递归时,数组对应的数据
代码思路:
首先判断n是否为0,如果为0则说明,数组中的数据均已放入创建的二叉树中
如果不为0,则开辟一块空间放入数据。同时下表pi++;
因为这是前序遍历,即根>>左子树>>右子树
所以顺序是先插入数据,然后进入左子树,再进入右子树即可
二叉树的销毁
// 二叉树销毁(后序遍历)
void BinaryTreeDestory(BTNode** root)
{
if (*root == NULL)
{
return;
}
BinaryTreeDestory(&((*root)->_left));
BinaryTreeDestory(&((*root)->_right));
free(*root);
}
代码思路:
先判断当前节点是否为空,如果为空则返回。否则则进入其子树检查。
当所有子树都free后,再free其本身即可
二叉树节点个数
// 二叉树节点个数
int BinaryTreeSize(BTNode* root)
{
if (root == NULL)
{
return 0;
}
return BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right)+1;
}
根据递归思想,要想知道二叉树的节点个数,就得先知道其子树的节点个数。如果为空则返回0
二叉树叶子节点的个数
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root)
{
if (root == NULL)
{
return 0;
}
if (root->_left==NULL&&root->_right==NULL)
{
return 1;
}
return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
}
根据叶子节点的特点(左右子树为空)仿照上个函数的实现即可
二叉树第K层的节点个数
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
if (root == NULL)
{
return 0;
}
if (k == 1)
{
return 1;
}
return BinaryTreeLevelKSize(root->_left,k-1) + BinaryTreeLevelKSize(root->_right,k-1);
}
思路:只要能确定递归时所处的层数即可,因为每递归一次,层数加1,所以只要把K==1时的所有节点加起来即可
二叉树找值为X的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
if (root == NULL)
{
return NULL;
}
if (root->_data == x)
{
return root;
}
BTNode*_left = BinaryTreeFind(root->_left, x);
if (_left != NULL)
{
return _left;
}
BTNode*_right = BinaryTreeFind(root->_right, x);
if (_right != NULL)
{
return _right;
}
return NULL;
}
思路:首先先判断当前节点对应的data是不是目标值,如果不是,则去左子树找,左子树没有则去右子树找。定义变量接受其子树结果是为了减少递归次数
二叉树的前中后序遍历
// 二叉树前序遍历
void BinaryTreePrevOrder(BTNode* root)
{
if (root == NULL)
{
return;
}
printf("%c ", root->_data);
BinaryTreePrevOrder(root->_left);
BinaryTreePrevOrder(root->_right);
}
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{
if (root == NULL)
{
return;
}
BinaryTreeInOrder(root->_left);
printf("%c ", root->_data);
BinaryTreeInOrder(root->_right);
}
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{
if (root == NULL)
{
return;
}
BinaryTreePostOrder(root->_left);
BinaryTreePostOrder(root->_right);
printf("%c ", root->_data);
}
根据不同遍历规则调整递归顺序即可
二叉树的层序遍历
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
if (root == NULL)
{
return;
}
Queue q;
QueueInit(&q);
QueuePush(&q, root);
while (!QueueEmpty(&q))
{
BTNode*tmp = QueueFront(&q);
printf("%c ", tmp->_data);
if (tmp->_left != NULL)
{
QueuePush(&q, tmp->_left);
}
if (tmp->_right != NULL)
{
QueuePush(&q, tmp->_right);
}
QueuePop(&q);
}
printf("\n");
}
思路:用队列实现。根据队列先进先出的规则,将当前节点放入队列中,然后将其子树放入队列。循环这个过程即可实现
判断是否是完全二叉树
// 判断二叉树是否是完全二叉树
bool BinaryTreeComplete(BTNode* root)
{
if (root == NULL)
{
return true;
}
if (root->_left == root->_right)
{
return true;
}
if (root->_left)
{
if (root->_left->_left == root->_left->_right)
{
return true;
}
else
{
return false;
}
}
if (root->_right)
{
if (root->_right->_left == root->_right->_right)
{
return true;
}
else
{
return false;
}
}
return BinaryTreeComplete(root->_left) && BinaryTreeComplete(root->_right);
}
思路:根据完全二叉树的特点,其叶节点的左右子树必定为空即可。