目次
1. 事前注文トラバーサル
事前順序トラバーサル: 最初にツリーのルート ノードをトラバースし、次に左側のサブツリーをトラバースし、最後に右側のサブツリーをトラバースします。
事前注文トラバーサル シーケンス: 1 -> 2 -> 4 -> 5 -> 3 -> 6 -> 7
トピックリンク
1. 再帰
部分問題の分解方法
class Solution {
public:
void preOrder(TreeNode* root,vector<int>& str)
{
if(root==NULL)return;
str.push_back(root->val);
preOrder(root->left,str);
preOrder(root->right,str);
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int> str;
preOrder(root,str);
return str;
}
};
2. 非再帰的
アイデア: バイナリ ツリーを 2 つの部分として考えます。1 つの部分は左側のノードで、もう 1 つの部分は左側のノードの右側のサブツリーです。最初にバイナリ ツリーのすべての左側のノードをスタックに入れてから、それらをポップアウトします。このプロセスでは、このノードの右のサブツリーが同じ方法でスタックにプッシュされ、次にスタックから 1 つずつポップアウトされます。
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
TreeNode* cur=root;
vector<int> v;
while(cur||!st.empty())
{
//访问一棵树的开始
// 1、访问左路节点,左路节点入栈,后续一次访问左路节点的右子树
while(cur)
{
v.push_back(cur->val);
st.push(cur);
cur=cur->left;
}
//一次访问左路节点的右子树
TreeNode* top=st.top();
st.pop();
//子问题的方式访问右子树
cur=top->right;
}
return v;
}
};
2 番目、順序どおりの走査
トピックリンク
順序トラバーサル: 最初にツリーの左側のサブツリーをトラバースし、次にルート ノードをトラバースし、最後に右側のサブツリーをトラバースします。 順序
トラバーサル シーケンス: 4 -> 2 -> 5 -> 1 -> 6 -> 3 -> 7
1. 再帰
再帰呼び出しは部分問題を分解します。これは、事前順序トラバーサル再帰と同じ考え方です。
class Solution {
public:
void inorder(TreeNode* root,vector<int>& res)
{
if(root==NULL)return;
inorder(root->left,res);
res.push_back(root->val);
inorder(root->right,res);
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
inorder(root,res);
return res;
}
};
2. 非再帰的
プリオーダートラバーサルと同様に、プリオーダートラバーサルはスタックにプッシュする順序でのプリオーダートラバーサルシーケンスであり、インオーダートラバーサルはスタックをポップする順序でのインオーダートラバーサルシーケンスです。
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
TreeNode* cur=root;
vector<int> v;
while(cur||!st.empty())
{
//访问一棵树的开始
// 1、访问左路节点,左路节点入栈,后续一次访问左路节点的右子树
while(cur)
{
st.push(cur);
cur=cur->left;
}
//一次访问左路节点的右子树
TreeNode* top=st.top();
st.pop();
v.push_back(top->val);
//子问题的方式访问右子树
cur=top->right;
}
return v;
}
};
3. ポストオーダートラバーサル
後続トラバーサル: 最初にツリーの左側のサブツリーをトラバースし、次に右側のサブツリーをトラバースし、最後にルート ノードをトラバースします。 後続の
トラバーサル シーケンス: 4 -> 5 -> 2 -> 6 -> 7 -> 3 -> 1
トピックリンク
1. 再帰
部分問題の分解
class Solution {
public:
void postOrder(TreeNode* root,vector<int>& ret)
{
if(root==NULL)return;
postOrder(root->left,ret);
postOrder(root->right,ret);
ret.push_back(root->val);
}
vector<int> postorderTraversal(TreeNode* root) {
vector<int> ret;
postOrder(root,ret);
return ret;
}
};
2. 非再帰的
後続のトラバーサルの非再帰は、事前順序および順序内トラバーサルの非再帰よりも少し複雑です。以前の事前順序トラバーサルおよび順序内トラバーサルの非再帰アルゴリズムをいくつか改善する必要があります。 , 現在のノードへのアクセスを記録する変数 prev を作成します。現在の左ノードの右サブツリーが空であるか、右サブツリーが訪問されている場合は、現在接続されているノードをスタックからポップアウトする必要があり、スタッキングこのときのシーケンスがその後のトラバーサルシーケンスとなる。
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
TreeNode* cur=root;
TreeNode* prev=NULL;
vector<int> v;
while(cur||!st.empty())
{
//访问一棵树的开始
// 1、访问左路节点,左路节点入栈,后续一次访问左路节点的右子树
while(cur)
{
st.push(cur);
cur=cur->left;
}
TreeNode* top=st.top();
//一个节点右子树为空或者上一个访问节点是右子树的根,说明右子树访问过滤,可以访问根节点了
if(top->right==nullptr||top->right==prev)
{
prev=top;
v.push_back(top->val);
st.pop();
}else cur=top->right;
}
return v;
}
};