链式二叉树(2)

简介: 链式二叉树(2)



题目&Main函数

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
//二叉树节点结构体
typedef int BTDataType;
typedef struct BinaryTreeNode
{
  BTDataType data;
  struct BinaryTreeNode* left;
  struct BinaryTreeNode* right;//
}BTNode;
//手动建造一个二叉树
//放入数据,左右置为NULL
BTNode* BuyNode(int x)
{
  BTNode* tmp = (BTNode*)malloc(sizeof(BTNode));
  assert(tmp);
  if (tmp == NULL)
  {
    perror("malloc fail");
    return;
  }
  tmp->data = x;
  tmp->left = NULL;
  tmp->right = NULL;
  return tmp;
}
//放入数据链接成树
BTNode* CreatBinaryTree()
{
  BTNode* node1 = BuyNode(1);
  BTNode* node2 = BuyNode(2);
  BTNode* node3 = BuyNode(3);
  BTNode* node4 = BuyNode(4);
  BTNode* node5 = BuyNode(5);
  BTNode* node6 = BuyNode(6);
  //BTNode* node7 = BuyNode(1);
  node1->left = node2;
  node1->right = node4;
  node2->left = node3;
  node4->left = node5;
  node4->right = node6;
  return node1;
}
int main()
{
  BTNode* node = CreatBinaryTree();
  //计算二叉树的节点个数
  //方法1
  int treesize = TreeSize(node);
  printf("%d\n", treesize);
  //方法2——遍历+全局变量/局部变量怎么办?传地址
  TreeSize(node);
  printf("%d\n", size);
  size = 0;
  TreeSize(node);
  printf("%d\n", size);
  //计算二叉树的叶子节点个数
  int leafsize = TreeLeafSize(node);
  printf("%d\n", leafsize);
  //计算二叉树的高度
  int Heightsize = TreeHeight(node);
  printf("%d\n", Heightsize);
  //计算第k层的节点个数
  //int K = TreeLevelK(node);
  //printf("%d\n", K);
}

二叉树节点个数计算实现代码

//计算二叉树的节点个数
//方法1
int TreeSize(BTNode* tree)
{
  if (tree == NULL)
  {
    return 0;
  }
  return TreeSize(tree->left) + TreeSize(tree->right) + 1;
}
//方法2
int size = 0;
void TreeSize(BTNode* root)
{
  if (root == NULL)
  {
    return ;
  }
  size++;
  TreeSize(root->left);
  TreeSize(root->right);
}

方法1&递归

  • 整体思路:根+左子树的节点个数+右子树的节点个数 (包含了只有一个节点1)
  • 返回条件:空树返回0
  • 方法1:递归
int TreeSize(BTNode* tree)
{
  if (tree == NULL)
  {
    return 0;
  }
  return TreeSize(tree->left) + TreeSize(tree->right) + 1;
}

方法2&遍历

  • 放法2:遍历+(size++)
  • 全局变量,不能使用静态局部变量。
  • 全局变量可以在主函数里面修改,作用域是全部函数,生命周期是程序结束
  • 使用全局变量,在主函数每次调用前都必须重新设置为0
  • 静态局部变量是只能在某个函数里面使用,作用域某指定函数,生命周期是程序结束
int size = 0;
void TreeSize(BTNode* root)
{
  if (root == NULL)
  {
    return ;
  }
  size++;
  TreeSize(root->left);
  TreeSize(root->right);
}

Q1

我们使用size局部变量来累计计算节点的个数??

结果:并没有累加上,因为每次调用函数,size都会重新定义

int TreeSize(BTNode* root)
{
    int size = 0;
  if (root == NULL)
  {
    return 0;
  }
  ++size;
  TreeSize(root->left);
  TreeSize(root->right);
  return size;
}
int main()
{
  BTNode* root = CreatBinaryTree();
  int size=TreeSize(root);
  printf("TreeSize:%d\n", size);
  return 0;
}

Q2

❗那我们把size变为静态的局部变量呢?当然不可以,因为静态局部变量生命周期是程序结束,意味着如果我们重复调用多次TreeSize这个函数,那么节点个数会成倍增长。

❗有人提议在main函数把size重新设置为0。当然也是不可以,因为size是静态局部变量,作用域只能在TreeSize函数里面

❗可以使用静态局部变量,但是需要修改的静态局部变量只能把size的地址&size传到main函数之后才可以修改。

❗所以最好就是使用全局变量,并且每次调用完之后都重新设置为0

