二叉树的一些常见操作:
typedef char BTDataType;//二叉树的元素类型
typedef struct BinaryTreeNode {
struct BinaryTreeNode* left;// 左子树
struct BinaryTreeNode* right;//右子树
BTDataType data;
}BTNode;
void BTNodeInit(BTNode* bt, BTDataType x)//初始化
{
bt->left = NULL;
bt->right = NULL;
bt->data = x;
}
int TreeSize(BTNode* root)//返回树的结点个数
{
return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}
int TreeLeafSize(BTNode* root)//叶子结点个数
{
if (root == NULL)
{
return 0;
}
if (root->left == NULL && root->right == NULL)
{
return 1;
}
return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}
int TreeDepth(BTNode* root)//返回树的深度
{
if (root == NULL)return 0;
int leftDepth = TreeDepth(root->left);//左树的深度
int rightDepth = TreeDepth(root->right);//右树的深度
return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;//树的深度=左树的深度+右树的深度+1
}
void Destroy(BTNode* root)//销毁树
{
if (root == NULL)return;
Destroy(root->left);
Destroy(root->right);
free(root);
root = NULL;
}
//使用括号表示法输入二叉树并转化为二叉树的链式存储结构
BTreeCreat(BTNode** root, int* pi, char* a)
{
//核心思路:
//'('表示开辟一个新节点链接在双亲节点的左孩子上,然后把双亲节点存入栈
//','表示开辟一个新节点链接在双亲节点的右孩子上
//')'表示双亲节点链接结束,把双亲节点取出栈
if (root == NULL)return;
ST st;//创建一个栈
QueueInit(&st);//初始化栈
int k = 1;//k用来判断节点是在左子树还是右子树,当k为1时在左子树,当k为2时在右子树
(*root)->data = a[(*pi)++];//把根节点1存进去
BTNode* newroot = *root;//newroof表示新节点的双亲结点
while (a[(*pi)])
{
if (a[*pi] == '(')
{
StackPush(&st, newroot);//把双亲节点插入栈
(*pi)++;
k = 1;
}
if (a[*pi] == ',')
{
(*pi)++;
k = 2;
}
if (a[*pi] == ')')
{
(*pi)++;
StackPop(&st);//把双亲节点拿出栈
continue;
}
newroot = (BTNode*)malloc(sizeof(BTNode));//创建一个新节点
newroot->left = NULL;
newroot->right = NULL;
newroot->data = a[*pi];//把数据存进去
if (k == 1)
{
StackTop(&st)->left = newroot;//把新节点链接在双亲节点的左孩子上
}
if (k == 2)
{
StackTop(&st)->right = newroot;//把新节点链接在双亲节点的右孩子上
}
(*pi)++;
}
StackDestroy(&st);//销毁栈
}
二叉树的遍历:
二叉树的前中后序遍历,采用的是分而治之的思路,从根节点开始分为根、左子树、右子树,然后向下递归,直至叶子结点返回。
void PrevOrder(BTNode* root)//前序 根->左 ->右
{
if (root == NULL)
{
//printf("NULL ");
return;
}
printf("%c ", root->data);
PrevOrder(root->left);
PrevOrder(root->right);
}
void InOrder(BTNode* root)//中序 左->根->右
{
if (root == NULL)
{
//printf("NULL ");
return;
}
InOrder(root->left);
printf("%c ", root->data);
InOrder(root->right);
}
void PostOrder(BTNode* root)//后序 左->右->根
{
if (root == NULL)
{
//printf("NULL ");
return;
}
PostOrder(root->left);
PostOrder(root->right);
printf("%c ", root->data);
}
void LevelOrder(BTNode* root)
{
Queue q;//创建一个队列
QueueInit(&q);//初始化队列
//层序遍历核心思路上一层出的时候带下一层进
if (root)
{
QueuePush(&q, root);
}
while (!QueueEmpty(&q))
{
BTNode* Front = QueueFront(&q);//把队列里的head->data即A赋值给Front
QueuePop(&q);//释放head
printf("%c ", Front->data);
//把下一层带进去
if (Front->left)QueuePush(&q, Front->left);
if (Front->right)QueuePush(&q, Front->right);
}
printf("\n");
QueueDestroy(&q);
}
判断二叉树是否为平衡二叉树:
//平衡树:左树右树的高度差不超过1,并且子树也为平衡树
bool TreeisBlanced(BTNode* root)//判断是否为平衡树 是返回true 不是返回false
{
if (root)return true;
int leftDepth = TreeDepth(root->left);
int rightDepth = TreeDepth(root->right);
return abs(leftDepth - rightDepth) < 2 //abs()是一个求绝对值的函数,判断左树右树的高度差是否超过1
&& TreeisBlanced(root->left)//判断左树是否为平衡树
&& TreeisBlanced(root->right);//判断右树是否为平衡树
}
判断该二叉树是否为完全二叉树
//判断该二叉树是否为完全二叉树
bool BTIsComplete(BTNode*root)
{
//思路:在层序遍历的基础上找不饱和节点,不饱和节点之后的节点必须为空
Queue q;
QueueInit(&q);
if (root == NULL)return;
QueuePush(&q, root);
int k = 0;//k=0表示节点饱和,k=1表示已有不饱和的节点
while (!QueueEmpty(&q))
{
BTNode* newroof = QueueFront(&q);
QueuePop(&q);
if (k == 1)
{
if (newroof->left != NULL || newroof->right != NULL)
{
QueueDestroy(&q);//每次返回前都要销毁栈,防止空间泄露
return false;
};
}
//先找到一个不饱满的节点
if (newroof->left == NULL || newroof->right == NULL)//子节点有一个为空的即为不饱和节点
{
if (newroof->left == NULL && newroof->right != NULL)//当左孩子为空右孩子不为空时,不是完全二叉树
{
QueueDestroy(&q);
return false;
}
k = 1;
}
if (newroof->left != NULL)
{
QueuePush(&q, newroof->left);
}
if (newroof->right != NULL)
{
QueuePush(&q, newroof->right);
}
}
return true;
}