(3)二叉树继续由前序得到层序遍历

二叉树继续由前序得到层序遍历

接上一篇:

二叉树由后序(LRD)和中序(LDR)得到前序(DLR)

程序运行

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

题目思路和源代码

/*给定一棵二叉树的后序遍历和中序遍历,
请你输出其层序遍历的序列。这里假设键值
都是互不相等的正整数。
输出格式:
在一行中输出该树的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。
输入样例:
7
2315764  后序
1234567  中序
输出样例:
4163572  层序
*/

/*
DCBHKGFEA 后序
BDCAEHGKF 中序
ABCDEFGHK 前序
ABECFDGHK 层序
思路:根据后序找根节点->分割中序->在分割出来的中序里继续找根节点(这样得到前序,再把前序按照层数归类,就是层序).............

*/

#include<iostream>
#include<string>
using namespace std;

struct Node
{
	char _ch;//某个节点的值
	Node *_next;
	Node(char ch, Node *next = nullptr)
	{
		_ch = ch;
		_next = next;
	}
};

//一个链表用来记录二叉树某一层的节点,因为由后序中序构建前序的时候是先左子树,后右子树,所以在层序遍历里面的位置也是没问题的
class LinkList
{
	public:
		LinkList()
		{
			_head = new Node(' ');
		}

		bool AddatTail(char ch)
		{
			Node *p = _head;
			while (p->_next!= nullptr)//找尾巴
			{
				p = p->_next;
			}
			p->_next = new Node(ch);	
			return true;
		}

		void showLinkList()
		{
			Node *p = _head;
			while (p != nullptr)
			{
				cout << p->_ch;
				p = p->_next;
			}
			cout << endl;
		}

		~LinkList()
		{
			Node *q = _head->_next;
			while (q != nullptr)
			{
				_head->_next = q->_next;
				delete q;
				q = _head->_next;
			}
			delete _head;//释放最后一个节点

		}

	private:
		Node *_head;

};


int depth = 0;//全局变量 记录二叉树的深度(层数)的,在递归调用时改变

void MidSplitToTwoArray(const int mid, const string zhongxv, string &midleft, string &midright)//分割中序字符串
{
	for (int i = 0; i < zhongxv.size(); i++)
	{
		if (i < mid)
			midleft = midleft + zhongxv[i];
		if (i > mid)
			midright = midright + zhongxv[i];
	}//切割中序
}

void HouSplitToTwoArray(const int houxvleftsize, const string houxv, string &houleft, string &houright)//切割后序字符串
{
	for (int i = 0; i <= houxv.size() - 2; i++)//因为最后一位是已经求出来了的根节点
	{
		if (i < houxvleftsize)
			houleft = houleft + houxv[i];
		if (i >= houxvleftsize)
			houright = houright + houxv[i];
	}//切割后序
}


//每次都找出根节点,一批一批的找,好像一不小心写成了得到前序的代码(本来还不知道中序后序得到前序是怎么写的...)
//获得树的深度 并且得到并输出先序遍历的结果
void finddepth(string houxv, string zhongxv, int nowdepth)
{
	//后序找根节点,中序分割出两个数组
	//cout << "当前后序:" << houxv<< endl;
	//cout << "当前中序:" << zhongxv<< endl;
	int num = houxv.size();
	cout << houxv[num - 1];//输出根节点
	nowdepth = nowdepth + 1;
	if (nowdepth > depth)//记录树的深度
		depth = nowdepth;
	//cout << "			根节点" << houxv[num - 1]<< endl;//输出根节点
	if (num > 1)//还可以继续分割,没结束
	{
		int mid = -1;
		for (int i = 0; i < num; i++)
		{
			if (zhongxv[i] == houxv[num - 1])//找到中序里面的分割点
			{
				mid = i;
				break;
			}
		}
		string midleft = "";//左子树中序
		string midright = "";//右子树中序
		string houleft = "";//左子树后序
		string houright = "";//右子树后序
		MidSplitToTwoArray(mid, zhongxv, midleft, midright);//切割中序
		int houxvleftsize = midleft.size();
		HouSplitToTwoArray(houxvleftsize, houxv, houleft, houright);//切割后序

		//cout << "houleft:" << houleft << "		midleft:" << midleft << endl;
		//cout << "houright:" << houright << "		midright:" << midright << endl;


		//cout << endl;

		if (midleft.size() != 0 && houleft.size() != 0)//因为有时候输的后序和中序是不对的 就会出现分割长度不匹配的情况
		//在剩余的节点中重新找根节点
			finddepth(houleft, midleft,nowdepth);
		if (midright.size() != 0 && houright.size() != 0)
			finddepth(houright, midright,nowdepth);
	}


}


