在众多的数据结构中,二叉树是一种特殊而重要的结构,有着普遍的应用。二叉树或者是一个结点,或者有且仅有一个结点为二叉树的根,其他结点被分红两个互不相交的子集,一个做为左子集,另外一个做为右子集,每一个子集又是一个二叉树。 ios
遍历一棵二叉树就是按某条搜索路径巡访其中每一个结点,使得每一个结点均被访问一次,并且仅被访问一次。最常使用的有三种遍历的方式: 数据结构
1.前序遍历:若二叉树为空,则空操做;不然先访问根结点,接着前序遍历左子树,最后再前序遍历右子树。 函数
2.中序遍历:若二叉树为空,则空操做;不然先中序遍历左子树,接着访问根结点,最后再前中遍历右子树。 spa
3.后序遍历:若二叉树为空,则空操做;不然前后序遍历左子树,接着后序遍历右子树,最后再访问根结点。 code
例如图(1)所示的二叉树: orm
前序遍历的顺序是ABCD,中序遍历的顺序是CBAD,后序遍历的顺序是CBDA。 ip
对一棵二叉树,若是给出前序遍历和中许遍历的结点访问顺序,那么后序遍历的顺序是惟一肯定的,也很方便地求出来。但若是如今只知道前序遍历和后序遍历的顺序,中序遍历的顺序是不肯定的,例如:前序遍历的顺序是ABCD,然后序遍历的顺序是CBDA,那么就有两课二叉树知足这样的顺序(见图(1)和图(2))。 ci
如今的问题是给定前序遍历和后序遍历的顺序,要求出总共有多少棵不一样形态的二叉树知足这样的遍历顺序。 string
ABCD CBDA
2
能够这么考虑,当且仅当以节点为根的子树(或原树)子节点只有一个,会产生多种解的状况。那么明显,仅仅根据前序和后序遍历的结果,单个的子节点没法肯定左右位置。能够判断有n个这样的节点,那么就可能有2^n种生成树。而这样的节点在本题中的明显特征就是,对应前序遍历路径中的特定节点,它的右面相邻的节点和后序遍历中此节点的左面相邻节点相同。最后注意,利用string的成员函数find()能够节省不少时间。 it
ps:本题还有另外的表示方法,即直接比较对应字符,不过这里采用别人的一种解法,更有意思也更能体会二叉树遍历的特色。
// Problem#: 1210 // Submission#: 1860874 // The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License // URI: http://creativecommons.org/licenses/by-nc-sa/3.0/ // All Copyright reserved by Informatic Lab of Sun Yat-sen University #include <iostream> #include <string> using namespace std; int main(){ string str1,str2; int re = 1; cin >> str1 >> str2; int size = str1.size(); int tmp = size - 1; for( int i=1 ; i<size ; i++ ){ int j = str2.find(str1[i]); if( j==tmp-1 ) re *= 2; tmp = j; } cout << re; return 0; }