docs: public static void postorder(int parent[], int N, int post[], @Nullable IGrowArray gwork) {
          if (parent.length < N)
              throw new IllegalArgumentException("parent must be at least of length N");
          if (post.length < N)
              throw new IllegalArgumentException("post must be at least of length N");
  
          int[] w = UtilEjml.adjust(gwork, 3*N);
  
          // w[0] to w[N-1] is initialized to the youngest child of node 'j'
          // w[N] to w[2N-1] is initialized to the second youngest child of node 'j'
          // w[2N] to w[3N-1] is the stacked of nodes to be examined in the dfs
          final int next = N;
  
          // specify the linked list as being empty initially
          for (int j = 0; j < N; j++) {
              w[j] = -1;
          }
          // traverse nodes in reverse order
          for (int j = N-1; j >= 0; j--) {
              // skip if j has no parent, i.e. is a root node
              if( parent[j] == -1 )
                  continue;
              // add j to the list of parents
              w[next+j] = w[parent[j]];
              w[parent[j]] = j;
          }
  
          // perform the DFS on each root node
          int k = 0;
          for (int j = 0; j < N; j++) {
              if( parent[j] != -1 )
                  continue;
  
              k = postorder_dfs(j,k,w,post,N);
          }
      }