//每次都找出根节点,一批一批的找,好像一不小心写成了得到前序的代码(本来还不知道中序后序得到前序是怎么写的...)
//填充层序得的链表数组
void findRoot(string houxv, string zhongxv, LinkList *cengxv, int nowdepth = 0)
{
	//后序找根节点,中序分割出两个数组
	//cout << "当前后序:" << houxv<< endl;
	//cout << "当前中序:" << zhongxv<< endl;
	int num = houxv.size();
	//cout<< houxv[num - 1];//输出根节点
	//cout <<houxv[num-1]<<"层数"<<nowdepth<<endl;
	cengxv[nowdepth].AddatTail(houxv[num - 1]);//写到层序数组里面(比如第一层的 就添加到nowdepth[0]链表里)
	nowdepth = nowdepth + 1;	
	//if (nowdepth > depth)//记录树的深度
		//depth = nowdepth;
	//cout << "			根节点" << houxv[num - 1]<< endl;//输出根节点
	if (num>1)//还可以继续分割,没结束
	{
		int mid=-1;
		for (int i = 0; i < num; i++)
		{
			if (zhongxv[i] == houxv[num - 1])//找到中序里面的分割点
			{
				mid = i;
				break;
			}
		}
		string midleft="";//左子树中序
		string midright="";//右子树中序
		string houleft="";//左子树后序
		string houright="";//右子树后序
		MidSplitToTwoArray(mid,zhongxv,midleft,midright);//切割中序
		int houxvleftsize = midleft.size();
		HouSplitToTwoArray(houxvleftsize,houxv,houleft,houright);//切割后序
		//cout << "houleft:" << houleft << "		midleft:" << midleft << endl;
		//cout << "houright:" << houright << "		midright:" << midright << endl;
		
		
		//cout << endl;

		if (midleft.size() != 0 && houleft.size() != 0)//因为有时候输的后序和中序是不对的 就会出现分割长度不匹配的情况
		//在剩余的节点中重新找根节点
			findRoot(houleft, midleft, cengxv, nowdepth);
		if (midright.size()!=0 && houright.size()!= 0)
			findRoot(houright, midright, cengxv,nowdepth);
	}
	
	
}




int main()
{
	string houxv;
	string zhongxv;
	cout << "请输入二叉树的后序遍历:";
	getline(cin, houxv);
	cout << "请输入二叉树的中序遍历:";
	getline(cin, zhongxv);

	if (houxv != "" && zhongxv != "" && houxv.size() == zhongxv.size())
	{
		int nowdepth = 0;//当前节点所在二叉树的深度
		cout << "得到的先序遍历:";

		//感觉不知不觉写出了 由 后序 中序 得到前序遍历...
		finddepth(houxv, zhongxv, nowdepth);//获得树的深度(层数)
		
		cout << endl << "二叉树的深度为:" << depth << endl;
		LinkList *cengxv = new LinkList[depth];//装很多个链表的数组,每个数组元素是一个链表的头指针,包含二叉树某一层的全部节点
		findRoot(houxv, zhongxv, cengxv, 0);//填充层序数组(其实是前序 按层分类是没问题的 是能保证从左到右的)
		cout << "层序遍历结果:" << endl;
		for (int ceng = 0; ceng < depth; ceng++)
		{
			cengxv[ceng].showLinkList();
		}
		delete [] cengxv;
	}
	cin.get();
	
	return 0;
}

总结

1.这几天写了二叉树的创建和遍历
2.二叉树又后序中序得到前序
3.二叉树由前序得到层序
总体顺序应该就是 中序+前序 —> 前序,前序—>层序

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值