Title

二叉树的带节点数量输出

题目:二叉树的带节点数量输出

问题描述

给出二叉树的先序遍历输出(空结点用'.')表示,请构造二叉树,并输出二叉树的广义表表示。
此广义表中每个结点均带有一个整数,这个整数表示对应的子树上结点总数。

输入

一行仅由‘.’与大小写字符构成的字符串,该字符串表示二叉树的先序遍历输出。
其中'.'表示空结点,字符串长度不超过100。

输出

在单独一行中二叉树的广义表表示,此广义表中每个结点均带有一个整数,这个整数表示对应的子树上结点总数。
具体格式参考输出样例。

输入样列

ABD...C..

输出样例

A[4](B[2](D[1],),C[1])


解题思路

本题输入是依照二叉树的先序遍历结果输入的,所以需要将二叉树先序遍历的结果转成链表形式的二叉树。然后题目需要求得每个节点的子树节点数,这时候可以考虑通过DFS(深度优先)递归地统计节点的子树节点数。
可以总结为如下几个步骤:

  1. 转化先序遍历为链表形式的树;
  2. 一串DFS递归代码传递节点数量;
  3. 代码的输出是先序输出,需要写一段先序遍历输出的代码。

代码实现

参考代码
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;
			}
		}
	}

有如下输入步骤:

  1. 根据先序序列找出并设置根数,压入栈中;

  2. 根据序列顺序向下搜索,此时序列内容有两种情况:

    2.1. 内容为.号表示为空节点,若k==1则将栈顶元素的左节点设置为NULL并使k=2,若k==2则将栈顶元素的右节点置为NULL并将栈顶元素出栈。

    2.2. 内容非.号表示节点非空,若k==1则将栈顶元素的左节点设置为data不用使k=2,若k==2则将栈顶元素的右节点置为data并将栈顶元素出栈,无论k==1还是k==2都要将孩子节点压入栈中

  3. 重复步骤1,2直到栈非空或者序列读取完毕 unsigned i=1; i<a.size() && !S.empty(); i++

posted @ 2023-06-28 21:45  是胡某某啊  阅读(54)  评论(0)    收藏  举报