工作树遍历程序似乎不起作用

时间:2015-11-14 04:42:39

标签: c recursion tree tree-traversal

我是C的树新手。为了了解更多,我用Google搜索并找到了一些不错的示例程序。 http://see-programming.blogspot.in/2013/03/insertion-deletion-and-traversal-in.html我复制并运行它完美无缺。其中一个功能称为 traverse 。其代码如下:

void traverse(struct treeNode *node) {
    if (node != NULL) {
            traverse(node->left);
            printf("%3d", node->data);
            traverse(node->right);
    }
    return;
}

整个计划:

 #include <stdio.h>
 #include <stdlib.h>

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

 struct treeNode *root = NULL;

 /* create a new node with the given data */
 struct treeNode* createNode(int data) {
    struct treeNode *newNode;
    newNode = (struct treeNode *) malloc(sizeof (struct treeNode));
    newNode->data = data;
    newNode->left = NULL;
    newNode->right = NULL;
    return(newNode);
  }

 /* insertion in binary search tree */
 void insertion(struct treeNode **node, int data) {
    if (*node == NULL) {
            *node = createNode(data);
    } else if (data < (*node)->data) {
            insertion(&(*node)->left, data);
    } else if (data > (*node)->data) {
            insertion(&(*node)->right, data);
    }
  }


  /* deletion in binary search tree */
  void deletion(struct treeNode **node, struct treeNode **parent, int data)     {
    struct treeNode *tmpNode, *tmpParent;
    if (*node == NULL)
            return;
    if ((*node)->data == data) {
            /* deleting the leaf node */
            if (!(*node)->left && !(*node)->right) {
                    if (parent) {
                            /* delete leaf node */
                            if ((*parent)->left == *node)
                                    (*parent)->left = NULL;
                            else
                                    (*parent)->right = NULL;
                            free(*node);
                    } else {
                            /* delete root node with no children */
                            free(*node);
                    }
            /* deleting node with one child */
            } else if (!(*node)->right && (*node)->left) {
                    /* deleting node with left child alone */
                    tmpNode = *node;
                    (*parent)->right = (*node)->left;
                    free(tmpNode);
                    *node = (*parent)->right;
            } else if ((*node)->right && !(*node)->left) {
                    /* deleting node with right child alone */
                    tmpNode = *node;
                    (*parent)->left = (*node)->right;
                    free(tmpNode);
                    (*node) = (*parent)->left;
            } else if (!(*node)->right->left) {
                    /*
                     * deleting a node whose right child
                     * is the smallest node in the right
                     * subtree for the node to be deleted.
                     */

                    tmpNode = *node;

                    (*node)->right->left = (*node)->left;

                    (*parent)->left = (*node)->right;
                    free(tmpNode);
                    *node = (*parent)->left;
            } else {
                    /*
                     * Deleting a node with two children.
                     * First, find the smallest node in
                     * the right subtree.  Replace the 
                     * smallest node with the node to be
                     * deleted. Then, do proper connections
                     * for the children of replaced node.
                     */
                    tmpNode = (*node)->right;
                    while (tmpNode->left) {
                            tmpParent = tmpNode;
                            tmpNode = tmpNode->left;
                    }
                    tmpParent->left = tmpNode->right;
                    tmpNode->left = (*node)->left;
                    tmpNode->right =(*node)->right;
                    free(*node);
                    *node = tmpNode;
            }
    } else if (data < (*node)->data) {
            /* traverse towards left subtree */
            deletion(&(*node)->left, node, data);
    } else if (data > (*node)->data) {
            /* traversing towards right subtree */
            deletion(&(*node)->right, node, data);
    }
  }

  /* search the given element in binary search tree */
  void findElement(struct treeNode *node, int data) {
    if (!node)
            return;
    else if (data < node->data) {
            findElement(node->left, data);
    } else if (data > node->data) {
            findElement(node->right, data);
    } else
            printf("data found: %d\n", node->data);
    return;

   }

   void traverse(struct treeNode *node) {
    if (node != NULL) {
            traverse(node->left);
            printf("%3d", node->data);
            traverse(node->right);
    }
    return;
    }

    int main() {
    int data, ch;
    while (1) {
            printf("1. Insertion in Binary Search Tree\n");
            printf("2. Deletion in Binary Search Tree\n");
            printf("3. Search Element in Binary Search Tree\n");
            printf("4. Inorder traversal\n5. Exit\n");
            printf("Enter your choice:");
            scanf("%d", &ch);
            switch (ch) {
                    case 1:
                            while (1) {
                            printf("Enter your data:");
                            scanf("%d", &data);
                            insertion(&root, data);
                            printf("Continue Insertion(0/1):");
                            scanf("%d", &ch);
                            if (!ch)
                                    break;
                            }
                            break;
                    case 2:
                            printf("Enter your data:");
                            scanf("%d", &data);
                            deletion(&root, NULL, data);
                            break;
                    case 3:
                            printf("Enter value for data:");
                            scanf("%d", &data);
                            findElement(root, data);
                            break;
                    case 4:
                            printf("Inorder Traversal:\n");
                            traverse(root);
                            printf("\n");
                            break;
                    case 5:
                            exit(0);
                    default:
                            printf("u've entered wrong option\n");
                            break;
            }
    }
    return 0;

     }

当我运行该程序时,它工作得很好。但是当我分析 traverse 函数时,我无法理解它。当您从 main 调用遍历函数时,您将根目录传递给它,就像在此程序中一样。但是当节点不为NULL时,它会继续打印树,因为还有更多数据需要打印。但每次节点不为NULL时,行遍历(node-&gt; left); 在打印节点之前再次调用该函数。因此,我不明白整个树是如何打印的。如果有人可以解释,那会很有帮助。

1 个答案:

答案 0 :(得分:3)

我们以此二叉树为例。 binary tree

  • 如何打印整棵树?

每次调用遍历函数时,我们都会打印* node的数据。

遍历过程是一个递归过程,其中处理根节点的函数将调用处理root的left-child和right-child的函数。例如,遍历(15)将调用遍历(5)和遍历(16),遍历(5)将调用遍历(3)和遍历(12)。

Recuration以叶节点结束,访问并打印每个节点。

  • 为什么结果是有序的?

在每次调用void遍历(struct treeNode * node)时,我们可以将* node视为子树的根。以下代码表示*节点的数据在其左子回归之前不会被打印。 traverse(node->left); printf("%3d", node->data); traverse(node->right);

并且遍历(node-&gt; left)仅在遍历其左子项和右子项时返回,node-&gt; left的子项也将在* node之前打印。因此,*节点的左子树中的所有节点将在*节点之前打印,并且*节点的右子树中的所有节点将在其之后打印。

例如,遍历(12)在打印12之前调用遍历(10),遍历(10)调用遍历(6)和遍历(6)调用遍历(7)。由于7是叶节点,因此遍历(7),遍历(6)和遍历(10)按顺序返回。然后遍历(12)打印12并调用遍历(13)。

我们可以获得6 7 10 12 13的有序结果