二叉树其中一层的宽度是指该层最左边非空结点到最右边非空结点的结点数,在非空结点中间的空结点也包含在内。而二叉树的宽度则是指所有层宽度中的最大值。
例如下图二叉树的宽度为4
首先,我们用先序法创建一个二叉链表。既然要求每层的宽度,这里我们便采用层次遍历的方法。但仅这样是不够的,我们该如何区分每一层?答案是:层次遍历的过程中,我们在每一层的后面加上一个空指针NULL,当发现队列的顶端为NULL时,代表这一层已遍历结束,k++,进入下一层。考虑到在非空节点中间的空节点也包含在内,所以,我们采用L来记录走过的结点数,但只有到达一个不为空的结点时,才把L走过的结点数计入W中(若一直为空,则不计入)。
一般的层次遍历:
void LevelPrint_Tree(BiTree T) //层次遍历并打印
{
BiTree p;
queue<BiTree>qu; //定义队列,存放二叉树结点指针(这里使用了STL的queue类型)
qu.push(T); //根节点入队
while (!qu.empty()) {
p = qu.front();
cout << p->data; //访问队首结点
qu.pop(); //队首结点出队
if (p->lchild != NULL) {
qu.push(p->lchild); //若结点有左孩子,则左孩子入队
}
if (p->rchild != NULL) {
qu.push(p->rchild); //若结点有右孩子,则左孩子入队
}
}
}
具体实现,我们来看代码:
# include <iostream>
# include <stdlib.h>
# include <queue>
# define maxn 256
using namespace std;
typedef struct BiTNode {
char data;
struct BiTNode* lchild; //左孩子
struct BiTNode* rchild; //右孩子
}BiTNode, * BiTree;
void Init_Tree(BiTree& T) //初始化
{
T = (BiTNode*)malloc(sizeof(BiTNode));
T->data = '#';
T->lchild = NULL;
T->rchild = NULL;
}
void Create_Tree(BiTree& T) //创建(基于先序顺序)
{
char c;
cin >> c;
if (c == '#') { // # 代表空指针
T = NULL;
}
else { //创建根节点
T = (BiTNode*)malloc(sizeof(BiTNode));
T->data = c;
Create_Tree(T->lchild); //先序创建左分支
Create_Tree(T->rchild); //先序创建右分支
}
}
int W[maxn] = { 0 }; //保存每层的宽度
int L[maxn] = { 0 }; //往后走过的结点数,到下一个不为空的结点为止(若后面全空,走过的步数不计)
int V[maxn] = { 0 }; //判断每一层L是否开始计数
int main()
{
BiTree T;
Init_Tree(T); //初始化
cout << "按先序顺序输入元素:";
Create_Tree(T); //创建
queue<BiTree>Q;
Q.push(T);
Q.push(NULL); //第一层结束,加入空指针
W[1] = 1; //第一层宽度为1
int k = 2; //k代表层数
while (!Q.empty()) {
T = Q.front();
Q.pop();
if (T->lchild || V[k]) {
L[k]++;
V[k] = 1;
if (T->lchild) { //到一个不为空的结点为止,W[k]加上L[k],L[k]归0
Q.push(T->lchild);
W[k] += L[k];
L[k] = 0;
}
}
if (T->rchild || V[k]) {
L[k]++;
V[k] = 1;
if (T->rchild) {
Q.push(T->rchild);
W[k] += L[k];
L[k] = 0;
}
}
if (Q.front() == NULL) { //到下一层,层数加1
k++;
Q.pop();
if (!Q.empty()) {
Q.push(NULL); //每一层后加一个空指针
}
}
}
int width = 0;
for (int i = 1; i <= k; i++) {
width = max(width, L[i]); //取最大宽度
}
cout << "二叉树的宽度为" <<width << endl;
return 0;
}
运行结果:
按先序顺序输入元素:ABD#G###CE##F##
二叉树的宽度为4
以上是我的个人学习成果,很高兴能与大家分享。