一、二叉树是什么?
二叉树是一种每个结点最多只有两个孩子的树。
满二叉树:所有分支结点的度都为2,且所有的叶子结点均在最底层。
完全二叉树:二叉树中度小于2的结点只出现在最后两层,且最底层的叶子结点都依此排列在该层的最左边位置。
二、二叉树的代码实现
Ps:代码中栈和队列的具体操作都是之前文章写的,可自行查看。
1.二叉树的创建
二叉树有两种存储结构:顺序存储和链式存储。(本文用的链式存储)
代码如下(示例):
struct BiNode {
char data;
struct BiNode* lchild, * rchild; //二叉链表
int tag = 0; //用于非递归后序遍历时判断有没有被访问过
BiNode operator = (BiNode& right)
{ //重载=
data = right.data;
lchild = right.lchild;
rchild = right.rchild;
tag = right.tag;
return *this;
}
};
void CreateTree(BiNode*& T) { //采用先序遍历的方式创建
char x;
cin >> x;
if (x == '#') T = NULL;
else
{
T = new BiNode;
T->data = x;
CreateTree(T->lchild);
CreateTree(T->rchild);
}
}
2.二叉树的高度、宽度
代码如下(示例):
int BiNodeDepth(BiNode* T) {
//基于后序顺序的二叉树高度计算
int leftdepth, rigthdepth;
if (T == NULL) return 0;
else
{
leftdepth = BiNodeDepth(T->lchild);
rigthdepth = BiNodeDepth(T->rchild);
return (leftdepth > rigthdepth) ? (leftdepth + 1) : (rigthdepth + 1);//比较该结点右子树和左子树的深度
}
void BiNodeWidth(BiNode* T) {
//求树的宽度
Quene Q;
InitQuene(Q);
int count[10]={0}; //用于存储第几层有几个节点
EnQuene(Q, T);
count[0]=1; //第一层有一个节点
int x = 1;
while (!QueneEmpty(Q))
{
for (int i = 0; i < count[x - 1]; i++)
{//每层有几个结点就执行几次,判断是否该层每个结点都有左右子树
struct BiNode* p = (BiNode*)malloc(sizeof(BiNode));
DelQuene(Q, p);//将队首元素赋值给p
if (p != NULL)
{
if (p->lchild) count[x]++;//若该结点有左孩子则x层的结点数加1
if (p->rchild) count[x]++;
EnQuene(Q, p->lchild);
EnQuene(Q, p->rchild);
}
free(p);
p = NULL;
}
x++;
}
int width = 0;
for (int i = 0; i < x; i++)
{
if (count[i] > width) width = count[i];//找到最大结点数即位宽度
}
cout << "该树的宽度为:" << width << endl;
}
3.二叉树的遍历
(1)先序遍历
根节点->左孩子->右孩子
bool PreOrderTraverse(BiNode* T) {
if (T == NULL) return 0;
cout << T->data << " ";
bool l = PreOrderTraverse(T->lchild);
bool r = PreOrderTraverse(T->rchild);
return r && l;
}
//非递归
void PreOrderTraverse2(BiNode* T) {
Quene Q; Stack S;
InitQuene(Q); InitStack(S);
EnQuene(Q, T);
while (!QueneEmpty(Q) || !StackEmpty(S))
{
struct BiNode *p=(BiNode*)malloc(sizeof(BiNode));
if (!QueneEmpty(Q))
{
DelQuene(Q, p);
if (p != NULL)
{
cout << p->data << " ";
EnQuene(Q, p->lchild);//左孩子入队
PushStack(S, p->rchild);//右孩子入栈
}
}
else
{
PopStack(S, p);
EnQuene(Q, p);
}
free(p);
p = NULL;
}
cout << endl;
//DestoryQuene(Q);
ClearStack(S);
DestoryStack(S);
}
(2)中序遍历
左孩子->根节点->右孩子
bool InOrderTraverse(BiNode* T) {
if (T == NULL) return 0;
bool l = InOrderTraverse(T->lchild);
cout << T->data << " ";
bool r = InOrderTraverse(T->rchild);
return l && r;
}
//非递归
void InOrderTraverse2(BiNode* T) {
Stack S;
InitStack(S);
while (T != NULL)
{
PushStack(S, T);
T = T->lchild;
}
while (!StackEmpty(S))
{
struct BiNode* p = (BiNode*)malloc(sizeof(BiNode));
PopStack(S, p);
cout << p->data << " ";
if (p->rchild != NULL)
{
p = p->rchild;
while (p != NULL)
{
PushStack(S, p);
p = p->lchild;
}
}
free(p);
p = NULL;
}
cout << endl;
ClearStack(S);
DestoryStack(S);
}
(3)后序遍历
左孩子->右孩子->根节点
bool PostOrderTraverse(BiNode* T) {
if (T == NULL) return 0;
bool l = PostOrderTraverse(T->lchild);
bool r = PostOrderTraverse(T->rchild);
cout << T->data << " ";
}
//非递归
void PostOrderTraverse2(BiNode* T) {
Stack S;
InitStack(S);
while (T != NULL)
{
PushStack(S, T);
T = T->lchild;
}
while (!StackEmpty(S))
{
struct BiNode* p = (BiNode*)malloc(sizeof(BiNode));
PopStack(S, p);
if (p->rchild != NULL && p->tag == 0)
{ //如果此节点右孩子存在且没有被访问过
p->tag = 1; //表示该节点已被访问过
PushStack(S, p);
p = p->rchild;
while (p != NULL)
{
PushStack(S, p);
p = p->lchild;
}
}
else
{
cout << p->data << " ";
}
free(p);
p = NULL;
}
}
(4)层次遍历
一层一层遍历,从左往右
void leverOrderTraverse(BiNode* T) {
Quene Q;
InitQuene(Q);
EnQuene(Q, T);
while (!QueneEmpty(Q))
{
struct BiNode* p = (BiNode*)malloc(sizeof(BiNode));
DelQuene(Q, p);
if (p != NULL)
{
cout << p->data << " ";
EnQuene(Q, p->lchild);
EnQuene(Q, p->rchild);
}
free(p);
p = NULL;
}
cout << endl;
}