web-dev-qa-db-ja.com

プレオーダーからポストオーダーへのトラバーサル

二分探索木の事前順序走査が6、2、1、4、3、7、10、9、11である場合、どのように後順序走査を取得しますか?

21
Bobj-C

ツリーの事前順序走査が提供されます。これは、出力、左への走査、右への走査によって構成されます。

ポストオーダートラバーサルはBSTから取得されるため、数字を並べ替えることにより、ポストオーダートラバーサルからインオーダートラバーサル(左へのトラバース、出力、右へのトラバース)を推測できます。あなたの例では、順序通りの走査は1、2、3、4、6、7、9、10、11です。

2つのトラバーサルから、元のツリーを構築できます。このために、より簡単な例を使用してみましょう。

  • 先行予約:2、1、4、3
  • 順番:1、2、3、4

事前順序トラバーサルにより、ツリーのルートは2になります。順序トラバーサルは、1が左のサブツリーに、3、4が右のサブツリーに落ちることを示しています。左のサブツリーの構造は、単一の要素を含んでいるので簡単です。右側のサブツリーの事前順序トラバーサルは、元の事前順序トラバーサルからこのサブツリーの要素の順序を取得することにより推定されます:4、3.これから、右側のサブツリーのルートは4であり、順序通りの走査(3、4)から、3が左のサブツリーに分類されることがわかります。最終的なツリーは次のようになります。

  2
 / \
1   4
   /
  3

ツリー構造を使用すると、ツリーをたどることで、左から右、右から右、出力という順序でトラバーサルを取得できます。この例では、ポストオーダートラバーサルは1、3、4、2です。

アルゴリズムを一般化するには:

  1. 事前順序走査の最初の要素は、ツリーのルートです。ルートよりも小さい要素が左のサブツリーを形成します。ルートよりも大きい要素が正しいサブツリーを形成します。
  2. 手順1を使用して、元の事前順序トラバースに現れる順序で配置されたサブツリーにある要素で構成される事前順序トラバーサルを使用して、左および右のサブツリーの構造を見つけます。
  3. 結果のツリーをpost-orderでトラバースして、指定されたpre-orderトラバーサルに関連付けられたpost-orderトラバーサルを取得します。

上記のアルゴリズムを使用すると、質問の予約順走査に関連付けられた予約順走査は、1、3、4、2、9、11、10、7、6です。

28
marcog

先行予約 =現在のノード、左サブツリー、右サブツリーの順にバイナリツリーの値を出力します。

Post-order =左サブツリー、右サブツリー、現在のノードの順にバイナリツリーの値を出力します。

バイナリsearchツリーでは、左側のサブツリーのすべてのノードの値は現在のノードの値よりも小さくなります。正しいサブツリーも同様です。したがって、バイナリ検索ツリーの事前順序ダンプの開始(つまり、そのルートノードの値)がわかっている場合、ダンプ全体をルートノード値、左サブツリーのノードの値、および右側のサブツリーのノード。

ツリーを後順で出力するには、再帰と出力の並べ替えが適用されます。このタスクは読者に任されています。

9
Ondrej Tucny

Ondrej Tucnyの回答に基づきます。 BSTのみに有効
例:

     20  
    /  \  
   10  30  
   /\    \  
  6  15   35  

予約注文= 20 10 6 15 30 35
投稿= 6 15 10 35 30 20

BSTの場合、事前予約トラバーサル。配列の最初の要素は20です。これはツリーのルートです。配列内の20未満のすべての数値は左のサブツリーを形成し、大きな数値は右のサブツリーを形成します。

//N = number of nodes in BST (size of traversal array)
int post[N] = {0}; 
int i =0;

void PretoPost(int pre[],int l,int r){
  if(l==r){post[i++] = pre[l]; return;}
  //pre[l] is root
  //Divide array in lesser numbers and greater numbers and then call this function on them recursively  
  for(int j=l+1;j<=r;j++) 
      if(pre[j]>pre[l])
          break;
  PretoPost(a,l+1,j-1); // add left node
  PretoPost(a,j,r); //add right node
  //root should go in the end
  post[i++] = pre[l]; 
  return;
 }

間違いがある場合は私を修正してください。

4
rajya vardhan

これは、Pythonでのpreorderからpostorderへのトラバーサルのコードです。あらゆるタイプのトラバーサルを見つけることができるようにツリーを構築しています

def postorder(root):
    if root==None:
        return
    postorder(root.left)
    print(root.data,end=" ")
    postorder(root.right)

def preordertoposorder(a,n):
    root=Node(a[0])
    top=Node(0)
    temp=Node(0)
    temp=None
    stack=[]
    stack.append(root)
    for i in range(1,len(a)):
        while len(stack)!=0 and a[i]>stack[-1].data:
            temp=stack.pop()
        if temp!=None:
            temp.right=Node(a[i])
            stack.append(temp.right)
        else:
            stack[-1].left=Node(a[i])
            stack.append(stack[-1].left)
    return root
class Node:
    def __init__(self,data):
        self.data=data
        self.left=None
        self.right=None  
a=[40,30,35,80,100]
n=5
root=preordertoposorder(a,n)
postorder(root)
# print(root.data)
# print(root.left.data)
# print(root.right.data)
# print(root.left.right.data)
# print(root.right.right.data)
3
Abhishek Yadav

事前注文のトラバーサル結果が提供されます。次に、値を適切なバイナリ検索ツリーに配置し、取得したBSTのポストオーダートラバーサルアルゴリズムに従うだけです。

