完全二叉树中节点度为1的最多有1个,没有左孩子就没有右孩子
树的结构定义是递归,任何一棵树都可以看成三部分,根和左子树,右子树
树不能构成回路或环以及孤立的点
二叉树不一定有两个子树,有可能为空
满二叉树必须是全满的,完全二叉树前K-1层都是满的,最后一层可以不满,但必须从左到右连续
顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。
若父亲节点是i,左孩子下标是2*i+1,右孩子下标是2*i+2。
若孩子下标是i,则父亲节点下标是(i-1)/2【向下取整】
二叉树的遍历分为:
前序(先根遍历,根->左子树->右子树:A B D N N E N N C N N,一般NULL不显示)
中序(中根遍历,左子树->根->右子树:N D N B N E N A N C N)
后序(后根遍历,左子树->右子树->根:N N D N N E B N N C A)
层序(A B C D E N N N N N N)从第一层到最后一层
前三个是深度优先遍历,最后一个是广度优先遍历,
判断是否为完全二叉树用层序(因为层序分成两段)
头文件及定义
#include<stdio.h>
#include<stdlib.h>
typedef char BTDataType;
typedef struct BinaryTreeNode//定义二叉树
{
BTDataType _data;// 当前节点值域
struct BinTreeNode* pLeft; // 指向当前节点左孩子
struct BinTreeNode* pRight; // 指向当前节点右孩子
}BTNode;
开辟新节点
BTNode* CreateNode(int x)//开辟节点
{
BTNode* node = (BTNode*)malloc(sizeof(BTNode));
node->_data = x;
node->pLeft=NULL;
node->pRight = NULL;
return node;
}
二叉树前序遍历
void PrevOrder(BTNode* root)//二叉树前序遍历
{
if (root == NULL)//如果是空树也打印一下
{
printf("NULL ");
return;
}
printf("%c ", root->_data);
PrevOrder(root->pLeft);
PrevOrder(root->pRight);
}
二叉树中序遍历
void InOrder(BTNode* root)//二叉树中序遍历
{
if (root == NULL)
{
printf("NULL ");
return;
}
InOrder(root->pLeft);
printf("%c ", root->_data);
InOrder(root->pRight);
}
二叉树后序遍历
void PostOrder(BTNode* root)//二叉树后序遍历
{
if (root == NULL)
{
printf("NULL ");
return;
}
PostOrder(root->pLeft);
PostOrder(root->pRight);
printf("%c ", root->_data);
}
二叉树层序遍历
int BinaryTreeLevelOrder(BTNode* root)//层序遍历,需要用到队列!
{
Queue q;
QueueInit(&q);
if (root == NULL)
{
return;
}
QueuePush(&q, root);//先把二叉树的头节点放进队列
while (!QueueEmpty(&q))//队列不为空,就出队头
{
BTNode* front = QueueFront(&q);
QueuePop(&q);//Pop不是把数据删除,而是把它从队列中移除
printf("%c ", front->_data);
//不为空就把左右子树放进队列
if (front->pLeft != NULL)
{
QueuePush(&q, front->pLeft);
}
if (front->pRight != NULL)
{
QueuePush(&q, front->pRight);
}
}
QueueDestroy(&q);
printf("\n");
}
判断一棵树是不是完全二叉树
//判断一棵树是不是完全二叉树,采用层序遍历,是返回1,不是返回0
int BinaryTreeComplete(BTNode* root)
{
Queue q;
QueueInit(&q);
if (root == NULL)
{
return 1;//空树也是完全二叉树
}
QueuePush(&q, root);//先把二叉树的头节点放进队列
while (!QueueEmpty(&q))//队列不为空,就出队头
{
BTNode* front = QueueFront(&q);
QueuePop(&q);//Pop不是把数据删除,而是把它从队列中移除
if (front == NULL)//若队列中出现空就跳出
{
break;
}
//把左右节点放进队列
QueuePush(&q, front->pLeft);
QueuePush(&q, front->pRight);
}
//只有当有效节点和NULL分成两段时才是完全二叉树
//非完全二叉树在NULL的那一部分会出现有效节点
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
QueuePop(&q);
if (front != NULL)
{
QueueDestroy(&q);
return 0;
}
}
QueueDestroy(&q);
return 1;
}
求二叉树第K层节点个数
int BinanyTreeLevelKSize(BTNode* root, int k)//求二叉树第K层节点个数
{
//当前树的第K层可以转换为左右子树的第K-1层,当层数等于1时就不需要分解
if (root == NULL)
return 0;
else if (k == 1)
return 1;
return BinanyTreeLevelKSize(root->pLeft, k - 1) +
BinanyTreeLevelKSize(root->pRight, k - 1);
}
删除二叉树
void DestoryTree(BTNode* root)//删除二叉树
{
if (root == NULL)
return;
//先销毁左右子树再销毁头节点
DestoryTree(root->pLeft);
DestoryTree(root->pRight);
free(root);
}
查找二叉树中值为X的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)//查找值为X的节点
{
if (root == NULL)
return 0;
if (root == x)
return root;
//在左右子树查找
BTDataType* node = BinaryTreeFind(root->pLeft, x);
if (node == x)
{
return node;
}
node = BinaryTreeFind(root->pRight, x);
if (node == x)
{
return node;
}
return NULL;//找不到返回空
}
计算二叉树中所有叶子节点个数
int TreeLeafSize(BTNode* root)//计算叶节点个数
{
if (root == NULL)
{
return 0;
}
else if (root->pLeft == NULL && root->pRight == NULL)
{
return 1;
}
else
{
return TreeLeafSize(root->pLeft) + TreeLeafSize(root->pRight);
}
}
计算二叉树中所有节点个数
int TreeSize(BTNode* root)//计算所有节点个数
{
if (root == NULL)
{
return 0;
}
else
{
return 1 + TreeSize(root->pLeft) + TreeSize(root->pRight);
}
}