C中的二进制搜索树程序表现奇怪

时间:2015-11-05 16:34:12

标签: c linked-list binary-tree binary-search-tree

我编写了以下用于创建二进制搜索树的代码,但是当调用创建函数并且它第一次尝试调用insertNode(...)时程序挂起。以下是代码:

XfaForm xfa = new XfaForm(reader);
Node node = xfa.getDatasetsNode();
NodeList list = node.getChildNodes();
for (int i = 0; i < list.getLength(); i++) {
    if ("data".equals(list.item(i).getLocalName())) {
        node = list.item(i);
        break;
    }
}
// strip <xfa:data>
node = node.getFirstChild();

// Transformer code here

任何人都可以指出我的错误。任何建议都是有帮助的。

3 个答案:

答案 0 :(得分:2)

在这种树中插入的算法是(insert(node, value)):

  • 如果node为NULL则分配节点,将左/右设置为NULL(它是叶子),将值设置为value,返回分配的节点
  • 如果value < node->valuenode->left = insert(node->left, value)
  • 其他:node->right = insert(node->right, value)
  • return node(以便我们有同类代码)

插入,假设您的main是相同的:root = insert(root, val)

您可以将指针传递给指针(&root),而不是返回值,但是您必须在函数中处理取消引用它。你似乎不太熟悉指针,如果你打算玩这种结构,你真的应该阅读更多关于它的内容。

另请注意,printf函数中的main无用:在那种树中,根值始终是第一个插入的值(或者你会必须在树中执行移位以平衡分支,但这是另一个问题)。 打印btree也意味着递归功能,你必须选择如何打印它(深度优先,排序......)。示例:如果node为NULL返回;在左边打电话给自己;印刷价值;称自己为正确→将打印按小到大的顺序排列的内容。

答案 1 :(得分:2)

  

任何人都可以指出我的错误。

主要问题是createNode修改了root的本地副本。永远不会修改全局变量root,并将其设置为NULL

  

任何建议都有帮助。

  1. 避免使用全局变量。将root移动为main中的本地变量。
  2. 更改create的签名和目的,以便它只创建一个节点,而不是其他任何内容。
  3. 不要投射malloc的结果。请参阅Specifically, what's dangerous about casting the result of malloc?
  4. insertNode中使用create代替main。在create的正确位置致电insertNode
  5. 添加一个打印树内容的函数。
  6. 在测试代码时,请使用随机数而不是用户输入的数据。
  7. 允许使用命令行参数灵活地创建5个以上的节点。
  8. 以下是我对该计划的建议:

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    struct BstNode{
       int value;
       struct BstNode* left;
       struct BstNode* right;
    };
    
    struct BstNode* create(int data){ 
       printf("Creating a node with value: %d\n", data);
       struct BstNode* node = malloc(sizeof(*node));
       node->value = data;
       node->left = NULL;
       node->right = NULL;
       return node;
    }
    
    struct BstNode* insertNode(struct BstNode* root, int data){
       if ( root == NULL )
       {
          return create(data);
       }
    
       if(data <= root->value)
          root->left = insertNode(root->left, data);
       else
          root->right = insertNode(root->right, data);
    
       return root;
    }
    
    void print(struct BstNode* node, int indent, char const* nodeName)
    {
       if ( node == NULL )
       {
          return;
       }
    
       for (int i = 0; i < indent; ++i )
       {
          printf("   ");
       }
       printf("%s: %d\n", nodeName, node->value);
       print(node->left, indent+1, "left");
       print(node->right, indent+1, "right");
    }
    
    int main(int argc, char** argv){
       struct BstNode *root = NULL; 
       int i;
       int data;
       int num = 5;
       if ( argc > 1 )
          num = atoi(argv[1]);
    
       srand(time(NULL));
       for(i=0;i<num;i++){
          data = rand()%10000;
          root = insertNode(root, data);
       }
    
       printf("\n");
       print(root, 0, "root");
       return 0;
    }
    

答案 2 :(得分:0)

函数insertNode具有无限递归,导致程序崩溃。

更具体地说

struct BstNode* insertNode(struct BstNode* root, int data){
  if(data <= root->value)
      root->left = insertNode(root->left, data);
  else
      root->right = insertNode(root->right, data);

printf("%d  ",root->value);
return root;

你进入功能并检查是否(data&lt; = root-&gt; value)。在这两种情况下(true和false),你再次调用insertNode函数,然后一次又一次地调用insertNode - 你永远不会得到return语句。递归函数需要有一个基本情况,它返回一些值而不再调用它自己。

thisFunction()
   if (base case)
     return value;
   else
     return thisFunction()

在二叉搜索树的情况下,基本情况是当你插入的密钥(数据)是A)插入的密钥大于当前节点并且当前节点的右边的子节点是叶子(null)或者B)插入的密钥是比当前节点更小(或等于你想要解决关系的方式)和当前节点的左子节点为空。(data > cur->data && cur->right == NIL)(data < cur->data && cur->left == NIL)。如果您遇到其中一种情况,只需将新节点设为当前节点的右子节点或左子节点。