データ構造のバイナリツリーのシリアル化と逆シリアル化(コードの実装を含む)

コンテンツ

1.二分木を再構築します 

2.バイナリツリーのシリアル化と逆シリアル化


1.二分木を再構築します 

二分木探索

トピックの説明:

 問題解決のアイデア:

1.プレオーダートラバーサルシーケンスの空のノードは「#」で表されているため、バイナリツリーを再帰的に復元できます。「#」が検出された場合はnullptrを返し、それ以外の場合は新しいヘッドノードを作成してから再帰的に構築します。左側のサブツリーと右側のサブツリーは、構築が完了した後、ヘッドノードを返します。

例として、シーケンスabc ## d ###を取り上げます(最後の#は下に置くことができません)

1.最初にヘッドノードに移動し、ノードを作成するのに空ではないことを確認します。

次に、左側のサブツリーを再帰的に作成してから、右側のサブツリーを再帰的に作成します。bに来るのは#createノードbではありません(私は1つ少ない#sorryを書きました)

 

次のノードに移動し、ノードcを作成するのが空ではないことを確認します。

次のノードに来たとき、#同様に次のノードも#空に戻り、cが作成されてbチェーンに戻されたことがわかりました。写真では、事前にリンクしました。外観のために:

 次に、次のノードに移動して、次ではない空の作成を見つけます。

次に、空のスペースを作成します(以前は#を書き留めることができなかったため)。同じことが次の場合にも当てはまります。

 

 対応するコード:

#include<string>
#include<iostream>
using namespace std;
class TreeNode{
  public:
    
   void Inorder(TreeNode*root){
        if(!root)return;
       Inorder(root->_left );
       cout<<root->val<<" ";
       Inorder(root->_right);
    }
    
    TreeNode(char ch)
    :_left(nullptr)
    ,_right(nullptr)
    ,val(ch)
    {}
    TreeNode*_left;
    TreeNode*_right;
    char val;
};

  TreeNode*CreatTree(const string&s,int &i){
              if(s[i]=='#'){//返回空
                  i++;
                  return nullptr;
              }
      
      TreeNode*root=new TreeNode(s[i++]);
      root->_left=CreatTree(s,i);//构建左树
      root->_right=CreatTree(s,i);//构建右树
      return root;//返回根节点
      
  }

int main(){
    string s;
    cin>>s;
    int i=0;
    TreeNode*root=CreatTree(s,i);
    root->Inorder(root);
    
    
}

2.バイナリツリーのシリアル化と逆シリアル化

297.バイナリツリーのシリアル化と逆シリアル化-LeetCode(leetcode-cn.com)

トピックの説明:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Codec {
public:

    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        if(!root){
            return "#";
        }
    return to_string(root->val)+" "+serialize(root->left)+" "+serialize(root->right);//转换字符串
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data){
        istringstream ss(data);//分割字符串
      return buildTree(ss);
    }
    TreeNode*buildTree(istringstream&ss){
        string str;
        ss>>str;//读入字符串
        if(str=="#"){
         return NULL;
        }
        TreeNode*root=new TreeNode(stoi(str));//构建根节点
        root->left=buildTree(ss);//再构建左子树
        root->right=buildTree(ss);//构建右子树
        return root;//返回根节点
    }

};

// Your Codec object will be instantiated and called as such:
// Codec ser, deser;
// TreeNode* ans = deser.deserialize(ser.serialize(root));

問題解決のアイデア:

最初に文字列を上記の質問の形式に変換してから、上記の質問の方法に従って復元できます。

対応するコード:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Codec {
public:

    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        if(!root){
            return "#";
        }
    return to_string(root->val)+" "+serialize(root->left)+" "+serialize(root->right);//转换字符串
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data){
        istringstream ss(data);//分割字符串
      return buildTree(ss);
    }
    TreeNode*buildTree(istringstream&ss){
        string str;
        ss>>str;//读入字符串
        if(str=="#"){
         return NULL;
        }
        TreeNode*root=new TreeNode(stoi(str));//构建根节点
        root->left=buildTree(ss);//再构建左子树
        root->right=buildTree(ss);//构建右子树
        return root;//返回根节点
    }

};

