树
树的定义
由零个或多个节点组成的有限集合,其中有且仅有一个节点,成为树根(root),其余的节点为m个互不相交的有限集合,每个集合本事又是一棵树,称为这棵树的子树。
树的特点
1.是非线性结构,除了根之外,所有节点都有一个直接前驱,但是可能有多个直接后继;
2.树的定义具有递归性,树中还有树
3.树可以为空,即树中节点的个数为0。
树的术语
树根:即树的根节点,特点是没有前驱。
叶子:即终端节点,没有后继。
双亲:即某个节点的直接前驱。
孩子:即某个节点的直接后继。
兄弟:同一个双亲下的节点互称为兄弟。
堂兄弟:即双亲为兄弟的节点,互称为堂兄弟。
节点的度:节点下挂接的子树的个数。
树的度:树中所有节点度的最大值。
节点的层数:从根到该节点的层数,默认树根是第一层。
树的深度(高度):树中所有节点层数最大值。
二叉树
概念:由0或多个节点组成的有限集合,其中由一个根节点以 及2个互不相交的有限集合,左子树和右子树,也就是度为2的树。
二叉树的特点
1.每个节点最多有两个子树,不存在度大于2的节点;
2.二叉树的左右子树次序不能颠倒。
二叉树的性质
1.在二叉树的第i层上,最多有-1个结点
遍历二叉树
1.先构造一个结点类
#include<iostream>
using namespace std;
class biTreeNode//节点类
{
public:
int val;
biTreeNode* left;
biTreeNode* right;
biTreeNode()//构造
{
val = NULL;
left = nullptr;
right = nullptr;
}
biTreeNode(int value)//有参构造
{
val = value;
left = nullptr;
right = nullptr;
}
};
2.创建一颗树
biTreeNode* craetebiTree()//创建树
{
biTreeNode* a = new biTreeNode(1);
biTreeNode* b = new biTreeNode(2);
biTreeNode* c = new biTreeNode(3);
biTreeNode* d = new biTreeNode(4);
biTreeNode* e = new biTreeNode(5);
biTreeNode* f = new biTreeNode(6);
biTreeNode* g = new biTreeNode(7);
biTreeNode* h = new biTreeNode(8);
biTreeNode* i = new biTreeNode(9);
biTreeNode* j = new biTreeNode(10);
a->left = b;
a->right = c;
b->left = d;
b->right = e;
c->left = f;
c->right = g;
d->left = h;
d->right = i;
e->left = j;
return a;//此时返回的a就是指向树根的指针,所以后续遍历的时候,调用这个函数,返回的就是树根的指针,使用root结点接收这个指针
}
3.遍历
遍历分为前序遍历,中序遍历,后序遍历。
先序遍历:先遍历根结点,再遍历左子树,最后遍历右子树;
中序遍历:先遍历左子树,再遍历根结点。最后遍历右子树;
后序遍历:先遍历左子树,再遍历右子树,最后遍历根结点。
其中,这些遍历都是通过函数的递归实现的,遍历主要以根结点来命名具体遍历方式的,比如根结点在中间,就是中序遍历。
求叶子个数的函数思路:先判断是否为空树,如果不为空,判断结点的左子树和右子树是否都为空,如果都为空,则表示这个结点是叶子,左子树的叶子结点个数加右子树的叶子结点个数就是总叶子个数。
求树高度的函数思路:通过递归将左子树的高度和右子树的高度求出,返回较大值,然后加上根结点,就是树的总高度。
void preOrder(biTreeNode* root)//先序遍历
{
if (root == nullptr)
{
return;
}
cout << root->val << " ";
preOrder(root->left);
preOrder(root->right);
}
void inOrder(biTreeNode* root)//中序遍历
{
if (root == nullptr)
{
return;
}
else
{
inOrder(root->left);
cout << root->val << " ";
inOrder(root->right);
}
}
void popOrder(biTreeNode* root)//后序遍历
{
if (root == nullptr)
{
return;
}
else
{
popOrder(root->left);
popOrder(root->right);
cout << root->val << " ";
}
}
int calcaulateLeafNum(biTreeNode* root)//叶子个数
{
if (root == nullptr)
{
return NULL;
}
if (root->left == nullptr && root->right == nullptr)
{
calcaulateLeafNum(root->left);
calcaulateLeafNum(root->right);
return 1;
}
return calcaulateLeafNum(root->left) + calcaulateLeafNum(root->right);
}
void calcaulateLeafNum2(biTreeNode* root, int* a)//无返回值做法
{
if (root == nullptr)
{
return;
}
if (root->left == nullptr && root->right == nullptr)
{
(*a)++;
}
calcaulateLeafNum2(root->left,a);
calcaulateLeafNum2(root->right,a);
}
int binaryTree_height(biTreeNode* root)//树的高度,有返回值做法
{
if (root == nullptr)
{
return 0;
}
else
{
int a = binaryTree_height(root->left);//左子树的高度
int b = binaryTree_height(root->right);//右子树的高度
return max(a, b)+1;//计算左右子树高度的最大值,+1的原因是,左子树为3,右子树为2,需要加上头结点。
}
}
int main()
{
biTreeNode* root = craetebiTree();
preOrder(root);
cout << endl;
inOrder(root);
cout << endl;
popOrder(root);
cout << endl;
cout<<calcaulateLeafNum(root)<<endl;
cout << binaryTree_height(root) << endl;
int a = 0;
calcaulateLeafNum2(root, &a);
return 0;
}