3
Tharindu Rusira

私はこれが古いことを知っていますが、より良い解決策があります。

予約注文から注文を取得するためにBSTを再構築する必要はありません。

以下は、再帰的に行う単純なpythonコードです:

import itertools

def postorder(preorder):
    if not preorder:
        return []
    else:
        root = preorder[0]
        left = list(itertools.takewhile(lambda x: x < root, preorder[1:]))
        right = preorder[len(left) + 1:]
        return postorder(left) + postorder(right) + [root]

if __name__ == '__main__':
    preorder = [20, 10, 6, 15, 30, 35]
    print(postorder(preorder))

出力:

 [6, 15, 10, 35, 30, 20]

説明

私たちは予約注文中であることを知っています。これは、ルートがBSTの値のリストの0インデックスにあることを意味します。そして、ルートに続く要素は次のとおりです。

  • 最初:ルートの左サブツリーに属するrootより小さい要素
  • 2番目:ルートの右サブツリーに属するrootより大きい要素

次に、両方のサブツリーで関数を再帰的に呼び出し(これらはまだ前の順序になっています)、left + right + root(後の順序)をチェーンします。

1
tgy

ここでは、バイナリ検索ツリーの事前順序走査が配列で指定されています。そのため、先行順序配列の最初の要素はBSTのルートになります。BSTの左部分とBSTの右側部分が見つかります。先行順序配列のすべての要素はルートよりも小さく、左ノードとpreのすべての要素-order配列が大きい場合、ルートは正しいノードになります。

#include <bits/stdc++.h>
using namespace std;
int arr[1002];
int no_ans = 0;
int n = 1000;
int ans[1002] ;
int k = 0;

int find_ind(int l,int r,int x){
    int index = -1; 
    for(int i = l;i<=r;i++){
        if(x<arr[i]){
            index = i;
            break;
        }
    }
    if(index == -1)return index;
    for(int i =l+1;i<index;i++){
        if(arr[i] > x){
            no_ans = 1;
            return index;
        }
    }
    for(int i = index;i<=r;i++){
        if(arr[i]<x){
            no_ans = 1;
            return index;
        }
    }
    return index;

}

void postorder(int l ,int r){

    if(l < 0 || r >= n || l >r ) return;
    ans[k++] = arr[l];
    if(l==r) return;
    int index = find_ind(l+1,r,arr[l]);
    if(no_ans){
        return;
    }
    if(index!=-1){
        postorder(index,r);
        postorder(l+1,index-1);
    }
    else{
        postorder(l+1,r);
    }
}

int main(void){

    int t;
    scanf("%d",&t);
    while(t--){
        no_ans = 0;
        int n ;
        scanf("%d",&n);

        for(int i = 0;i<n;i++){
            cin>>arr[i];
        }
        postorder(0,n-1);
        if(no_ans){
            cout<<"NO"<<endl;
        }
        else{

            for(int i =n-1;i>=0;i--){
                cout<<ans[i]<<" ";
            }
            cout<<endl;
        }
    }

    return 0;
} 
1
HeadAndTail

事前注文が与えられていて、それをポストオーダーに変換する場合。次に、BSTでは常に番号を昇順で指定することを覚えておく必要があります。したがって、ツリーを構築するための順序と順序の両方があります。

予約注文: 6, 2, 1, 4, 3, 7, 10, 9, 11

順番に: 1, 2, 3, 4, 6, 7, 9, 10, 11

そしてそのポストオーダー:1 3 4 2 9 11 10 7 6

1
The_Zshane

私たちが知っているように、preOrderは親、左、右のシリーズに従います。

ツリーを構築するには、いくつかの基本的な手順に従う必要があります。

あなたの質問はシリーズ6、2、1、4、3、7、10、9、11で構成されています

ポイント-:

  1. シリーズの最初の番号はルート(親)、つまり6

2. 6より大きい番号を見つけます。このシリーズでは、7がこのシリーズの最初の大きい番号であるため、右のノードはここから始まり、この番号の左(7)が左のサブツリーになります。

                      6
                    /   \
                   2     7
                 /  \     \
                1    4     10
                     /     / \
                     3     9  11

3.同じ方法でBSTの基本ルール(左、ルート、右)に従います

一連のポスト順はL、R、N、つまり1,3,4,2,9,11,10,7,6になります

1
Atish Aryan

完全なコードはこちら)

class Tree:
    def __init__(self, data = None):
        self.left = None
        self.right = None
        self.data = data

    def add(self, data):
        if self.data is None:
            self.data = data
        else:
            if data < self.data:
                if self.left is None:
                    self.left = Tree(data)
                else:
                    self.left.add(data)
            Elif data > self.data:
                if self.right is None:
                    self.right = Tree(data)
                else:
                    self.right.add(data)
    def inOrder(self):
        if self.data:
            if self.left is not None:
                self.left.inOrder()
            print(self.data)
            if self.right is not None:
                self.right.inOrder()

    def postOrder(self):
        if self.data:
            if self.left is not None:
                self.left.postOrder()
            if self.right is not None:
                self.right.postOrder()
            print(self.data)

    def preOrder(self):
        if self.data:
            print(self.data)
            if self.left is not None:
                self.left.preOrder()
            if self.right is not None:
                self.right.preOrder()
arr = [6, 2, 1, 4, 3, 7, 10, 9, 11]
root = Tree()
for i in range(len(arr)):
    root.add(arr[i])
print(root.inOrder())
0
Kamol Usmonov