一、遍历二叉树
1.前序遍历
前序遍历,是二叉树遍历的一种,也叫做先根遍历、先序遍历、前序周游,可记做根左右。前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。
void PreOrder(BTNode* root) {
if (!root) {
printf("NULL ");
return;
}
printf("%c ", root->date);
PreOrder(root->left);
PreOrder(root->right);
}
2.中序遍历
中序遍历(LDR)是二叉树遍历的一种,也叫做中根遍历、中序周游。在二叉树中,中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树。代码与前序类似。
3.后序遍历
后序遍历(LRD)是二叉树遍历的一种,后序遍历首先遍历左子树,然后遍历右子树,最后访问根结点,在遍历左、右子树时,仍然先遍历左子树,然后遍历右子树,最后遍历根结点,代码与前序类似。
4.层序遍历
逐层从左到右访问所有节点,先遍历第一层,然后再遍历第二层的,依次下去到最后一层。
思想:利用数据结构队列的性质,先把根节点插入到队列,再把当前节点带出并把非空孩子节点带入队列,队列为空说明遍历结束。
//队列的构建这里不列出
void LevelOrder(BTNode* root) {
QE qe;//建立队列
QueueInit(&qe);
QueuePush(&qe, root);//插入根节点
//队列为空遍历完成
while (!QueueEmpty(&qe)) {
BTNode* front = QueueFront(&qe);
QueuePop(&qe);
printf("%c", front->date);
//带入非空孩子节点
if (front->left) {
QueuePush(&qe, front->left);
}
if (front->right) {
QueuePush(&qe, front->right);
}
}
QueueDestroy(&qe);
}
二、二叉树的基本操作
1.求二叉树节点的数量
int BinaryTreeSize(BTNode* root) {
if (!root) {
return 0;
}
return BinaryTreeSize(root->left) + BinaryTreeSize(root->right)+1 ;
}
2.求二叉树叶子节点的数量
int BinaryTreeLeafSize(BTNode* root) {
if (!root) {
return 0;
}
if (!root->left && !root->right) {
return 1;
}
return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}
3.求二叉树第K层节点数量
int BinaryTreeLeavelKSize(BTNode* root,int k) {
if (!root) {
return 0;
}
if (k == 1) {
return 1;
}
return BinaryTreeLeavelKSize(root->left, k - 1) + BinaryTreeLeavelKSize(root->right, k - 1);
}
4.求二叉树的深度
int BinaryTreeDepth(BTNode* root){
if(!root){
return 0;
}
int left= BinaryTreeDepth(root->left);
int right=BinaryTreeDepth(root->right);
return left>right?left+1:right+1;
}
5.根据值查找二叉树的节点并返回
BTNode* BinaryTreeFind(BTNode* root, BTDateType x) {
if (root == NULL) {
return NULL;
}
if (root->date == x) {
return root;
}
BTNode* left = BinaryTreeFind(root->left, x);
if (left) {
return left;
}
BTNode* right = BinaryTreeFind(root->right, x);
if (right) {
return right;
}
return NULL;
}
6.判断二叉树是否为完全二叉树
思想:与二叉树的层序遍历类似,先把根节点插入到队列,再把当前节点带出并把孩子节点带入队列(孩子节点为空也要带入),当队列首元素为空判断队列内元素是否有非空元素,有则为非完全二叉树,没有则为完全二叉树。
bool IsCmpBinaryTree(BTNode* root) {
QE qe;
QueueInit(&qe);
QueuePush(&qe, root);
while (QueueFront(&qe)) {
BTNode* front = QueueFront(&qe);
QueuePop(&qe);
QueuePush(&qe,front->left);
QueuePush(&qe,front->right);
}
while (!QueueEmpty(&qe)) {
BTNode* front = QueueFront(&qe);
QueuePop(&qe);
if (front) {
return false;
}
}
QueueDestroy(&qe);
return true;
}
7.判断二叉树是否为单值二叉树
思想:从根开始判断与左右节点是否相等
bool isUnivalTree(struct TreeNode* root)
{
if(!root){
return true;
}
if(root->left&&root->val!=root->left->val)
{
return false;
}
if(root->right&&root->val!=root->right->val)
{
return false;
}
return isUnivalTree(root->left)&&isUnivalTree(root->right);
}
8.将二叉树前序遍历的值放入数组
int TreeSize(struct TreeNode* root){
if(root==NULL){
return 0;
}
return TreeSize(root->left)+TreeSize(root->right)+1;
}
void _preorderTraversal(struct TreeNode* root,int*a,int*i){
if(root==NULL){
return ;
}
a[(*i)++]=root->val;
_preorderTraversal(root->left,a,i);
_preorderTraversal(root->right,a,i);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize){
int size=TreeSize(root);//计算树节点个数
int*a=malloc(sizeof(int)*size);
int i=0;
_preorderTraversal(root,a,&i);
*returnSize=size;
return a;
}
9.判断一棵树是否为另一棵树的子树
bool isSame(struct TreeNode* root1, struct TreeNode* root2){
if(root1==root2){
return true;
}
if(!root1||!root2||root1->val!=root2->val){
return false;
}
return isSame(root1->left,root2->left)&&isSame(root1->right,root2->right);
}
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot){
if(!root){
return false;
}
if(isSame(root,subRoot)){
return true;
}
return isSubtree(root->left,subRoot)||isSubtree(root->right,subRoot);
}