【问题标题】:Binary tree only displays half of content二叉树只显示一半内容
【发布时间】:2014-07-23 17:21:24
【问题描述】:

我的程序假设从文件中读取字符并显示文件中内容的前序、中序和后序遍历。问题是它只显示文件中一半的内容。不确定它在哪里以及为什么停止从文件中读取?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MaxWordSize 50

typedef struct {
    char word[MaxWordSize + 1];
}NodeData;

typedef struct treeNode {
    NodeData data;
    struct treeNode *left, *right;
}TreeNode, *TreeNodePtr;

typedef struct {
    TreeNodePtr root;
}BinaryTree;

void visit(TreeNodePtr node) {
    printf("%s", node -> data.word);
}//end visit

void preOrder(TreeNodePtr node) {
    void visit(TreeNodePtr);
    if (node != NULL) {
        visit(node);
        preOrder(node -> left);
        preOrder(node -> right);
    }
}

void inOrder(TreeNodePtr node) {
    void visit(TreeNodePtr);
    if (node != NULL) {
        inOrder(node -> left);
        visit(node);
        inOrder(node -> right);
    }
}

void postOrder(TreeNodePtr node) {
    void visit(TreeNodePtr);
    if (node != NULL) {
        postOrder(node -> left);
        postOrder(node -> right);
        visit(node);
    }
}

TreeNodePtr buildTree(FILE *in) {
    char str[MaxWordSize + 1];
    fscanf(in, "%s", str);
    if (strcmp(str, "@") == 0) {
        return NULL;
    }
    TreeNodePtr p = (TreeNodePtr)malloc(sizeof(TreeNode));
    strcpy(p -> data.word, str);
    p -> left = buildTree(in);
    p -> right = buildTree(in);
    return p;
}

int main() {
    TreeNodePtr buildTree(FILE *);
    void preOrder(TreeNodePtr);
    void inOrder(TreeNodePtr);
    void postOrder(TreeNodePtr);
    FILE *in = fopen("./c/btree.in.txt", "r");
    BinaryTree bt;
    bt.root = buildTree(in);
    printf("\n The pre-order traversal is : ");
    preOrder(bt.root);
    printf("\n The in-order traversal is : ");
    inOrder(bt.root);
    printf("\n The post-order traversal is : ");
    postOrder(bt.root);
    printf("\n\n");
    fclose(in);
    system ("PAUSE");
    return 0;
}

我的输入文件内容是:

C E F @ @ H @ @ B @ @ G A @ @ N J @ @ K @ @

我的输出是:

The pre-order traversal is: CEFHB
The in-order traversal is: FEHCB
The post-order traversal is: FHEBC

【问题讨论】:

  • 你应该做一些调试来找出问题所在的函数。然后为那个方法构建一个minimal test-case
  • 其实....我想我看到了问题所在。该代码似乎运行完美,我认为 输入文件 是错误的。输入文件形成了树 C (E (F H)) (B),这是一棵有效的树,因此其余部分被忽略:G A @ @ N J @ @ K @ @
  • 你能添加一张输入文件应该代表什么树的图表吗?
  • @MooingDuck 你完全正确!谢谢!
  • 问题是对'@'(和返回)的检查经常发生,以至于在处理'B'后立即退出递归。所以逻辑是错误的。也许添加一个递归计数器,如果该计数器指示递归的顶层,则仅在文件末尾返回,否则读取另一个输入并继续。

标签: c binary-tree traversal inorder postorder


【解决方案1】:

实际上....我想我看到了问题所在。代码似乎运行完美,我认为输入文件有误。

给定这个输入:C E F @ @ H @ @ B @ @ G A @ @ N J @ @ K @ @,代码执行如下:

bt.root = buildTree(in);
    fscanf(in, "%s", str); //finds C
    p -> left = buildTree(in);
        fscanf(in, "%s", str); //finds E
        p -> left = buildTree(in);
            fscanf(in, "%s", str); //finds F
            p -> left = buildTree(in);
                fscanf(in, "%s", str); //finds @
            p -> right = buildTree(in);
                fscanf(in, "%s", str); //finds @
        p -> right = buildTree(in);
            fscanf(in, "%s", str); //finds H
            p -> left = buildTree(in);
                fscanf(in, "%s", str); //finds @
            p -> right = buildTree(in);
                fscanf(in, "%s", str); //finds @
    p -> right = buildTree(in);
        fscanf(in, "%s", str); //finds B
        p -> left = buildTree(in);
            fscanf(in, "%s", str); //finds @
        p -> right = buildTree(in);
            fscanf(in, "%s", str); //finds @

此时,每个节点都有两个子节点,因此执行停止,将G A @ @ N J @ @ K @ @ 剩余留在输入缓冲区中。
读入的树在左边。如果剩下的被重新解析,它也会形成一棵树,如右图所示。

       C                       G
   E       B               A       N
 F   H   @   @           @   @   J   K
@ @ @ @                         @ @ @ @

我不确定您打算读入什么树,但输入可能缺少根节点?


话虽如此,您的buildTree 例程中至少存在一个错误,尽管您没有遇到它。试试这个输入:“A”,你会发现它:D

【讨论】:

    【解决方案2】:

    检查你的 buildTree 方法。

    您正在使用这些规则在这里实现一个简单的语法......

    Node -> char Node Node
    Node -> @
    

    尝试使用这些规则手动解析字符串。所以,开始...

    Input -> C LeftNode RightNode
      LeftNode -> E LeftNode RightNode
        LeftNode -> F LeftNode RightNode
          LeftNode -> @
          RightNode -> @
        RightNode -> ...
    

    等等。

    语法是一种高级概念(通常在大学三年级教授),但它是理解 buildTree 等方法的必要模型。

    PS,除了了解 buildTree 的工作原理之外,您还应该真正用它所实现的语法定义对其进行注释。记录下来可以节省大量工作。

    【讨论】:

    • 嗯,这个二叉树的语法非常简单直观,完全有可能他在不知道语法的情况下实现了它。
    • 此外,据我所知,他的 buildTree 的实现正在运行,这使得整个答案具有误导性。 (我并不是说它没有错误,我至少看到了一个错误,但该输入不应该遇到错误)
    猜你喜欢
    • 2013-12-28
    • 2016-05-16
    • 2019-08-15
    • 1970-01-01
    • 2017-07-05
    • 2012-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多