【问题标题】:Unable to create Binary Search Tree无法创建二叉搜索树
【发布时间】:2015-05-23 19:12:31
【问题描述】:

嗯,我正在尝试从给定的输入创建一个不平衡的二叉搜索树,作为一个(未排序的)整数序列。
我的方法是递归地为每个单独的节点找到正确的位置,然后为它分配内存并为其定义数据。
但是我无法有效地调试程序,因为尽管已经对其进行了适当的审查,但我似乎无法确定问题所在。 对于如下输入:
所以对于输入:

11
15 6 4 8 5 3 1 10 13 2 11

预期的输出应该是后序遍历和中序遍历,但奇怪的是没有打印任何内容(除了我在中间给出的换行符)。

更新:
1.[2015 年 3 月 20 日]-考虑到警告,删除了 malloc 类型转换。
2. [2015 年 3 月 21 日] 做了一些更改,虽然现在,代码只给出以下输出:

11 13
11 13 


代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define arrmax 100
/***Pointer-based BST implementation, developed by Abhineet Saxena***/

/***The data-type declaration***/
typedef struct node{
int data;
struct node* parent;
struct node* leftChild;
struct node* rightChild;
}Node;

typedef struct tree
{
    Node* root;
    int size;
}BSTree;

/***Method prototypes***/
/*Method to create a tree*/
Node* createTree(int[],int,int);

//Changed from void to Node*: void createNode(Node*,int);
Node* createNode(Node*,int);
void inOrder(Node* root);
void postOrder(Node *root);

int main(void) {

    BSTree* bs_tree;
    //Incorrect here: bs_tree=(BSTree*)malloc(sizeof(BSTree));
    bs_tree=malloc(sizeof(BSTree));
    bs_tree->root=NULL;
    bs_tree->size=0;
    /****Taking the input****/
    int num_elem,iterv;
    scanf("%d\n",&num_elem);
    //Incorrect here: int *arr=(int*)malloc(sizeof(int)*(num_elem));
    int *arr=malloc(sizeof(int)*(num_elem));
    for(iterv=0;iterv<num_elem;iterv++)
    {
        scanf("%d",&arr[iterv]);
    }
    bs_tree->root=createTree(arr,0,num_elem-1);
    postOrder(bs_tree->root);

    printf("\n");
    inOrder(bs_tree->root);

    return 0;
}
Node* createTree(int marr[],int left,int right)
{
    int iterv;
    Node* root;
    root=NULL;
    for(iterv=left;iterv<=right;iterv++)
    {

        //Made changes here: Old:-createNode(root,marr[iterv]);
         root=createNode(root,marr[iterv]);

    }
    return root;
}
Node* createNode(Node* root,int key)
{
    if(root==NULL)
    {
        root=malloc(sizeof(Node));
        //printf("Used malloc here for key: %d\n",key);
        root->data=key;
        root->leftChild=NULL;
        root->rightChild=NULL;
        root->parent=NULL;
        //Changed here: [old]return;
        return root; 

    }
    else
    {
        if(key<root->data)
                {

                        //Added code here[Old: createNode(root->leftChild,key);]
                        if(root->leftChild!=NULL)
                            createNode(root->leftChild,key);
                       else
                       {
                           root->leftChild=createNode(root->leftChild,key);
                           return root;
                       }
                }
        else
                //Added Code here: [old codeline:-] createNode(root->rightChild,key);
                 {
                     if(root->rightChild!=NULL)
                          createNode(root->rightChild,key);
                    else
                     {
                         root->rightChild=createNode(root->rightChild,key);
                         return root;
                     }
                 }                  
    }
}

void inOrder(Node* bst_tree)
{
    if(bst_tree!=NULL)
    {
        inOrder(bst_tree->leftChild);
        printf("%d ",bst_tree->data);
        inOrder(bst_tree->rightChild);
    }
    else
        return;
}
void postOrder(Node* bst_tree)
{
    if(bst_tree!=NULL)
    {
        postOrder(bst_tree->leftChild);
        postOrder(bst_tree->rightChild);
        printf("%d ",bst_tree->data);
    }
    else
        return;
}

【问题讨论】:

  • 标准警告:请do not cast malloc()C 中的家人的返回值。
  • Taking due consideration of the warning,removed the malloc typecast. 我猜你错过了很多其他地方。 :-)
  • 我相信现在一定没问题。我正在尝试这里介绍的方法,将恢复工作修改(以及实现细节)。
  • 合并了更改,但仍然无法正常工作,需要帮​​助。 @Sourav Ghosh 介意指出我哪里可能出错了吗?
  • 您可以从inOrder()postOrder() 中删除else return;。它在那里没有任何作用。

标签: c pointers malloc pass-by-value


【解决方案1】:

您的createNode() 函数为节点分配内存并用数据填充它,但我看不到它将新节点链接到数据结构的其余部分。您所有的 leftChildrightChild 指针以及树 root 保持为 NULL。

所以你在堆上有很多节点某处,但是你的树是空的......

当你在main()做时

bs_tree->root = createTree(arr,0,num_elem-1);

你也应该在createTree()

root = createNode(root,marr[iterv]);

createNode()

root->leftChild = createNode(root->leftChild,key);
root->rightChild = createNode(root->rightChild,key);

当然还有来自所有这些功能的return root;

编辑

可能的实现:

Node* insertNode(Node* root, int value)
{
    if(root == NULL)
    {
        root = malloc(sizeof(Node));
        root->data = val;
        root->leftChild = NULL;
        root->rightChild = NULL;
    }
    else
        if(val < root->data)
            root->leftChild = insertNode(root->leftChild, val);
        else
            root->rightChild = insertNode(root->rightChild, val);

    return root;
}

【讨论】:

  • 我已经进行了建议的改进,但我无法获得正确的输出,关于它可能仍然出错的地方有什么帮助吗??
  • 并非createNode() 中的所有控制路径都以return 结尾。你真的编译了吗?尝试打开编译器中的所有警告...
  • 好的,我会尽快尝试。我今天有考试,一旦我通过了,我会用工作代码和你建议的所有更改来更新答案。
【解决方案2】:

我认为,问题出在void createNode(Node* root,int key) 函数中。变量Node* root 是函数的局部变量。所以这些变化不会反映在createNode()之外。

仅供参考,C 使用按值传递来传递函数参数。

所以,要么你必须

  1. returncreateNode() 新分配的root 并在调用者中收集它。您还需要将createNode() 函数的返回类型更改为Node *(或void *,至少)。

  1. 使用指向Node * 的指针作为createNode() 中的参数

重要提示:在您使用完分配的内存后,请始终free()。否则会导致内存泄漏。

【讨论】:

    【解决方案3】:

    这部分不正确:

    void createNode(Node* root,int key)
    {
         ...
         root=(Node*)malloc(sizeof(Node));
         ...
    }
    

    root 是您的论点,更改其值(您在其中存储另一个地址)很少是一个好主意。您必须使用指向该指针的指针:

    void createNode(Node** root,int key)
    {
         ...
         *root = malloc(sizeof(Node));
         ...
    }
    

    或者在最后返回新值:

    Node* createNode(Node* root,int key)
    {
         ...
         root = malloc(sizeof(Node));
         ...
    
         return root;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-08
      • 1970-01-01
      相关资源
      最近更新 更多