openjudge树的转换

照例先上题目

7:树的转换

  • 查看
  • 提交
  • 统计
  • 提问
总时间限制: 
5000ms 
内存限制: 
65536kB
描述

我们都知道用“左儿子右兄弟”的方法可以将一棵一般的树转换为二叉树,如:

    0                             0
  / | \                          /
 1  2  3       ===>             1
   / \                           \
  4   5                           2
                                 / \
                                4   3
                                 \
                                  5

现在请你将一些一般的树用这种方法转换为二叉树,并输出转换前和转换后树的高度。

输入
输入包括多行,最后一行以一个#表示结束。
每行是一个由“u”和“d”组成的字符串,表示一棵树的深度优先搜索信息。比如,dudduduudu可以用来表示上文中的左树,因为搜索过程为:0 Down to 1 Up to 0 Down to 2 Down to 4 Up to 2 Down to 5 Up to 2 Up to 0 Down to 3 Up to 0。
你可以认为每棵树的结点数至少为2,并且不超过10000。
输出
对于每棵树,按如下格式输出转换前和转换后树的高度:
Tree t: h1 => h2
其中t是树的编号(从1开始),h1是转换前树的高度,h2是转换后树的高度。
样例输入
dudduduudu
ddddduuuuu
dddduduuuu
dddduuduuu
#
样例输出
Tree 1: 2 => 4
Tree 2: 5 => 5
Tree 3: 4 => 5
Tree 4: 4 => 4










































  1. 题目描述一棵树的方式是先根遍历。设置一个栈,用于保存父结点,栈底压入整棵树的根结点;栈顶结点始终是当前的父结点。扫描输入字符串,遇到'd',从栈顶取出父结点FA,新建一个结点SON作为FA的儿子,链接起来,并将SON压入栈中,作为新的父结点备用;遇到'u',执行弹栈操作,回溯到上一个父结点。在此过程中,栈可达到的最大尺寸-1就是树的高度。
  2. 根据“左子右兄(left child right sibling)”的规则,当为FA添加儿子时,若FA->lchild为空,那么此时SON是FA的第一个儿子,FA->lchild=SON,若FA->lchild不为空,那么SON是FA->lchild的弟弟,要添加到FA->lchild右子链的最末端。
  3. 采用递归计算转换后的二叉树的高度。
代码清单
#include <iostream>
using namespace std;

#include <stack>

#define MAXN 20010

typedef struct _tnode
{
	int info;
	struct _tnode *lmchild;
	struct _tnode *rsibling;
} tnode;

stack<tnode *> rootstack;

tnode *build_bin_tree(char inputseq[], tnode *root, int *max_stack_sz)
{
	char *p=inputseq;
	int val=1;
	tnode *father, *temp, *current;

	while( *p != '\0' )
	{
		if (*p == 'd')	//一个新的结点
		{
			temp=new tnode;
			temp->info=(val++);
			temp->lmchild=NULL;
			temp->rsibling=NULL;

			father=rootstack.top();

			//temp现在是father的儿子,那么,它是father的left-most-child(lmc)呢,还是lmc的right sibling呢?
			if(father->lmchild == NULL)	//是father的lmc
			{
				father->lmchild=temp;
			}
			else	//是lmc的right sibling
			{
				current=father->lmchild;
				while (current->rsibling != NULL)	current=current->rsibling;
				current->rsibling=temp;
			}
			rootstack.push(temp);

			if(rootstack.size() > (*max_stack_sz))	(*max_stack_sz)=rootstack.size();	//记录栈的最大尺寸
		}
		else
		{
			rootstack.pop();
		}

		++p;
	}

	return root;
}

int bin_tree_layer(tnode *root)	//递归计算转换后二叉树的层数
{
	int left_h, right_h;

	if(root==NULL) return 0;
	else
	{
		left_h = 1 + bin_tree_layer(root->lmchild);
		right_h = 1 + bin_tree_layer(root->rsibling);
		if (left_h > right_h)	return left_h;
		else return right_h;
	}
}

void delete_bin_tree(tnode *root)
{
	if (root != NULL)
	{
		delete_bin_tree(root->lmchild);
		delete_bin_tree(root->rsibling);
		delete root;
		root=NULL;
	}
}

int main()
{
	//freopen("D:\\in.txt", "r", stdin);
	//freopen("D:\\out.txt", "w", stdout);

	tnode *root;
	int max_stack_sz, bt_layers, serial=0;
	char inputseq[MAXN];

	while (1)
	{
		cin.getline(inputseq, MAXN, '\n');

		if(inputseq[0] == '#') break;
			
		//初始化
		++serial;

		root=new tnode;
		root->info=0;
		root->lmchild=NULL;
		root->rsibling=NULL;

		while(!rootstack.empty())	rootstack.pop();
		rootstack.push(root);

		max_stack_sz=1;

		//处理
		root = build_bin_tree(inputseq, root, &max_stack_sz);
		bt_layers = bin_tree_layer(root);

		cout<<"Tree "<<serial<<": "<<(max_stack_sz-1)<<" => "<<(bt_layers-1)<<endl;

		//收尾工作
		delete_bin_tree(root);
	}

	return 0;
}


你可能感兴趣的:(二叉树,树,OpenJudge,左子右兄,树的转换)