後の配列の最後の3つが、非再帰的及び再帰トラバーサル形態がある前に、シーケンスにおけるプリアンブル、:従来のバイナリツリートラバーサルは、4つを含みます。特別に適合いくつかのトラバーサル方法は、さまざまな機能を実現することができます。
プリアンブルバイナリツリーは、配列に、工程を横断した後に理解することができます。
- 各ノードは、城のようなものである、各ノードは、三辺を有している(何も息子のノードは、空の息子には2つの側面があるように見えることができない)、ちょうど城の他の三つの壁を接続します。
- (いない壁を介して)円経路に沿って散歩を示す左側入口ルートから人が、右流出口のルートに戻ります。
- 各ノード城のために、人々は、三回通過する第一の左側を通過する、第二のパスの下側、右側に第3のパスと、
- あなたが最初にアクセスし、行きがけ、共感として知られ、城の内側を通る前順と後順に渡している二三を訪れたときに男が入りました。
シーケンスは、シーケンスで、後に前再帰的に
プリアンブルは、シーケンスで、後続の再帰形はトラバースINORDER以下の例では、非常に簡単です。
class Solution {
vector<int> ans;
public:
vector<int> inorderTraversal(TreeNode* root) {
if(root){
inorderTraversal(root->left); //遍历左子树
ans.push_back(root->val); //访问操作
inorderTraversal(root->right); //遍历右子树
}
return ans;
}
};
2プリアンブル、順序非再帰形
機能するためには、再帰的なオーバーヘッドの複数の呼び出しの必要性を排除し、独自のスタックを維持することができます。メインプロセスは、彼の息子が彼の息子が空に、そしてポップスタックノードと彼の息子を見るために右で左まで継続的に左をプッシュすることです。(先行順走査あれば、彼は訪問のためにプッシュするとき、)例えば予約限定するには:
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> ans;
stack<TreeNode*> s;
TreeNode *T = root;
while(!s.empty() || T){
while(T){ //若结点非空,则一直将左儿子压栈
s.push(T);
T = T->left;
}
T = s.top();
s.pop();
ans.push_back(T->val); //访问操作
T = T->right;
}
return ans;
}
};
その後の3の非再帰形
非再帰形及び後続のプリアンブルシーケンスわずかに異なります。後順が、第3のノードは、アクセスを通過させる必要があり、その主な理由は、正確に第一及び第二パスノードに対応する、プッシュとポップ操作2です。したがって、トラバーサル順に、ノードが直接スタックをスタックしない、経過第二又は第三の時間を介して確認する必要があることです。なお、第3を介して各ノードかどうかを記録するためのスタックを開くことが可能です。
//对于每一个结点,压栈是第一次经过,瞄一眼发现没被标记过则是第二次经过,瞄一眼发现已经标记过一次则是第三次经过
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> s;
stack<bool> s_flag; //记录每个结点是否被瞄过
TreeNode *T = root;
bool flag;
while(!s.empty() || T!=NULL){
while(T != NULL){
s.push(T);
s_flag.push(false); //将结点压栈的同时做个记录
T = T->left;
}
//瞄一眼栈顶结点,看看是否之前被瞄过
T = s.top();
flag = s_flag.top();
s_flag.pop();
if(flag == false){ //若该结点之前未被瞄过,则将其标记为已瞄
s_flag.push(true);
T = T->right;
}else{ //若该结点之前已被瞄过,则说明是第三次经过,故弹出该结点
res.push_back(T->val);
s.pop();
T = NULL; //避免下一轮中又将T结点压栈
}
}
return res;
}
};
レイヤ4予約限定!
DFS対応する後順が考えられる前に、対応する配列は、BFSを横断すると考えられています。一般的に用いられる方法は、チームに息子ノードにキュー、行チームノードが引き出されるたびに、方法を使用することです。
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> res;
if(!root) return res; //排除空树
int i, N;
queue<TreeNode*> q;
TreeNode *T = root;
//开启循环
q.push(T);
while(!q.empty()){
N = q.size(); //保存每一行的结点个数,起到了各层之间隔板的作用
vector<int> v; //保存这一行的结点值
for(i=0; i<N; i++){
T = q.front();
q.pop();
v.push_back(T->val);
if(T->left) q.push(T->left);
if(T->right) q.push(T->right);
}
res.push_back(v);
}
return res;
}
};
5いくつかのアプリケーションを横断
ツリーの最大深さを求め、最小深さ(トラバーサル配列)
ツリーの右側面図を求める;(トラバーサル配列)
ジグザグトラバーサル配列;(思考トラバーサル順序が、スタックを達成するために、二つの異なる方向の使用)
リーフノードの数、(いくつかの利用可能を横切ります)
(手動導出等再帰処理)とプリアンブルシーケンスプレオーダーバイナリシーケンス決意によって横切ら
百二十から三経路の和(再帰的に)
補足する他のアプリケーション。。。