C 二叉树——代码跟踪

C 二叉树——代码跟踪,c,algorithm,data-structures,binary-search-tree,C,Algorithm,Data Structures,Binary Search Tree,给定如下所示的二叉树,确定在调用函数A(根)的情况下访问如下所示二叉树节点的顺序。假设树节点和指针的定义如图所示。假设root是指向包含60的节点的指针。 我对这个问题的回答如下。对吗?我做错了什么? 60 / \ 30 90

给定如下所示的二叉树,确定在调用函数A(根)的情况下访问如下所示二叉树节点的顺序。假设树节点和指针的定义如图所示。假设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中,它表示要首先打印节点\u ptr->数据,以便打印60 然后函数调用B(node_ptr->left),然后在B中调用A(node_ptr->left),然后打印数据,数据为5。然后调用一个(node_ptr->right)返回到一个,打印数据,这样就可以打印8。现在我不太确定下一步该怎么做,但从逻辑上讲,打印30是有意义的,但我不确定ptr是如何从8到30的。然后,如果你继续使用相同的模式,38会被打印,32会被打印。 对于正确的子树。。。
90 77 62 88

首先,您的代码中有很多错误。我猜应该是这样的:

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(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)
        ...

您还混合了两种不同的遍历算法<代码>A()是预订单,
B()
是订单
A()
B()
应该自己调用,而不是彼此调用。(使用实数变量/函数名而不是
A
B
等的另一个原因。)

首先,您的代码中有大量错误。我猜应该是这样的:

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(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)
        ...

您还混合了两种不同的遍历算法<代码>A()是预订单,
B()
是订单
A()
B()
应该自己调用,而不是彼此调用。(使用实变量/函数名而不是
A
B
等的另一个原因。)

只需随时间写出完整的执行堆栈即可。像这样:

A(60)
  printf
  B(30)
    A(5)
      ...
    printf
    A(38)
      ...
  B(90)
    ...
(树的其余部分留给读者作为练习。)


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

只需随时间写出完整的执行堆栈。像这样:

A(60)
  printf
  B(30)
    A(5)
      ...
    printf
    A(38)
      ...
  B(90)
    ...
(树的其余部分留给读者作为练习。)


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

A
是预顺序遍历,而
B
是顺序遍历

确定打印顺序的一个简单方法是查看如何访问节点本身。我通常在树的外部画一个轮廓(从根开始,根据首先遍历的子树向左或向右移动)。如果我在进行预排序遍历,那么每当我沿着节点的外部移动时,我都会打印出一个节点。如果我正在进行按顺序遍历,则仅当我移动到节点下时才打印出节点(当您查看按顺序遍历时,这是有意义的,因为您首先打印叶子;它们是绘制轮廓时移动到其下的第一个节点)。如果我正在进行后序遍历,则仅当我沿着节点的内部移动时,才会打印出节点

更新

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

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

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(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(一个递归调用已经结束,您正在后退一级)。

A
是一个预顺序遍历,而
B
是一个顺序遍历

确定打印顺序的一个简单方法是查看如何访问节点本身。我通常在树的外部画一个轮廓(从根开始,根据首先遍历的子树向左或向右移动)。如果我在进行预排序遍历,那么每当我沿着节点的外部移动时,我都会打印出一个节点。如果我正在进行按顺序遍历,则仅当我移动到节点下时才打印出节点(当您查看按顺序遍历时,这是有意义的,因为您首先打印叶子;它们是绘制轮廓时移动到其下的第一个节点)。如果我正在进行后序遍历,则仅当我沿着节点的内部移动时,才会打印出节点

更新

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

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

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(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(一个递归调用已结束,您正在后退一级)。

上述跟踪对于预订单或顺序都不正确 60岁之前、30岁之前、5岁之前、8岁之前、35岁之前等
在-5、8、30、32、35等中,

上述跟踪对于预订单或订单都不正确 60岁之前、30岁之前、5岁之前、8岁之前、35岁之前等
在-5、8、30、32、35等中

您可能应该将其标记为
作业
。不鼓励使用AFAIK
作业
标记。给出的代码不会编译。你到底是什么意思?@Vivin,但如果一个问题被诚实地标记为这样的话,我很可能会正确地给出我的答案。@nmichaels基本上是提供的代码,因此决定了元素的打印顺序。我只是想验证一下,看看我是否正确。你可能应该把它标记为
家庭作业