【问题标题】:Homework, Recursive BST insert function in C作业,C中的递归BST插入函数
【发布时间】:2014-04-24 23:37:10
【问题描述】:

这是我在 c 中第一堂课的作业。它侧重于 c 中的动态分配,以 bst 的形式。

我必须有一个动态分配的 BST,递归实现。我知道我的遍历工作正常,并且在插入节点时遇到了麻烦。我只有根节点,其他所有节点似乎都设置为 NULL。我认为遍历时无法打印其余节点,因为我正在尝试访问 NULL 结构的数据成员。到目前为止我的代码如下:

void insert_node(TreeNode** root, int toInsert){
    if(*root==NULL){
        TreeNode *newnode = (TreeNode *)malloc(sizeof(TreeNode));
        newnode->data = toInsert;
        newnode->left = NULL;
        newnode->right = NULL;
    }
    else if(toInsert > (*root)->data){ //if toInsert greater than current
        struct TreeNode **temp = (TreeNode **)malloc(sizeof(struct TreeNode*));
        *temp = (*root)->right;
        insert_node(temp, toInsert);
    }
    else{ //if toInsert is less than or equal to current
        struct TreeNode **temp = (TreeNode **)malloc(sizeof(struct TreeNode*));
        *temp = (*root)->left;
        insert_node(temp, toInsert);
    }
}

void build_tree(TreeNode** root, const int elements[], const int count){
    if(count > 0){
        TreeNode *newroot = (TreeNode *)malloc(sizeof(TreeNode));
        newroot->data = elements[0];
        newroot->left = NULL;
        newroot->right = NULL;
        *root = newroot;
        for(int i = 1; i < count; i++){
            insert_node(root, elements[i]);
        }
}

我确定这只是众多问题之一,但我在任何使用“(*root)->data”的行上都会遇到分段错误,我不知道为什么。

附带说明,尽管“(*root)->data”行出现分段错误,但我仍然能够打印“(*root)->data”。怎么可能打印值,但仍然出现分段错误?

【问题讨论】:

  • 您不要将您的newnode 附加到insert_node 中的树上。

标签: c pointers binary-search-tree dynamic-memory-allocation


【解决方案1】:

很乱。一些可能有帮助的事情

1) 不需要使用 TreeNode*,指向指针的指针,作为参数。使用 jsut TreeNode。 (这里出了点问题,因为它是文本编辑器的一些功能,请考虑并在此行中的每个 TreeNode 之后附加 *)

2) 不是严格的规则,但作为最佳实践,避免使用链表的第一个节点来存储实际值。仅用作列表的标题。原因是,如果您需要删除此节点,您不会丢失列表。只是一个提示

3) 在您的第一个函数中,如果 *root==NULL,我宁愿让函数失败,也不愿将其添加到临时列表中(在当前代码中丢失了,请参阅它将值添加到列表中没有被传递到函数之外。

4) 好吧,如果新值大于节点,您实际上是让它向右移动,如果它小于节点,则向左移动,但它永远不会停止。看这个例子: 假设您有列表 1->3->4。现在你要插入 2。算法会做什么?继续尝试插入 1 节点和 3 节点,在它们之间切换,但从未实际插入任何东西。 解决方案:由于您将自下而上构建此列表,因此您的列表将始终被排序(如果您正确插入节点)。所以你只需要检查下一个节点是否更高,如果是,就插入你所在的位置。

5) 如果您将 TreeNode *root 作为参数传递(在第二个函数中),则不必重新创建新列表并使 root=newlist。只需使用根。 所有这些都会导致(没有测试,可能是一些错误):

void insert_node(TreeNode* root, int toInsert){
if(root==NULL){
    printf("Error");
    return;
}
TreeNode* temp = root; //I just don't like to mess with the original list, rather do this
if(temp->right!=NULL && toInsert > temp->right->data){ //if toInsert greater than next
    insert_node(temp->right, toInsert);
}
else{ //if toInsert is less or equal than next node
    TreeNode* temp2 = temp->right; //grabbing the list after this node
    temp->right=(TreeNode*)malloc(sizeof(TreeNode)); //making room for the new node
    temp->right->right=temp2; //putting the pointer to the right position
    temp->right->left=temp; //setting the left of the next node to the current
    temp->right->data=toInsert;
}
}

void build_tree(TreeNode* root, const int elements[], const int count){
if(count > 0){
    for(int i = 0; i < count; i++){
        insert_node(root, elements[i]);
    }
}
}

【讨论】:

  • 还有几个cmets。从未在 C 上使用过左右,不确定它是否会起作用。我总是宁愿以老式的方式使用链表(数据和指向下一个的指针)。您实际上不需要递归,但如果它是分配的要求,好吧。
猜你喜欢
  • 1970-01-01
  • 2017-10-03
  • 1970-01-01
  • 2021-04-11
  • 2018-03-25
  • 1970-01-01
  • 2021-10-03
  • 1970-01-01
  • 2015-11-08
相关资源
最近更新 更多