3

当我在整数数组中有前序遍历和中序遍历时,给出输出树的后序遍历的代码。我如何用给定的 inorder 和 postorder 数组同样获得预购?

void postorder( int preorder[], int prestart, int inorder[], int inostart, int length)
{ 
  if(length==0) return; //terminating condition
  int i;
  for(i=inostart; i<inostart+length; i++)
    if(preorder[prestart]==inorder[i])//break when found root in inorder array
      break;
  postorder(preorder, prestart+1, inorder, inostart, i-inostart);
  postorder(preorder, prestart+i-inostart+1, inorder, i+1, length-i+inostart-1);
  cout<<preorder[prestart]<<" ";
}

这是 preorder() 的原型

void preorder(int inorderorder[], int inostart, int postorder[], int poststart, int length)

使用 postorder() 它将是

int preorder[6]={6,4,1,5,8,9};
int inorder[6]={1,4,5,6,8,9};
postorder( preorder,0,inorder,0,6);

输出将是

1 5 4 9 8 6

下面是 print_preorder() 的错误代码,下面仍然无法正常工作

void print_preorder( int inorder[], int inostart, int postorder[], int poststart, int length)
    {
      if(length==0) return; //terminating condition
      int i;
      for(i=inostart; i<inostart+length; i++)
        if(postorder[poststart+length-1]==inorder[i])
          break; 
      cout<<postorder[poststart+length-1]<<" ";
      print_preorder(inorder, inostart , postorder, poststart, i-inostart);
      print_preorder(inorder, inostart+i-poststart+1, postorder, i+1, length-i+inostart-1);
    }
4

2 回答 2

9

这里有一些提示:

  • 子数组中的最后一个元素postorder是您的新preorder根。
  • 数组可以在新根inorder的两侧一分为二。preorder
  • 您可以递归调用print_preorder这两inorder个子数组上的函数。
  • 调用print_preorder函数时,inorderpostorder数组的大小相同。
  • 您有一个越界的数组访问:超出postorder[poststart+length]了数组的末尾。要获取最后一个元素,您需要postorder[poststart+length-1]
  • 您的第一个递归print_preorder函数选择了错误的长度。请记住,这length是子数组的长度,但它是数组inostart中的绝对位置。inorder您的函数可能会以否定调用length
  • 您的第二个递归函数距离转换边界和长度还很遥远。将它画在纸上并跟踪您的算法可能会有所帮助。

绘制树可能会有所帮助:

     6
   /   \
  4     8
 / \     \
1   5     9

然后写出三个遍历:

// index:         0 1 2 3 4 5
int postorder[6]={1,5,4,9,8,6};
int inorder[6]=  {1,4,5,6,8,9};
int preorder[6]= {6,4,1,5,8,9};

现在,放下电脑,拿出笔和纸,想想问题:)

想象一下这个调用堆栈(新的根打印在左边):

6 print_preorder(len=6, in=[1 4 5 6 8 9], post=[1 5 4 9 8 6])
4 |-> print_preorder(len=3, in=[1 4 5], post=[1 5 4])
1 |   |-> print_preorder(len=1, in=[1], post=[1])
  |   |   |-> print_preorder(len=0, in=[], post=[])
  |   |   |-> print_preorder(len=0, in=[], post=[])
5 |   |-> print_preorder(len=1, in=[5], post=[5])
  |       |-> print_preorder(len=0, in=[], post=[])
  |       |-> print_preorder(len=0, in=[], post=[])
8 |-> print_preorder(len=2, in=[8 9], post=[9 8])
      |-> print_preorder(len=0, in=[], post=[])
9     |-> print_preorder(len=1, in=[9], post=[9])
          |-> print_preorder(len=0, in=[], post=[])
          |-> print_preorder(len=0, in=[], post=[])

祝你好运 :)

于 2010-06-09T01:54:09.013 回答
4
  1. 后序中的最后一个元素将是树的根。

  2. 之后,我们将查看 Inorder 数组以确定根的位置。数组的左边是左子树,右边是右子树。

  3. 通过使用该索引,我们将确定左边的元素是根。

  4. 右子树类似,主要思想是通过查找中序数组来确定左子树和右子树的索引。希望我很清楚..

    public static void printpreorder(char []inorder,int i_start,int i_end,char[] postorder,int p_start,int p_end)
    {
      if(i_start > i_end || p_start > p_end)
             return ; 
      char root = postorder[p_end];
      System.out.print(root);
      System.out.print("(");
        int k=0;
          for(int i=0; i< inorder.length; i++){
              if(inorder[i]==root){
                k = i;
                break;
              }
          }
      printpreorder(inorder, i_start, k-1, postorder, p_start, p_start+k-(i_start+1));
      System.out.print(")(");
      printpreorder(inorder, k+1, i_end, postorder, p_start+k-i_start, p_end-1);
      System.out.print(")");    
    }
    

这对我来说是家庭作业。感谢@Stephen 提供了一个很好的答案

于 2014-05-24T07:20:06.350 回答