【id:77】【20分】A. DS二叉树—二叉树镜面反转(不使用队列)

题目描述

假设二叉树用二叉链表存储,用先序序列结果创建。输入二叉树的先序序列,请你先创建二叉树,并对树做个镜面反转,再输出反转后的二叉树的先序遍历、中序遍历、后序遍历和层序遍历的序列。所谓镜面反转,是指将所有非叶结点的左右孩子对换。

--程序要求--

若使用C++只能include一个头文件iostream;若使用C语言只能include一个头文件stdio

程序中若include多过一个头文件,不看代码,作0分处理

不允许使用第三方对象或函数实现本题的要求

输入

测试次数t

每组测试数据是一个二叉树的先序遍历序列,#表示空树

输出

对每棵二叉树,输出镜面反转后的先序、中序、后序和层次遍历序列。如果空树,输出四个NULL(后面不加空格)。如下:

NULL

NULL

NULL

NULL

输入样例1

3
41#32###65##7##
AB#C##D##
AB##C##

输出样例1

4 6 7 5 1 3 2 
7 6 5 4 3 2 1 
7 5 6 2 3 1 4 
4 6 1 7 5 3 2 
A D B C 
D A C B 
D C B A 
A D B C 
A C B 
C A B 
C B A 
A C B 

以下是思路 

  镜面反转二叉树很简单,右树变左树,左树变右树即可。

  这题要求只能用iostream头文件,这意味着层次遍历的时候不能用C++自带的队列来做。前中后序遍历倒是比较简单,用递归实现即可。

  那么最大的问题就是层序遍历在不使用队列的情况下该如何实现。这里先来分析层序遍历的特点

1.从根节点开始,先访问左子树(类似前序遍历)

2.逐层向下遍历(说明各个节点应当有自己的level域来存放该节点所在层的编号。

  那么问题就变成了给每个节点的level赋对应的值。并利用前序遍历的结果打印输出。那么对应的Node和Tree的成员应该有以下这些。

#include <iostream>
using namespace std;

class Node
{
public:
	Node* left, * right;
	char data;
	int level;//节点所在层级
	Node() { left = right = NULL;level = 0;data = '-'; }
};

class Tree
{
public:
	Node* root;
	Node** list;//存放前序遍历的结果
	string str;
	int pos;
	int lev = 0;//当前二叉树层级
	int size;
	Tree(string s)
	{
		str = s; pos = 0;size = 0;
		root = create(lev);
		list = new Node * [size + 1];
		pos = 0;
	}
	Node* create(int lev);
	void pre(Node*end);
	void mid(Node* end);
	void last(Node* end);
	void levelp();
};

  给节点找level值可以选择在建树的时候就赋值,也可以选择在前序遍历的时候赋值,这里选择在建树的时候就找到对应的level值。(那么就需要在递归的时候往里头传入一个参数,这个参数就是节点所在层次)。同时只需要换一下建左右树的顺序就能得到对应的镜像二叉树。

Node* Tree::create(int lev)
{
	char temp = str[pos];
	pos++;
	if (temp == '#')
	{

		return NULL;
	}
	else
	{
		size++;
		Node* tmp = new Node();
		tmp->data = temp;
		tmp->level = lev;
		lev++;
		tmp->right = create(lev);
		tmp->left = create(lev);
		return tmp;
	}
}

  前中后序遍历在C++中先序构建二叉树+输出(递归实现)这篇讲过了,这里就不多说了。主要是层次遍历。这里用list存放先序遍历的结果(Node*类型)。再去遍历这个数组即可得到结果。

void Tree::levelp()
{
	int i = 0;//size
	int tmp = 0;//level
	while (i < size)
	{
		for (int j = 0;j < size;j++)
		{
			if (tmp == list[j]->level)
			{
				cout << list[j]->data << " ";
				i++;
			}
		}
		tmp++;
	}
}

以下是代码

#include <iostream>
using namespace std;

class Node
{
public:
	Node* left, * right;
	char data;
	int level;
	Node() { left = right = NULL;level = 0;data = '-'; }
};
class Tree
{
public:
	Node* root;
	Node** list;
	string str;
	int pos;
	int lev;
	int size;
	Tree(string s)
	{
		str = s; pos = 0;size = 0;lev = 0;
		root = create(lev);
		list = new Node * [size + 1];
		pos = 0;
	}
	Node* create(int lev);
	void pre(Node*end);
	void mid(Node* end);
	void last(Node* end);
	void levelp();
};
Node* Tree::create(int lev)
{
	char temp = str[pos];
	pos++;
	if (temp == '#')
	{

		return NULL;
	}
	else
	{
		size++;
		Node* tmp = new Node();
		tmp->data = temp;
		tmp->level = lev;
		lev++;
		tmp->right = create(lev);
		tmp->left = create(lev);
		return tmp;
	}
}
void Tree::pre(Node* end)
{
	if (end)
	{
		cout << end->data << " ";
		list[pos] = end;
		pos++;
		pre(end->left);
		pre(end->right);
	}
}
void Tree::mid(Node* end)
{
	if (end)
	{
		mid(end->left);
		cout << end->data << " ";
		mid(end->right);
	}
}
void Tree::last(Node* end)
{
	if (end)
	{
		last(end->left);
		last(end->right);
		cout << end->data << " ";
	}
}
void Tree::levelp()
{
	int i = 0;//size
	int tmp = 0;//level
	while (i < size)
	{
		for (int j = 0;j < size;j++)
		{
			if (tmp == list[j]->level)
			{
				cout << list[j]->data << " ";
				i++;
			}
		}
		tmp++;
	}
}
int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		string str;
		cin >> str;
		Tree tree(str);
		if (tree.root)
		{
			tree.pre(tree.root);
			cout << endl;
			tree.mid(tree.root);
			cout << endl;
			tree.last(tree.root);
			cout << endl;
			tree.levelp();
			cout << endl;
		}
		else
		{
			for (int i = 0;i <= 3;i++)
			{
				cout << "NULL" << endl;
			}
		}
	}
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值