// Your Codec object will be instantiated and called as such:
// Codec ser, deser;
// TreeNode* ans = deser.deserialize(ser.serialize(root));

方法2:

レイヤーオーダートラバーサル:最初に、レイヤーオーダートラバーサルの方法に従って文字列にシリアル化します。デシリアライズする場合:最初に文字列が#であるかどうかを判断し、空を返し、空でない場合は最初にヘッドノードを作成します

そして、それをキューに入れます。左と右の子を作成します。左の子が空でない場合はキューに追加し、右の子が空でない場合はキューに追加し、上記のプロセスを繰り返して最後に追加します。ルートノードを返すことができます。

対応するコード:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Codec {
public:

    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
         string ans;
        if(root==NULL){
          return "#";
        }
    
        queue<TreeNode*>q;
        ans+=to_string(root->val);
        ans+=" ";//以空格作为分隔
        q.push(root);//将节点放入队列中
        while(!q.empty()){
           TreeNode*node=q.front();//取出头部数据
           q.pop();
           if(node->left){//左不为空
               q.push(node->left);//入站
               ans+=to_string(node->left->val);//将左孩子的值加入到字符串中
               ans+=" ";//以空格分隔
           }

           else{//空用#代表
               ans+="#";
               ans+=" ";
           }

           if(node->right){//右树不为空同理
               q.push(node->right);
               ans+=to_string(node->right->val);
               ans+=" ";
           }

           else{
               ans+="#";
               ans+=" ";
           }

        }

          return ans;//将字符串返回

    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        if(data=="#")return NULL;//如果确定是空树直接返回
    
        istringstream ss(data);//将字符串以空格分割
        vector<string>ans;
        string tmp;
        while(ss>>tmp){//将字符串放入容器中
            ans.push_back(tmp);
        }
        int i=0;
        TreeNode*root=new TreeNode(stoi(ans[i++]));//构建头节点
        queue<TreeNode*>q;
        q.push(root);//放入队列中
        while(!q.empty()){
            auto node=q.front();//取出头节点
            q.pop();
              if(ans[i]!="#")//如果不为空
             node->left=new TreeNode(stoi(ans[i]));//构建左子树
             else
             node->left=NULL;//否则就指向空
             i++;//i往后面走
            if(ans[i]!="#")//构建右子树
            node->right=new TreeNode(stoi(ans[i]));
            else
            node->right=NULL;
              i++;
            if(node->left){//不为空则继续放入队列中
                q.push(node->left);
            }
            if(node->right){
                q.push(node->right);
            }

        }
        return root;
    }
};

// Your Codec object will be instantiated and called as such:
// Codec ser, deser;
// TreeNode* ans = deser.deserialize(ser.serialize(root));

二分木と二分木の間で変換する

431. N-aryツリーをバイナリツリーにエンコードします-LeetCode(leetcode-cn.com)

問題解決のアイデア:

n-aryツリーのすべての子ノードを左側のツリーの右側の境界に配置します。元に戻すときは、最初に現在のノードを構築し、その子ノードを再帰的に構築します。詳細については、次のコードを参照してください。

TreeNode* encode(Node* root) {
    if (root == NULL)
        return NULL;
    TreeNode* head = new TreeNode(root->val);
    head->left = en(root->children);
    return head;
}
TreeNode* en(vector<Node*>child) {
    TreeNode* head = nullptr;
    TreeNode* cur = nullptr;
    for (auto x : child) {
        TreeNode* tNode = new TreeNode(x->val);
        if (head == nullptr)
            head = tNode;
        else
            cur->right = tNode;
        
        cur = tNode;
        cur->left = en(x->children);//将左树右边界的头返回
    }
    return head;
}

Node* decode(TreeNode* root) {
    if (root == nullptr)
        return nullptr;
    return new Node(root->val, de(root->left));
}
vector<Node*>de(TreeNode* root) {
    vector<Node*>child;
    while (root) {
        Node* cur = new Node(root->val, de(root->left));//构建其孩子节点
        child.push_back(cur);
        root = root->right;
    }
    return child;
}

おすすめ

転載: blog.csdn.net/qq_56999918/article/details/123468355