链式二叉树结点类型的定义
typedef char BinaryTreeDataType;
typedef struct BSTreeNode
{
struct BSTreeNode* left;//存储左孩子的地址
struct BSTreeNode* right;//存储右孩子的地址
BinaryTreeDataType val;//节点的数据域
}BTNode;
二叉树的深度优先遍历
1.前序遍历 (根-左子树-右子树)
void PrevOrderTree(BTNode* root)
{
if (root == NULL)
{
return;
}
printf("%c ", root->val);//访问根节点的值
PrevOrderTree(root->left);//左边走
PrevOrderTree(root->right);//右边走
}
2.中序遍历 (左子树-根-右子树)
void InOrderTree(BTNode* root)
{
if (root == NULL)
{
return;
}
InOrderTree(root->left);//左边走
printf("%c ", root->val);
InOrderTree(root->right);//右边走
}
3.后序遍历 (左子树-右子树-根)
void PostOrderTree(BTNode* root)
{
if (root == NULL)
{
return;
}
PostOrderTree(root->left);
PostOrderTree(root->right);
printf("%c ", root->val);
}
二叉树的广度优先遍历
层序遍历
自上而下,从左往右逐层访问树的结点的过程就是层序遍历。
实现思路:这里可以借助队列来实现,先进先出的性质,先入根节点,在出根节点,同时把根节点的左右非空节点入队列,其他节点重复此过程,直到队列为空时结束。
void LevelOrderTree(BTNode* root)
{
queue<BTNode*> q;//创建一个结构体指针类型队列qif (root == NULL)
{
return;
}
q.push(root);//入根节点
while (!q.empty())//判断队列是否为空
{
BTNode* front = q.front();//front用来保存队头数据
printf("%c ", front->val);//打印队头的值
q.pop();//出对头节点
if (front->left)//左节点不为空,入该节点
{
q.push(front->left);
}
if (front->right)//右节点不为空,入该节点
{
q.push(front->right);
}
}
}
二叉树结点的个数
求节点个数时是带有返回值的递归,可以将该问题拆解成子问题,节点为空,返回0,非空,返回左子树节点个数+右子树节点个数+1(节点本身)。
int CountTreeNode(BTNode* root)
{
if (root == NULL)
{
return 0;
}
return CountTreeNode(root->left) + CountTreeNode(root->right) + 1;//左边节点+右边节点+自身节点等于节点个数
}
叶子结点(左右节点都为空)的个数
实现思路:也是子问题拆解问题
1.若为空,返回0。
2.若左右都为空,返回1
3.除上述两种情况外,说明该树存在子树,其叶子结点个数 = 左子树的叶子结点个数 + 右子树的叶子结点个数。
int SizeLeafNode(BTNode* root)
{
if (root == NULL)
{
return 0;
}
if (root->left == NULL && root->right == NULL)
{
return 1;
}
return SizeLeafNode(root->left) + SizeLeafNode(root->right);//左边的叶子节点+右边的叶子节点
}
第k层结点的个数
实现思路:相对于根结点的第k层结点的个数 = 相对于以其左孩子为根的第k-1层结点的个数 + 相对于以其右孩子为根的第k-1层结点的个数。(见图理解)
int SizeKTreeNode(BTNode* root, int k)
{
if (k < 1 || root == NULL)
{
return 0;
}
if (k == 1)
{
return 1;
}
return SizeKTreeNode(root->left, k - 1) + SizeKTreeNode(root->right, k - 1);
}
值为x的结点
子问题:
1.先判断根结点是否是目标结点。
2.再去左子树中寻找。
3.最后去右子树中寻找。
BTNode* FindTreeNode(BTNode* root, BinaryTreeDataType x)
{
if (root == NULL)
{
return NULL;
}
if (root->val == x)//该节点的值与x比较
{
return root;
}
BTNode* left = FindTreeNode(root->left, x);//往左边找
if (left)
{
return left;//表示左边找到了,直接返回,不去找右
}
BTNode* right = FindTreeNode(root->right, x);//往右边找
if (right)
{
return right;
}
return NULL;//左右子树都没有找到
}
树的最大深度
子问题:
1.若为空,则深度为0。
2.若不为空,则树的最大深度 = 左右子树中深度较大的值 + 1
int DepthTree(BTNode* root)
{
if (root == NULL)
{
return 0;
}
int left = DepthTree(root->left);
int right = DepthTree(root->right);
return left > right ? left + 1 : right + 1;//左右边高的加上1(判断二叉树是否是根)}
判断二叉树是否是完全二叉树
实现思路:借助一个队列
1.先入非空根节点,出根节点,同时把根节点的两个字树入队列(空节点也入)。
2.其他节点重复步骤1,如果出到空节点,不在入节点。
3.继续判断队列是否为空,出队列这些节点,如果有非空节点,说明不是完全二叉树,全是空节点,则是完全二叉树。
bool IsComBTree(BTNode* root)
{
queue<BTNode*> q;
if (root != NULL)
{
q.push(root);
}
BTNode* front = NULL;
while (!q.empty())
{
front = q.front();
q.pop();
if (front == NULL)
{
break;//表示出到NULL,跳出循环,不在入数据。
}
q.push(front->left);
q.push(front->right);
}
while (!q.empty())
{
front = q.front();
if (front)
{
return false;//表示队列里面还有非空节点
}
q.pop();
}
return true;}