二叉树 - 跟踪代码

时间:2010-12-14 21:05:03

标签: c algorithm data-structures binary-search-tree

给定下面显示的二叉树,确定在调用函数A(root)的情况下访问下面显示的二叉树的节点的顺序。假设树节点和指针如图所示定义。假设root是指向包含60的节点的指针。 我对此问题的回答如下。这是对的吗?我做错了什么?

                                   60
                                 /    \
                                30     90
                               /  \   / 
                              5   38  77
                               \  /  / \
                               8 32 62  88



struct treeNode{
  int data;
  struct treeNode *left, *right:
  {

struct treeNode *tree_ptr;

void A(struct treeNode *node_ptr){
    if (node_ptr != NULL){
    printf(“%d ,”,node_ptr->data);
    B(node_ptr->left);
    B(node_ptr->right);
   }   
}

void B(struct treeNode *node_ptr){
    if (node_ptr != NULL) {
    A(node_ptr->left);
    printf(“%d ,”,node_ptr->data);
    A(node_ptr->right);
   }
 }   

答案: 在void A中,它首先打印node_ptr->数据如此打印60 然后函数调用B(node_ptr-> left)然后在B内,A被调用(node_ptr-> left)然后你打印那个数据为5.然后A(node_ptr-> right)被调用返回到A,打印该数据,以便打印8。现在我不太确定下一步该做什么,但我从逻辑上讲它是有意义的打印30但我不知道ptr从8到30如何。然后如果你继续在相同的模式38打印和32打印。 对于正确的子树...... 90 77 62 88

4 个答案:

答案 0 :(得分:1)

对于初学者来说,你的代码中有很多错误。我猜它应该更像这样:

struct treeNode{
  int data;
  struct treeNode *left, *right;
}

treeNode *tree_ptr;

void A(treeNode *node_ptr){
    if (node_ptr != NULL){  /// this could be just if(node_ptr)
        printf(“%d ,”,node_ptr->data);
        B(node_ptr->left);
        B(node_ptr->right);
    }   
}

void B(treeNode *node_ptr){
    if (node_ptr != NULL) {
        A(node_ptr->left);
        printf(“%d ,”,node_ptr->data);
        A(node_ptr->right);
    }
}   

您还混合了两种不同的遍历算法。 A()是预订,B()是有序的。 A()B()应该自称,而不是彼此。 (使用实际变量/函数名称而不是AB等的另一个原因。)

答案 1 :(得分:1)

随着时间的推移写出完整的执行堆栈。像这样:

A(60)
  printf
  B(30)
    A(5)
      ...
    printf
    A(38)
      ...
  B(90)
    ...

(树的其余部分作为练习留给读者。)

然后从上到下,写下printf语句的结果。

答案 2 :(得分:1)

A是预先遍序的遍历,而B是有序遍历。

您可以轻松了解打印顺序,了解如何访问节点本身。我通常在树的外面画一个轮廓(从根开始,然后根据你首先遍历的子树向左或向右移动)。如果我正在进行预订遍历,每当我沿着其外部移动时,我会打印出一个节点。如果我正在进行有序遍历,那么只有当我在下移动时才打印出一个节点(当你查看有序遍历时这是有意义的,因为你最终会先打印出叶子;它们是您在绘制轮廓时在下移动的第一个节点。如果我正在进行后期遍历,只有当我沿着内部移动时才会打印出一个节点。

<强>更新

在5和8之后打印出30的原因是你没有进行纯粹的预订遍历。您正在预订和有序遍历之间跳跃。

找出顺序的一种简单方法是实际记下代码在跟踪时所经历的步骤(我经常使用钢笔/铅笔和纸张将信息保存在一起)。例如,您可以写出这样的调用堆栈:

A(60)
  printf(60)
  call B(60.left)
    B(30)
      call A(30.left)
        A(5)
          printf(5)
          call B(5.left)
            B(null)
          call B(5.right)
            B(8)
              call A(8.left)
                A(null)
              printf(8)
              call A(8.right)
                A(null)
      printf(30)
      call A(30.right)
        A(38)
        ...

您可以轻松查看节点的打印顺序,更重要的是,您可以从打印8“跳转”到打印30(一个递归调用已经结束并且您正在退回一个级别)。

答案 3 :(得分:1)

如上所示的跟踪对于预订或按顺序不能正确 前60,30,5,835 32等 在 - 5,8,30,32,35等。