二叉树的带节点数量输出
题目:二叉树的带节点数量输出
问题描述
给出二叉树的先序遍历输出(空结点用'.')表示,请构造二叉树,并输出二叉树的广义表表示。
此广义表中每个结点均带有一个整数,这个整数表示对应的子树上结点总数。
输入
一行仅由‘.’与大小写字符构成的字符串,该字符串表示二叉树的先序遍历输出。
其中'.'表示空结点,字符串长度不超过100。
输出
在单独一行中二叉树的广义表表示,此广义表中每个结点均带有一个整数,这个整数表示对应的子树上结点总数。
具体格式参考输出样例。
输入样列
ABD...C..
输出样例
A[4](B[2](D[1],),C[1])
解题思路
本题输入是依照二叉树的先序遍历结果输入的,所以需要将二叉树先序遍历的结果转成链表形式的二叉树。然后题目需要求得每个节点的子树节点数,这时候可以考虑通过DFS(深度优先)递归地统计节点的子树节点数。
可以总结为如下几个步骤:
- 转化先序遍历为链表形式的树;
- 一串DFS递归代码传递节点数量;
- 代码的输出是先序输出,需要写一段先序遍历输出的代码。
代码实现
参考代码
Click For Code
#include <bits/stdc++.h>
using namespace std;
typedef struct tree {
char data;
tree* right;
tree* left;
int cnt;
}*BTree,BTNode;
int getnum(BTree root) {
if(root==NULL)
return 0;
root->cnt=getnum(root->left)+getnum(root->right)+1;
return root->cnt;
}
void preorder(BTree root) {
if(root ==NULL)
return ;
if(root !=NULL)
cout<<root->data<<'['<<root->cnt<<']';
if(root->left!=NULL || root->right!=NULL) {
cout<<'(';
preorder(root->left);
cout<<',';
preorder(root->right);
cout<<')';
}
}
int main() {
/*ABD...C..*/
stack <BTNode*> S;
string a;
cin>>a;
BTree root=(BTree)malloc(sizeof(BTNode));
root->right=NULL;
root->left=NULL;
if(a[0]!='.')
root->data=a[0];
else {
printf("\n");
exit(0);
}
S.push(root);
int k=1;
for(unsigned i=1; i<a.size() && !S.empty(); i++) {
if(a[i]=='.') {
if(k==1) {
S.top()->left=NULL;
k=2;
} else if(k==2) {
S.top()->right=NULL;
S.pop();
}
} else {
BTree p=(BTree)malloc(sizeof(BTNode));
p->right=NULL;
p->left=NULL;
p->data=a[i];
if(k==1) {
S.top()->left=p;
S.push(p);
} else if(k==2) {
S.top()->right=p;
S.pop();
S.push(p);
k=1;
}
}
}
getnum(root);
preorder(root);
printf("\n");
return 0;
}
代码详解
二叉树结构体形式
typedef struct tree {
char data;//节点数据
tree* right;//右子树
tree* left;//左子树
int cnt;//节点数量
}*BTree,BTNode;
DFS求节点数量函数
int getnum(BTree root) {
if(root==NULL)//设置终止点
return 0;
root->cnt=getnum(root->left)+getnum(root->right)+1;//节点数等于左子树数量加右子树数量加他本身
return root->cnt;//递归传参
}
输出函数
void preorder(BTree root) {
if(root ==NULL)
return ;
if(root !=NULL)
cout<<root->data<<'['<<root->cnt<<']';
if(root->left!=NULL || root->right!=NULL) {
cout<<'(';
preorder(root->left);
cout<<',';
preorder(root->right);
cout<<')';
}
}
这是按照题目要求的格式输出——在先序遍历输出的基础上在每个非空节点输出[节点数]。
先序遍历序列输入函数
stack <BTNode*> S;//设置栈
string a;
cin>>a;
BTree root=(BTree)malloc(sizeof(BTNode));
root->right=NULL;
root->left=NULL;
if(a[0]!='.')
root->data=a[0];
else {
printf("\n");
exit(0);
}
S.push(root);
//初始化树根
int k=1;//左右子树的标志
for(unsigned i=1; i<a.size() && !S.empty(); i++) {
if(a[i]=='.') {
if(k==1) {
S.top()->left=NULL;
k=2;
} else if(k==2) {
S.top()->right=NULL;
S.pop();
}
} else {
BTree p=(BTree)malloc(sizeof(BTNode));
p->right=NULL;
p->left=NULL;
p->data=a[i];
if(k==1) {
S.top()->left=p;
S.push(p);
} else if(k==2) {
S.top()->right=p;
S.pop();
S.push(p);
k=1;
}
}
}
有如下输入步骤:
-
根据先序序列找出并设置根数,压入栈中;
-
根据序列顺序向下搜索,此时序列内容有两种情况:
2.1. 内容为.号表示为空节点,若k==1则将栈顶元素的左节点设置为NULL并使k=2,若k==2则将栈顶元素的右节点置为NULL并将栈顶元素出栈。
2.2. 内容非.号表示节点非空,若k==1则将栈顶元素的左节点设置为data,不用使k=2,若k==2则将栈顶元素的右节点置为data并将栈顶元素出栈,无论k==1还是k==2都要将孩子节点压入栈中。 -
重复步骤1,2直到栈非空或者序列读取完毕
unsigned i=1; i<a.size() && !S.empty(); i++。

浙公网安备 33010602011771号