コンテンツ
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.バイナリツリーのシリアル化と逆シリアル化
トピックの説明:
/** * 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));
二分木と二分木の間で変換する
問題解決のアイデア:
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; }