簡體   English   中英

將后置二叉樹遍歷索引轉換為層級(廣度優先)索引

[英]Convert a post-order binary tree traversal index to an level-order (breadth-first) index

假設一個完整的二叉樹,可以在給定的樹遍歷算法中對每個節點進行定位。

例如,高度為3的簡單完整樹的節點索引如下所示:

廣度優先(又稱水平順序):

     0
   /   \
  1     2
 /  \  /  \
3   4  5  6

后訂單部優先:

     6
   /   \
  2     5
 /  \  /  \
0   1  3  4

給出了樹的高度和后遍歷中的索引。

如何根據此信息計算廣度優先索引?

我認為它必須迭代/遞歸地計算。 話雖如此,有人將在37秒內完成簡單的單行計算,並對我投下反對票。 盡管如此,可以通過遞歸考慮來解決。 考慮深度優先的后遍歷的簡單樹(基於1):

   3
  / \
 1   2

從遞歸的角度來看,這就是您需要考慮的全部。 您位於子樹(3)的根,子樹(1)的左側或右側(2)。 如果您是根本,那您就完成了。 否則,左右子樹是相同的,並且右子樹中的后遍歷索引等於相應的左子樹索引+子樹中的節點數。

以下代碼在O(log n)執行此計算。 對於深度為10(1023個節點)的樹,它最多以10次迭代(遞歸)計算索引值。

它跟蹤給定節點的深度,並根據是在處理左還是右子樹來計算寬度優先行的位置。 請注意,這使用基於1的索引值。 我發現用這些術語來思考它更簡單(深度為2的樹中有3個節點,后遍歷中最頂層的節點為3)。 還要注意,它認為樹的深度為1才有一個節點(我不確定這是否是典型的約定)。

// Recursively compute the given post-order traversal index's position
// in the tree:  Its position in the given level and its depth in the tree.
void ComputePos( int treedepth, int poindex, int *levelposition, int *nodedepth )
{
    int nodes;
    int half;

    // compute number of nodes for this depth.
    assert( treedepth > 0 );
    nodes = ( 1 << ( treedepth )) - 1;
    half = nodes / 2;   // e.g., 7 / 2 = 3

    //printf( "poindex = %3d, Depth = %3d, node count = %3d", poindex, treedepth, nodes );

    (*nodedepth)++;

    if ( poindex == nodes ) {
        // This post-order index value is the root of this subtree
        //printf( "  Root\n" );
        return;
    }
    else if ( poindex > half ) {
        // This index is in the right subtree
        //printf( "  Right\n" );
        poindex -= half;
        *levelposition = 2 * *levelposition + 1;
    }
    else {
        // Otherwise it must be in the left subtree
        //printf( "  Left\n" );
        *levelposition = 2 * *levelposition;
    }

    treedepth -= 1;
    ComputePos( treedepth, poindex, levelposition, nodedepth );
}

int main( int argc, char* argv[] )
{
    int levelposition = 0;   // the 0-based index from the left in a given level
    int nodedepth = 0;  // the depth of the node in the tree
    int bfindex;
    int treedepth = atoi( argv[1] );   // full depth of the tree (depth=1 means 1 node)
    int poindex = atoi( argv[2] ); // 1-based post-order traversal index

    ComputePos( treedepth, poindex, &levelposition, &nodedepth );

    //printf( "ComputePos( %d, %d ) = %d, %d\n", treedepth, poindex, levelposition, nodedepth );

    // Compute the breadth-first index as its position in its current
    // level plus the count of nodex in all the levels above it.
    bfindex = levelposition + ( 1 << ( nodedepth - 1 ));
    printf( "Post-Order index %3d = breadth-first index %3d\n", poindex, bfindex );

    return 0;
}

這是為以下樹(深度4)計算的值,該樹顯示了后遍歷索引值(從1開始)。

            15
          /    \
         /      \
        /        \
       /          \
      /            \
     7             14     
    / \            / \    
   /   \          /   \   
  3     6       10    13  
 /\    / \      /\    / \ 
1  2  4   5    8  9  11  12


[C:\tmp]for /l %i in (1,1,15) do po2bf 4 %i
Post-Order index   1 = breadth-first index   8
Post-Order index   2 = breadth-first index   9
Post-Order index   3 = breadth-first index   4
Post-Order index   4 = breadth-first index  10
Post-Order index   5 = breadth-first index  11
Post-Order index   6 = breadth-first index   5
Post-Order index   7 = breadth-first index   2
Post-Order index   8 = breadth-first index  12
Post-Order index   9 = breadth-first index  13
Post-Order index  10 = breadth-first index   6
Post-Order index  11 = breadth-first index  14
Post-Order index  12 = breadth-first index  15
Post-Order index  13 = breadth-first index   7
Post-Order index  14 = breadth-first index   3
Post-Order index  15 = breadth-first index   1

蠻力破解,直到找到更好的答案:

  1. 從后置數組/索引構建樹,使每個節點的值成為當前數組索引。

消耗索引:索引的上半部分是您的左子樹,下半部分是您的右子樹,中間節點是根。 遞歸每個子樹。

  1. 遍歷樹的廣度優先,將計算出的廣度優先索引作為映射對的值放入map中,並使用鍵作為節點的值。 map.put( node.value, tree_visitor.current_index)

  2. 詢問地圖,傳遞所需的鍵(這是后順序節點的索引)以獲取對應的廣度優先節點的索引。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM