目录

二叉树的存储结构:

链式二叉树的实现

1.二叉树的结构体类型

2.创建二叉树结点

代码实现:

3.二叉树的前序遍历

测试结果:

4.二叉树的中序遍历

测试结果:

5.二叉树的后序遍历

测试结果:

6.求二叉树的总结点个数

错误写法:

所以正确的代码实现:

测试结果:

7.求二叉树的叶子节点个数

测试结果:

8.求二叉树的高度层次

测试结果:

9.求二叉树第K层的节点个数

测试结果:

10.查找二叉树某个节点的值

测试结果:

完整的链式二叉树代码:

.h文件:

.c文件:


二叉树的存储结构:

 1. 顺序存储顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。而现实中使用中只有堆才会使用数组来存储。二叉树顺 序存储在物理上是一个数组,在逻辑上是一颗二叉树。

2. 链式存储 :二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是 链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所 在的链结点的存储地址 。链式结构又分为二叉链和三叉链,三叉比较复杂,所以在下面对二叉树的代码实现用的都是二叉链表的方式进行的实现。

链式二叉树的实现

1.二叉树的结构体类型

typedef int BTDataType;
typedef struct BinaryTreeNode {BTDataType data; //二叉树节点的值struct BinaryTreeNode* left;   //二叉树的左指针——指向它的左孩子struct BinaryTreeNode* right; //二叉树的右指针——指向它的右孩子
}BTNode;    //重定义了二叉树的类型名称为BTNode

2.创建二叉树结点

以下代码是根据该图进行实现:

代码实现:

//创建二叉树
BTNode* TreeCreate() {//动态开辟所需要的结点BTNode* n1 = (BTNode*)malloc(sizeof(BTNode));assert(n1);    //assert作用断言,判断动态开辟是否成功!BTNode* n2 = (BTNode*)malloc(sizeof(BTNode));assert(n2);BTNode* n3 = (BTNode*)malloc(sizeof(BTNode));assert(n3);BTNode* n4 = (BTNode*)malloc(sizeof(BTNode));assert(n4);BTNode* n5 = (BTNode*)malloc(sizeof(BTNode));assert(n5);BTNode* n6 = (BTNode*)malloc(sizeof(BTNode));assert(n6);BTNode* n7 = (BTNode*)malloc(sizeof(BTNode));assert(n7);//创建好后,给各结点赋值n1->data = 1;n2->data = 2;n3->data = 3;n4->data = 4;n5->data = 5;n6->data = 6;n7->data = 7;//给各节点的左右指针指明方向,形成二叉树n1->left = n2;n1->right = n4;n2->left = n3;n2->right = NULL;n3->left = NULL;n3->right = n7;n7->left= NULL;n7->right = NULL;n4->left = n5;n4->right = n6;n5->left = NULL;n5->right =NULL;n6->left = NULL;n6->right = NULL;//形成二叉树后,返回让指针返回根节点return n1;}

3.二叉树的前序遍历

.前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点的操作发生在遍历其左右子树之前。

口诀:先遍历根,再遍历左子树,最后遍历右子树。 

//二叉树的前序遍历
void PreOrder(BTNode* root) {if (root == NULL) {printf("NULL ");return;}//先遍历根printf("%d  ", root->data);PreOrder(root->left);PreOrder(root->right);
}

上图为部分递归图解, 过程:root先指向根节点,打印1,接着进入递归,root->left,指向节点2,打印节点值,再进入递归,root->left,指向节点3,打印3,再进行递归,root->left,发现为空,打印NULL后返回节点3,进而递归root->right,指向节点7,再对7的左右节点进行递归......,注:每次递归完了都会返回上一层,继续执行上一层的下一句代码......

测试结果:


4.二叉树的中序遍历

中序遍历(Inorder Traversal)——访问根结点的操作发生在遍历其左右子树之中(间)。

口诀:先遍历左子树,再遍历根,最后遍历右子树

//二叉树的中序遍历
void InOrder(BTNode* root) {if (root == NULL) {printf("NULL ");return;}//先遍历左子树,再根,再右InOrder(root->left);printf("%d  ", root->data);InOrder(root->right);
}

上图为部分递归图解,过程:root先指向根节点,进入递归,root->left,指向节点2,再进入递归root->left,指向节点3,再进行递归root->left,发现为空,打印NULL后返回节点3,打印节点值3,进而递归root->right,指向节点7,再对7的左右节点进行递归......发现都为空,返回节点3,节点3递归完成,继续返回上一层节点2的递归,打印节点2,进而递归root->right,为空,返回节点2,节点2递归完成,返回节点1,打印节点1,进而递归节点1的root->right......

测试结果:


5.二叉树的后序遍历

后序遍历(Postorder Traversal)——访问根结点的操作发生在遍历其左右子树之后。

口诀:先遍历左子树,再遍历右子树,最后遍历根节点。

//二叉树的后序遍历
void PostOrder(BTNode* root) {if (root == NULL) {printf("NULL ");return;}//先遍历左子树,再右,最后根PostOrder(root->left);PostOrder(root->right);printf("%d  ", root->data);
}

后序遍历,自己画图理解吧~~

测试结果:


6.求二叉树的总结点个数

错误写法:

//统计二叉树的所有节点个数—-错误写法void  BinaryTreeSize2(BTNode* root) {static int count = 0;if (root == NULL)return ;//遇到节点先统计++++count;BinaryTreeSize(root->left);BinaryTreeSize(root->right);}

//使用static延长局部变量的生命周期,出了作用域不会被销毁,仍会累计个数 。但这种静态操作,只能调用一次,多次调用会把上一次的结果也累计上,得出错误的答案,所以这种写法并不可取,链式二叉树大多是递归形式进行定义,那么需要分而治之!将大问题化解成多个小问题,然后各个击破!

举个例子:学校需要清点这两天来到学校的学生和老师人数,需要院长将计算机系和会计系的总人数报上去,那么有两种方法,其一:院长一个班一个班的进行遍历统计,最后报回总人数;其二,院长让两个系的主任去统计,然后两个系的主任让班主任去统计,班主任再让班长去统计各班的人数。院长的任务就是把两个系主任统计出的名单加起来,最后报上去。而第二种方法相比第一种是非常简便的,只需要让级别小的去统计,然后将它们返回的结果相加再报给上级即可。这就是分而治之!!!

所以正确的代码实现:

//统计二叉树的所有节点个数——分而治之(大事化小,小事化了)
int BinaryTreeSize(BTNode* root) {return root == NULL ? 0 : BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}

先统计该节点的左子树部分的节点数,进而统计该节点的右子树部分的节点数,最后把两树相加,再把自己算上即可。

测试结果:


7.求二叉树的叶子节点个数

实现该功能仍是用到了分而治之的算法,先让各个小弟把活干好,我们这个大哥只需要拿到成果即可~哈哈哈!

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

测试结果:


8.求二叉树的高度层次

该功能实现的思路是要计算出左子树层次高度和右子树层次高度,取出较大的那个高度,然后+1就是该二叉树的高度层次。

//计算二叉树的高度层次
int BinaryTreeHigh(BTNode* root) {if (root == NULL)return 0;int leftHigh = BinaryTreeHigh(root->left);int rightHigh = BinaryTreeHigh(root->right);return leftHigh > rightHigh ? leftHigh + 1 : rightHigh + 1;
}

测试结果:


9.求二叉树第K层的节点个数

这个功能也是使用递归实现,求二叉树第K层的节点个数就是求该二叉树的左子树第K-1层的节点个数+该二叉树的右子树第K-1层的节点个数,仍然是递归的核心思路,大问题划分成多个小问题去求解!

//计算二叉树的第K层的节点数
int BinaryTreeKlevel(BTNode* root,int k) {assert(k > 0);if (root == NULL) {    //表明该层无节点return 0;}if (k == 1)        //表明在第一层return 1;//求二叉树的第K层节点就是求它的左右子树的第K-1层节点相加所得return BinaryTreeKlevel(root->left, k - 1) +BinaryTreeKlevel(root->right, k - 1);
}

测试结果:


10.查找二叉树某个节点的值

        我在实习该功能的核心思路是使用先序遍历,先看根节点的值是否和要找的节点值相同,若不相同则使用递归去寻找根的左子树值,左子树部分全部找完也没找到,就去右子树部分去寻找,若两边都没有,则返回空。

/查找二叉树某个节点的值
BTNode* TreeFind(BTNode* root, BTDataType x) {if (root == NULL)return NULL;if (root->data == x)return root;//先从左子树开始BTNode* lret = TreeFind(root->left, x);if (lret)return lret;//找不到后再从右子树开始BTNode* rret = TreeFind(root->right, x);if (rret)return rret;//两边都找不到后,返回空return NULL;
}

测试结果:


11.二叉树的销毁

//销毁二叉树——使用后序遍历,先消除左右子树,最后消除跟节点(从下到上)
void TreeDestory(BTNode* root) {if (root == NULL) {return;}//递归TreeDestory(root->left);TreeDestory(root->right);free(root);root == NULL;
}

该功能的实现:二叉树的销毁也是通过一层一层的向下递归,从下往上去释放节点。

注:不可直接删除根节点,因为二叉树是用链表构成的,删除了根节点,并不能删除它链接的左右子树节点,这些节点仍然存在,从而成为野指针,消耗内存,不可取!!!


完整的链式二叉树代码:

.h文件:

#pragma once
#include<assert.h>
#include<stdlib.h>
#include<stdio.h>typedef int BTDataType;
typedef struct BinaryTreeNode {BTDataType data; //二叉树节点的值struct BinaryTreeNode* left;   //二叉树的左指针——指向它的左孩子struct BinaryTreeNode* right; //二叉树的右指针——指向它的右孩子
}BTNode;//创建二叉树
BTNode* TreeCreate();//二叉树的前序遍历
void PreOrder(BTNode* root);//二叉树的中序遍历
void InOrder(BTNode* root);//二叉树的后序遍历
void PostOrder(BTNode* root);//统计二叉树的所有节点个数
int BinaryTreeSize(BTNode* root);void BinaryTreeSize2(BTNode* root);//统计二叉树的叶子节点个数
int BinaryTreeleaf(BTNode* root);//计算二叉树的高度层次
int BinaryTreeHigh(BTNode* root);//计算二叉树的第K层的节点树
int BinaryTreeKlevel(BTNode* root,int k);//查找二叉树某个节点的值
BTNode* TreeFind(BTNode* root, BTDataType x);

.c文件:

#include"Binary Tree.h"
#define _CRT_SECURE_NO_WARNINGS 1//创建二叉树
BTNode* TreeCreate() {BTNode* n1 = (BTNode*)malloc(sizeof(BTNode));assert(n1);BTNode* n2 = (BTNode*)malloc(sizeof(BTNode));assert(n2);BTNode* n3 = (BTNode*)malloc(sizeof(BTNode));assert(n3);BTNode* n4 = (BTNode*)malloc(sizeof(BTNode));assert(n4);BTNode* n5 = (BTNode*)malloc(sizeof(BTNode));assert(n5);BTNode* n6 = (BTNode*)malloc(sizeof(BTNode));assert(n6);BTNode* n7 = (BTNode*)malloc(sizeof(BTNode));assert(n7);n1->data = 1;n2->data = 2;n3->data = 3;n4->data = 4;n5->data = 5;n6->data = 6;n7->data = 7;n1->left = n2;n1->right = n4;n2->left = n3;n2->right = NULL;n3->left = NULL;n3->right = n7;n7->left= NULL;n7->right = NULL;n4->left = n5;n4->right = n6;n5->left = NULL;n5->right =NULL;n6->left = NULL;n6->right = NULL;return n1;}//二叉树的前序遍历
void PreOrder(BTNode* root) {if (root == NULL) {printf("NULL ");return;}//先遍历根printf("%d  ", root->data);PreOrder(root->left);PreOrder(root->right);
}//二叉树的中序遍历
void InOrder(BTNode* root) {if (root == NULL) {printf("NULL ");return;}//先遍历左子树,再根,再右InOrder(root->left);printf("%d  ", root->data);InOrder(root->right);
}//二叉树的后序遍历
void PostOrder(BTNode* root) {if (root == NULL) {printf("NULL ");return;}//先遍历左子树,再右,最后根PostOrder(root->left);PostOrder(root->right);printf("%d  ", root->data);
}//统计二叉树的所有节点个数——分而治之(大事化小,小事化了)
int BinaryTreeSize(BTNode* root) {return root == NULL ? 0 : BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}//统计二叉树的所有节点个数—-错误写法
static int count = 0;
void  BinaryTreeSize2(BTNode* root) {if (root == NULL)return ;++count;BinaryTreeSize(root->left);BinaryTreeSize(root->right);}//统计二叉树的叶子节点个数
int BinaryTreeleaf(BTNode* root) {if (root == NULL) {return 0;}if (root->left == NULL && root->right == NULL)return 1;return BinaryTreeleaf(root->left) + BinaryTreeleaf(root->right);
}//计算二叉树的高度层次
int BinaryTreeHigh(BTNode* root) {if (root == NULL)return 0;int leftHigh = BinaryTreeHigh(root->left);int rightHigh = BinaryTreeHigh(root->right);return leftHigh > rightHigh ? leftHigh + 1 : rightHigh + 1;
}//计算二叉树的第K层的节点数
int BinaryTreeKlevel(BTNode* root,int k) {assert(k > 0);if (root == NULL) {    //表明该层无节点return 0;}if (k == 1)        //表明在第一层return 1;//求二叉树的第K层节点就是求它的左右子树的第K-1层节点相加所得return BinaryTreeKlevel(root->left, k - 1) +BinaryTreeKlevel(root->right, k - 1);
}//查找二叉树某个节点的值
BTNode* TreeFind(BTNode* root, BTDataType x) {if (root == NULL)return NULL;if (root->data == x)return root;//先从左子树开始BTNode* lret = TreeFind(root->left, x);if (lret)return lret;//找不到后再从右子树开始BTNode* rret = TreeFind(root->right, x);if (rret)return rret;//两边都找不到后,返回空return NULL;
}//销毁二叉树——使用后序遍历,先消除左右子树,最后消除跟节点(从下到上)
void TreeDestory(BTNode* root) {if (root == NULL) {return;}TreeDestory(root->left);TreeDestory(root->right);free(root);root == NULL;
}//主函数
int main() {BTNode* root = TreeCreate();/*printf("前序遍历:");PreOrder(root);printf("\n");*///printf("中序遍历:");//InOrder(root);//printf("\n");/*printf("后序遍历:");PostOrder(root);printf("\n");*/printf("TreeSize:%d \n", BinaryTreeSize(root));printf("TreeSize:%d \n", BinaryTreeSize(root));计算节点个数的错误写法///*printf("节点个数:%d \n", count);//printf("节点个数:%d \n", count);*/printf("TreeLeaf:%d \n", BinaryTreeleaf(root));printf("TreeHigh:%d \n", BinaryTreeHigh(root));printf("Tree K level:%d \n", BinaryTreeKlevel(root, 1));printf("Tree K level:%d \n", BinaryTreeKlevel(root, 2));printf("Tree K level:%d \n", BinaryTreeKlevel(root, 3));printf("Tree K level:%d \n", BinaryTreeKlevel(root, 4));printf("\n");BTNode* ret = TreeFind(root, 3);if (ret)printf("该节点存在,且地址值为:%p\n", ret);elseprintf("该节点在二叉树中不存在!\n");return 0;
}

链式二叉树的代码实现相关推荐

  1. 二叉树(二)----->链式二叉树(上)

    文章的主体内容 1.链式二叉树链式二叉树的表示法 2.二叉树的前中后序遍历思想 3.求二叉树节点的个数及叶子节点的个数及第k层节点数 5.查找二叉树值为x的节点 6.二叉树的层序遍历 7.二叉树的深度 ...

  2. 顺序二叉树(堆)与链式二叉树的C语言实现

    文章目录 树的概念及结构 树的概念 树的相关概念 树的表示 树在实际中的运用 二叉树的概念及结构 二叉树的概念 现实中的二叉树 特殊的二叉树 二叉树的性质 二叉树的存储结构 二叉树的顺序结构及实现 二 ...

  3. 数据结构树状结构链式二叉树

    链式二叉树: 遍历: 前序 中序 后序 下面是具体实现: 1.前序遍历: void PreTraverseLTree(struct LTNode *pT) {if(pT!=NULL){cout< ...

  4. 数据结构初阶——链式二叉树

    目录 树概念及结构 树的概念 树的表示 二叉树概念及结构 概念 特殊二叉树 二叉树的性质 二叉树链式结构及实现 二叉树的简单创建 二叉树的前序遍历 二叉树中序遍历与二叉树后序遍历 求二叉树节点个数 求 ...

  5. php之二叉树,PHP数据结构之实现链式二叉树与遍历

    /******************************************************** * 我写的PHP都是从C语言的数据结构中演化而来****************** ...

  6. 链式二叉树的C语言代码

    #include <stdio.h> #include <malloc.h> //构造数据类型 struct  BTNode{  char data; struct   BTN ...

  7. C_数据结构_链式二叉树

    # include <stdio.h> # include <malloc.h>struct BTNode {int data;struct BTNode * pLchild; ...

  8. 链式二叉树的创建、遍历和遍历算法的应用

    目录

  9. 【C】二叉树--顺序结构(详解堆的实现,topK排序、堆排)、和链式结构(链式结构的遍历、链式结构常见递归操作以及练习题)

    本章我们将引入树的概念并详细介绍二叉树.我们会在介绍顺序二叉树基础上,进一步介绍堆以及堆的实现,并以此为依据详解topK排序.堆排等问题:然后我们会介绍链式二叉树的实现以及各种操作.最后,我们也会给出 ...

最新文章

  1. Spring Boot 3.0.0 发布第一个里程碑版本M1,你的 Java 升到 17 了吗?
  2. 8 - 9 template两大功能 : simple_tag、模板继承
  3. 兼容IE低版本的文件上传解决方案
  4. 进程间通信-共享内存实例
  5. java异步多线程 判断线程状态_java多线程和异步回调
  6. php代码实现文件下载,php实现文件下载的简单代码
  7. [other] 代码量代码复杂度统计-lizard
  8. ios标签控制器怎么用_带故事板的iOS标签栏控制器
  9. python 如何做web界面_python的web实例教程,用python做个简单web界面选什么框架最简单...
  10. PHP连接MSSQL数据库案例,PHPWAMP多个PHP版本连接SQL Server数据库
  11. MD5加盐的一个简单算法
  12. cheerio 获取 outerHtml
  13. 京东物流的区块链创新实践之路 PPT
  14. 如何开发自己的VUE组件库并打包复用
  15. 树莓派安装LibreOffice中文包
  16. java输入日期计算天数_Java输入日期得到天数
  17. 需求与商业模式分析-6-五个课题
  18. Python3 微信支付(小程序支付)V3接口
  19. Self-Attention详解
  20. VSCode配置JAVA开发环境插件安装

热门文章

  1. 分组密码以及分组密码的模式
  2. 强化学习入门——以Q-Learning为实例
  3. 【C++】limits头文件 numeric_limits
  4. IBM P570机器Down,处理解决方案
  5. 功率谱密度的一个小理解
  6. 【Python】Dpark例子分析
  7. 7月14日第壹简报,星期四,农历六月十六
  8. 人民日报申论万能结构
  9. 数据的存储结构有哪些?
  10. html初学者对相对地址,绝对地址的理解