int TreeSize(BTNode* root)
{
  static int size = 0;
  if (root == NULL)
  {
    return 0;
  }
  ++size;
  TreeSize(root->left);
  TreeSize(root->right);
  return size;
}
int main()
{
  BTNode* root = CreatBinaryTree();
  int size=TreeSize(root);
  printf("TreeSize:%d\n", size);
  size=TreeSize(root);
  printf("TreeSize:%d\n", size);
  size=TreeSize(root);
  printf("TreeSize:%d\n", size);
  /*size = 0;
  TreeSize(root);
  printf("TreeSize:%d\n", size);
  size = 0;
  TreeSize(root);
  printf("TreeSize:%d\n", size);
  size = 0;
  TreeSize(root);
  printf("TreeSize:%d\n", size);*/❌
  return 0;
}

二叉树叶子节点个数计算实现代码

//计算二叉树的叶子节点个数
int TreeLeafSize(BTNode* root)
{
  if (root == NULL)
  {
    return 0;
  }
  if (root->right == NULL && root->left == NULL)
  {
    return 1;
  }
  return TreeLeafSize(root->left)+TreeLeafSize(root->right);
}

递归分析

  • 整体思路:左树的叶子节点+右树的叶子节点
  • 返回条件:若为叶子节点则返回1,若为空树NULL返回0
  • 叶子节点的特质就是左右子树都为NULL

二叉树高度个数计算实现代码

计算二叉树的高度
//写法1
int TreeHeight(BTNode* root)
{
  if (root == NULL)
  {
    return 0;
  }
  int leftHeight= TreeHeight(root->left);
  int rightHeight=TreeHeight(root->right);
  if (leftHeight > rightHeight)
  {
    return leftHeight + 1;
  }
  else//<=
  {
    return rightHeight + 1;
  }
}
//写法2
#include<math.h>
int TreeHeight(BTNode* root)
{
  if (root == NULL)
  {
    return 0;
  }
  return fmax(TreeHeight(root->left), TreeHeight(root->right))+1;
}
//写法3❌
int TreeHeight(BTNode* root)
{
  if (root == NULL)
  {
    return 0;
  }
  return TreeHeight(root->left) > TreeHeight(root->right) ? 
    TreeHeight(root->left) + 1 : 
    TreeHeight(root->right) + 1;
}

递归分析

  • 整体思路:根+(左右子树高的子树)
  • 返回条件:空树NULL返回0

写法1&2

//写法1
int TreeHeight(BTNode* root)
{
  if (root == NULL)
  {
    return 0;
  }
  int leftHeight= TreeHeight(root->left);
  int rightHeight=TreeHeight(root->right);
  if (leftHeight > rightHeight)
  {
    return leftHeight + 1;
  }
  else//<=
  {
    return rightHeight + 1;
  }
}
//写法2
#include<math.h>
int TreeHeight(BTNode* root)
{
  if (root == NULL)
  {
    return 0;
  }
  return fmax(TreeHeight(root->left), TreeHeight(root->right))+1;
}

写法3

写法3在我们OJ题当中是会报错的❗因为调用的次数太多了 ❗

//写法3❌
int TreeHeight(BTNode* root)
{
  if (root == NULL)
  {
    return 0;
  }
  return TreeHeight(root->left) > TreeHeight(root->right) ? 
    TreeHeight(root->left) + 1 : 
    TreeHeight(root->right) + 1;
}

  • 第K层的节点个数&递归
  • 二叉树查找第x个节点
  • 不要不要不要对比代码,学会调试。
  • 注意返回条件NULL 和 0 的区别。
  • 大家可以自己动手画出代码的全部图解。画图理解❗
  • ❗重点在于,左右子树不会同时调用,一般都是先调用完左数,在调用右树

🙂感谢大家的阅读,若有错误和不足,欢迎指正

目录
相关文章
|
2月前
|
C语言
链式二叉树(1)
链式二叉树(1)
28 0
|
2月前
链式二叉树(3)
链式二叉树(3)
23 0
|
3月前
|
DataX
二叉树链式结构的实现(二叉树的遍历以及各种常用功能函数的实现)
二叉树链式结构的实现(二叉树的遍历以及各种常用功能函数的实现)
34 0
|
5月前
|
存储 算法
链式二叉树的基本操作实现(建议收藏!!!)(2)
链式二叉树的基本操作实现(建议收藏!!!)
74 0
|
6月前
二叉树的链式结构
二叉树的链式结构
|
6月前
|
存储
链式二叉树(二叉树看这一篇就够了)
链式二叉树(二叉树看这一篇就够了)
26 0
|
1月前
|
存储
二叉树链式结构的实现和二叉树的遍历以及判断完全二叉树
二叉树链式结构的实现和二叉树的遍历以及判断完全二叉树
22 1
|
30天前
|
存储 算法 安全
数据结构与算法:链式二叉树
上一篇文章我们结束了二叉树的顺序存储,本届内容我们来到二叉树的链式存储!
数据结构与算法:链式二叉树
|
存储 算法
【链式二叉树】数据结构链式二叉树的(万字详解)
【链式二叉树】数据结构链式二叉树的(万字详解)
|
4月前
二叉树链式结构
二叉树链式结构