C++验证二叉树的前序或中序序列化

任意给出一个序列,判断他属不属于二叉树的前序序列,或者还是中序序列,文章采用的是非重构树的方法。
如图:遇到空节点用#表示

实现思路:根据前序遍历的定义:先访问当前节点,再依次访问其左右子树,化成序列为:"9,3,4,#,#,1,#,#,2,#,6,#,#"
中序遍历:先访问根节点的左子树,再访问当前根节点,最后访问根节点的右子树。化成序列为:“#,4,#,3,#,1,#,9,#,2,#,6,#”
那么从定义入手,判断q前序序列,先访问自身,那么首个字符一定是根节点,我们把空节点‘’#’也当成一个没有子节点的根节点,那么他和非空节点的区别就是访问完空节点后,只需占一个位置,后续不用在创建位置,而当访问完非空节点后,既需要删除自身的一个位置,又需要为后续访问它的子节点创建两个位置进行访问,如此一来,把位置数依次放入栈中,占据一个位置后,栈内的头部数据就减一,创建一个位置就push(1),若栈内有0就弹出,按照这个逻辑就实现了前序遍历的原理,若序列保持相应的顺序,则最后栈内的“位置”被占完也就表明他是前序序列。
至于中序序列:只需要每次遍历完左子树后创建两个位置去遍历根节点和右子树,以此类推,就可判断序列是否为中序序列,注意:一开始需要创建一个位置去遍历左子树,最后一个右节点遍历结束后不需要在创建新位置。
#include<iostream>
#include<stack>
#include<string>
using namespace std;
class Solution {
public:
   static bool isValidSerialization(string preorder) {//验证是否是前序序列
        int l = preorder.size();
        stack<int> stk;
        stk.push(1);//初始化要先建立一个位置给根节点
        int i = 0;
        while (i < l) {
            if (stk.empty()) {
                return false;
            }
            if (preorder[i] == ',') {
                i++;
            }
            else if (preorder[i] == '#') {//遇到空节点直接删除一个位置
                stk.top() -= 1;
                if (stk.top() == 0) {
                    stk.pop();
                }
                i++;
            }
            else {
                while (i < l && preorder[i] != ',') {//防止出现多位数
                    i++;
                }
                stk.top() -= 1;
                if (stk.top() == 0) {
                    stk.pop();
                }
                stk.push(2);//遇到非空根节点删除一个位置的同时要创建两个子节点
            }
        }
        return stk.empty();//如果栈中所有位置都被使用完证明序列符合前序序列
    }
   static bool isValid(string inorder) //验证是否是中序序列
   {
       int l = inorder.size();
       stack<int> stk;
       int i = 0;
       stk.push(1);
       while (i < l) 
       {
           if (stk.empty()) {
               return false;
           }
           if (inorder[i] == ',') {
               i++;
           }
           else if (inorder[i] == '#') {//遇到空节点直接删除一个位置,同时创建两个位置分别留给根节点和右子节点
               stk.top() -= 1;
               if (stk.top() == 0) {
                   stk.pop();
               }
               if (i != l - 1) {
                   stk.push(2);               
               }
               i++;           
           }
           else 
           {
               while (i < l &&inorder[i] != ',') {//防止出现多位数
                   i++;
               }             
               stk.top() -= 1;
               if (stk.top() == 0) {
                   stk.pop();
               }         
            }
       }
        return stk.empty();//如果栈中所有位置都被使用完证明序列符合中序序列
   }
};
int main() {
    string s1 = "9,3,4,#,#,1,#,#,2,#,6,#,#";
    cout << Solution::isValidSerialization(s1) << endl;
    string s2 = "9,#,#,1";
    cout << Solution::isValidSerialization(s2) << endl;
    string s3 = "#,13,#,16,#,13,#,16,#,13,#,16,#,13,#";
    cout << Solution::isValid(s3) << endl;

注意:此方法暂时只应用于前序和中序判断,后序和层序遍历数据结构规律分情况所以此方法实现较为难,可以采用重构树的方法去实现。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值