简介:树形结构是一种典型的非线性结构,它能够反映元素之间的层次关系和分支关系,树形结构在现实生活中应用很多,比如家族的族谱关系,公司的组织关系等等。
二叉树的基本操作是本文的主要内容。
掌握:学习二叉树结构,首先要掌握二叉树的性质、二叉树的顺序存储结构、二叉树的链式存储结构、二叉树的遍历方式等基本定义。
二叉树可以为空树,也可以为一个根节点加上两棵分别称为左子树和右子树的、互不相交的二叉树组成。是一种有序树(左右不可颠倒),可以缺少其中一棵或两棵子树。
二叉树的链式存储结构定义:
typedef struct BiTNode {
//数据域
TElemType data;
//指向左右孩子指针
struct BiTNode *LChild, *RChild;
}BiTNode, *BiTree;
void inputTElem(TElemType &e){
scanf("%c", &e);
}
status isEmptyElem(TElemType e){
if (e == '#') return OK;
else return ERROR;
}
创建二叉树:
void createBiTree(BiTree &T) {
//按照【先序次序】输入二叉树中结点的值创建二叉树T
TElemType e;
//输入
inputTElem(e);
//判空,若为空建立一个空树
if (isEmptyElem(e)) T = NULL;
else {
//申请一个节点空间
T = (BiTree)malloc(sizeof(BiTree));
//生成根节点
T->data = e;
//先序创建左子树
createBiTree(T->LChild);
//先序创建右子树
createBiTree(T->RChild);
}
}
先序遍历二叉树:
void PreOrderTraverse(BiTree T, void(*visit)(TElemType &e)) {
if (T){
//先访问根节点
visit(T->data);
//遍历左子树
PreOrderTraverse(T->LChild, visit);
//遍历右子树
PreOrderTraverse(T->RChild, visit);
}
}
中序遍历二叉树:
void InOrderTraverse(BiTree T, void(*visit)(TElemType &e)) {
if (T){
InOrderTraverse(T->LChild, visit);
//中间访问节点
visit(T->data);
InOrderTraverse(T->RChild, visit);
}
}
后序遍历二叉树:
void PostOrderTraverse(BiTree T, void(*visit)(TElemType &e)) {
//后序遍历二叉树T的递归算法
if (T){
PostOrderTraverse(T->LChild, visit);
PostOrderTraverse(T->RChild, visit);
//最后访问节点
visit(T->data);
}
}
统计二叉树中叶子节点的个数:
int countLeaf(BiTree T){
//定义两个整形变量分别记录左、右子树的叶子节点数
int countLeft, countRight;
//如果此时T为空树,直接返回0
if (!T) return 0;
//判断此时T是否没有孩子,没有的话直接返回本身1
if (T->LChild == NULL&&T->RChild == NULL) return 1;
//经过两次if,确定有孩子,再次使用countLeaf()计算孩子的叶子节点数
countLeft = countLeaf(T->LChild);
countRight = countLeaf(T->RChild);
//直到全部计算完成返回总和的值
return countLeft + countRight;
}
求二叉树的深度:
int depthBiTree(BiTree T){
//和求叶子节点数是一个原理...分别记录深度
int depthLeft, depthRight;
//如果此时T为空树,就不计算它的深度,返回0
if (!T) return 0;
//只要T此时不是空树就继续使用这个函数往下找,判断T的孩子,孩子的孩子...总会到头...
else {
depthLeft = depthBiTree(T->LChild);
depthRight = depthBiTree(T->RChild);
//看看哪个大就取哪个,加到最后就是深度了
if (depthLeft >= depthRight) return depthLeft + 1;
else return depthRight + 1;
//返回的最后一个就是最终要求的深度
}
}
代码:
#include <stdio.h>
#include <tchar.h>
#include <stdlib.h>
#define ERROR 0
#define OK 1
typedef int status;
typedef struct BiTNode {
//数据域
TElemType data;
//指向左右孩子指针
struct BiTNode *LChild, *RChild;
}BiTNode, *BiTree;
void inputTElem(TElemType &e){
scanf("%c", &e);
}
status isEmptyElem(TElemType e){
if (e == '#') return OK;
else return ERROR;
}
void createBiTree(BiTree &T) {
//按照【先序次序】输入二叉树中结点的值创建二叉树T
TElemType e;
//输入
inputTElem(e);
//判空,若为空建立一个空树
if (isEmptyElem(e)) T = NULL;
else {
//申请一个节点空间
T = (BiTree)malloc(sizeof(BiTree));
//生成根节点
T->data = e;
//先序创建左子树
createBiTree(T->LChild);
//先序创建右子树
createBiTree(T->RChild);
}
}
void PreOrderTraverse(BiTree T, void(*visit)(TElemType &e)) {
if (T){
//先访问根节点
visit(T->data);
//遍历左子树
PreOrderTraverse(T->LChild, visit);
//遍历右子树
PreOrderTraverse(T->RChild, visit);
}
}
void InOrderTraverse(BiTree T, void(*visit)(TElemType &e)) {
if (T){
InOrderTraverse(T->LChild, visit);
//中间访问节点
visit(T->data);
InOrderTraverse(T->RChild, visit);
}
}
void PostOrderTraverse(BiTree T, void(*visit)(TElemType &e)) {
//后序遍历二叉树T的递归算法
if (T){
PostOrderTraverse(T->LChild, visit);
PostOrderTraverse(T->RChild, visit);
//最后访问节点
visit(T->data);
}
}
int countLeaf(BiTree T){
//定义两个整形变量分别记录左、右子树的叶子节点数
int countLeft, countRight;
//如果此时T为空树,直接返回0
if (!T) return 0;
//判断此时T是否没有孩子,没有的话直接返回本身1
if (T->LChild == NULL&&T->RChild == NULL) return 1;
//经过两次if,确定有孩子,再次使用countLeaf()计算孩子的叶子节点数
countLeft = countLeaf(T->LChild);
countRight = countLeaf(T->RChild);
//直到全部计算完成返回总和的值
return countLeft + countRight;
}
int depthBiTree(BiTree T){
//和求叶子节点数是一个原理...分别记录深度
int depthLeft, depthRight;
//如果此时T为空树,就不计算它的深度,返回0
if (!T) return 0;
//只要T此时不是空树就继续使用这个函数往下找,判断T的孩子,孩子的孩子...总会到头...
else {
depthLeft = depthBiTree(T->LChild);
depthRight = depthBiTree(T->RChild);
//看看哪个大就取哪个,加到最后就是深度了
if (depthLeft >= depthRight) return depthLeft + 1;
else return depthRight + 1;
//返回的最后一个就是最终要求的深度
}
}
int main(){
//建立空树
BiTree T;
printf("输入字符序列创建二叉树T:\n");
//创建树T
createBiTree(T);
printf("先序遍历:");
PreOrderTraverse(T, visit);
printf("\n中序遍历:");
InOrderTraverse(T, visit);
printf("\n后序遍历:");
PostOrderTraverse(T, visit);
printf("\n叶子节点数:%d\n", countLeaf(T));
printf("深度:%d\n", depthBiTree(T));
system("pause");
return 0;
}
测试二叉树:
测试输入树:ABD#G###CE##F##
测试结果: