1.トラバーサルの事前注文
ルート-----左-----右
1.1再帰的なプレオーダートラバーサル
void preOrder1(BinTree *root) //递归前序遍历
{
if(root!=NULL)
{
cout<<root->data<<" ";
preOrder1(root->lchild);
preOrder1(root->rchild);
}
}
1.2非再帰的なプレオーダートラバーサル
前のトラバーサル訪問の順序に従って、最初にルートノードが訪問され、次に左の子と右の子がそれぞれ訪問されます。つまり、どのノードでも、ルートノードと見なすことができるため、直接アクセスできます。訪問後、左側の子が空でない場合、左側のサブツリーは同じルールに従ってアクセスされます。その左側のサブツリー、次に右側のサブツリーにアクセスします。したがって、処理プロセスは次のとおりです。
任意のノードPの場合:
-
ノードPにアクセスし、ノードPをスタックにプッシュします。
-
ノードPの左側の子が空かどうかを判断し、空の場合は、スタックの最上位ノードを取得してポップ操作を実行し、スタックの最上位ノードの右側の子を現在のノードPとして設定し、ループします。 to 1);が空でない場合、Pの左の子を現在のノードPとして設定します。
-
PがNULLでスタックが空になるまで、トラバーサルは終了します。
void preOrder2(BinTree *root) //非递归前序遍历
{
stack<BinTree*> s;
BinTree *p=root;
while(p!=NULL||!s.empty())
{
while(p!=NULL)
{
cout<<p->data<<" ";
s.push(p);
p=p->lchild;
}
if(!s.empty())
{
p=s.top();
s.pop();
p=p->rchild;
}
}
}
Javaバージョン
public void preOrder(TreeNode root) {
Stack<TreeNode> s = new Stack<>();
TreeNode p = root;
while (!s.isEmpty() || p != null) {
while (p != null) {
System.out.println(p.val);
s.push(p);
p = p.left;
}
if (!s.isEmpty()) {
p = s.pop();
p = p.right;
}
}
}
2.順序どおりのトラバーサル
左-----ルート-----右
2.1再帰的なインオーダートラバーサル
void inOrder1(BinTree *root) //递归中序遍历
{
if(root!=NULL)
{
inOrder1(root->lchild);
cout<<root->data<<" ";
inOrder1(root->rchild);
}
}
2.2非再帰的なインオーダートラバーサル
中次走査シーケンスによれば、どのノードでも、最初にその左の子が訪問され、左の子ノードはノードと見なされ、次に左の子ノードがOnlyになるまで、その左の子ノードを訪問し続けます。空のノードにアクセスしてから、同じルールに従って右側のサブツリーにアクセスします。したがって、処理プロセスは次のとおりです。
任意のノードPの場合
-
左の子が空でない場合は、Pをスタックに置き、Pの左の子を現在のPとして設定してから、現在のノードPで同じ処理を実行します。
-
左側の子が空の場合は、スタックの最上位要素を取得してポップ操作を実行し、スタックの最上位ノードにアクセスして、現在のPをスタックの最上位ノードの右側の子として設定します。
-
PがNULLでスタックが空になるまで、トラバーサルは終了します。
void inOrder2(BinTree *root) //非递归中序遍历
{
stack<BinTree*> s;
BinTree *p=root;
while(p!=NULL||!s.empty())
{
while(p!=NULL)
{
s.push(p);
p=p->lchild;
}
if(!s.empty())
{
p=s.top();
cout<<p->data<<" ";
s.pop();
p=p->rchild;
}
}
}
Javaバージョン
public void inOrder(TreeNode root) {
Stack<TreeNode> s = new Stack<>();
TreeNode p = root;
while (!s.isEmpty() || p != null) {
while (p != null) {
s.push(p);
p = p.left;
}
if (!s.isEmpty()) {
p = s.pop();
System.out.println(p.val);
p = p.right;
}
}
}
3.注文後のトラバーサル
左-----右-----ルート
3.1再帰的なポストオーダートラバーサル
void postOrder1(BinTree *root) //递归后序遍历
{
if(root!=NULL)
{
postOrder1(root->lchild);
postOrder1(root->rchild);
cout<<root->data<<" ";
}
}
3.2非再帰的なポストオーダートラバーサル
ルートノードは、左の子と右の子がアクセスした後にのみアクセスできるようにする必要があります。したがって、ノードPの場合、最初にスタックに配置されます。
Pに左子または右子がない場合は、直接アクセスできます。または、Pに左子または右子があるが、左子と右子の両方が訪問されている場合は、ノードに直接アクセスすることもできます。 。
上記の2つのケースでない場合は、Pの右の子と左の子が順番にスタックに入れられ、スタックの最上位の要素が取得されるたびに、右の前に左の子が訪問されるようになります。子、および左の子と右の子の両方がルートノードにあります。前に訪問するポイント。
void postOrder3(BinTree *root) //非递归后序遍历
{
stack<BinTree*> s;
BinTree *cur; //当前结点
BinTree *pre=NULL; //前一次访问的结点
s.push(root);
while(!s.empty())
{
cur=s.top();
if((cur->lchild==NULL&&cur->rchild==NULL)||
(pre!=NULL&&(pre==cur->lchild||pre==cur->rchild)))
{
cout<<cur->data<<" "; //如果当前结点没有孩子结点或者孩子节点都已被访问过
s.pop();
pre=cur;
}
else
{
if(cur->rchild!=NULL)
s.push(cur->rchild);
if(cur->lchild!=NULL)
s.push(cur->lchild);
}
}
}
Javaバージョン
public void postOrder(TreeNode root) {
Stack<TreeNode> s = new Stack<>();
TreeNode cur;
TreeNode pre = null;
s.push(root);
while (!s.isEmpty()) {
cur = s.peek();
if (cur.left == null && cur.right == null ||
(pre != null && (pre == cur.left || pre == cur.right))) {
System.out.println(cur.val);
s.pop();
pre = cur;
} else {
if (cur.right != null) {
s.push(cur.right);
}
if (cur.left != null) {
s.push(cur.left);
}
}
}
}
記事のソース
https://www.cnblogs.com/SHERO-Vae/p/5800363.html