您的当前位置:首页正文

【算法】满二叉树,已知其先序序列求后续序列 C++实现

2024-12-03 来源:个人技术集锦

分析

       正常来说只是知道一个二叉树的先序遍历是无法确定一颗二叉树的,但是作为一棵满二叉树,树的形态确定了,先序遍历的顺序固定为“根左右”的条件下,二叉树也就得以确定。
       那么在满二叉树的情况下,如何通过先序遍历得到后续遍历呢?让我们先进行下面的分析

实例分析

通常情况下,我们进先序遍历,一定是从根出发,于是这个根便是整个序列中的“头部”:
               a |  bdecfg
去掉“头部”以后,剩下的部分由左右两个子树构成。因为先序是根左右的次序,观察&思索也可以发现——剩下的部分从中间等分刚好可以得到这颗树的左右两个子树部分
               bde  |  cfg
化分出来的两个子序列也是子树的先序遍历:
               b |  de               c |  fg

于是就形成一个“套娃”。然后首先会做出的反应就是递归。

实现思路

       既然已经确定使用递归了,现在的关键就是:怎么递归、在哪里使用递归、递归做什么以及递归结束的条件(也就是寻找最小的子问题)。
       通过上述实例的分析,整个满二叉树先序遍历的序列可以的流程为:根->左子树->右子树;每颗子树的流程也是:根->左子树->右子树。现在要获取的是后续遍历,在不耗费额外空间时间重构整棵树的条件下,把这个过程改为:左子树->右子树->根。
       在先序序列中如何体现 左子树->右子树->根 的流程呢?不妨在草稿纸上用刚刚的实例看看:

后序(左右根):((de) b)->((fg)c)-> a

可以发现实际上就是把序列分成:头部、左部、右部,然后按照:左部——右部——头部 的顺序输出。头部只有一个字符,左右部本身视作一个新的先序序列再次划分三部。
       划到后面,左右部只剩下三个字符组成的先序,此时最后一次化分,可以得到只有头部的先序序列,只需要输出头部就可以了,然后逐步回代,因为子树的头输出过了,组成大树以后,其左右子树也就已经完成的输出,也只需要输出头部即可。

于是就有
化分函数(树先序序列 ){
    if(序列数量大于一个){
        化分函数(左子树先序序列);
        化分函数(右子树先序序列);
    }
    输出根(头部序列);
}

代码实现

#include <iostream>
//#include<cmath>
using namespace std;

#define GET_ARRAY_LEN(array, len) { len = sizeof(array)/sizeof(array[0]);}
//获取数组长度宏


/**
* @a           目标数组
* @begin  子树开始的下标
* @end    子树结束的下标
**/
void preToPost(char a[],
	int begin,
	int end
	) {
	char root = a[begin];   //暂存根,子树遍历完后最后输出
	
	if (begin + 1 <= end) {
		begin = begin + 1;//左端+1(把根节点独立出来)
		
		//此时左子树从begin+1位开始,到(begin+end)/2)结束
		preToPost(a, begin,((begin+end)/2)); //左子树

        //此时右子树从((begin+end)/2) + 1)位开始,到end结束
		preToPost(a, (((begin+end)/2) + 1), end); //右子树
	}
	cout << root;  //输出根

}

void main() {
	//测试数据
	//char a[] = { 'a','b','d','h','i','e','j','k','c','f','l','m','g','n','o' };  
	char a[] = { 'a','b','d','e','c','f','g' };
	int length;  //字符数组长度
	
	/*
	这里可以添加一个判断序列数量是否满足满二叉树的判定
	if (  ) {
	   cout<<"输出数据不满足满二叉树条件"<<endl;
		return ;// 判断是否满足满二叉树的条件
	}*/
	
	GET_ARRAY_LEN(a, length); //调用写好的宏得到数组长度
	
	//测试数据输出
	cout<<"先序遍历为:"<<endl;
	for (int i = 0;i < length;i++)
		cout << a[i];
	cout << endl;
	
	cout<<"后序遍历为:"<<endl;
	preToPost(a, 0, length - 1);
	cout << endl << endl << endl << endl;
}

测试结果

显示全文