【问题标题】:Binary Search Tree Nothing Getting Printed二叉搜索树什么都没有打印
【发布时间】:2015-03-22 02:29:27
【问题描述】:

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

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

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

注意: 这个问题与我之前提出的 BST 相关问题密切相关,但方法完全不同,我面临的挑战也是如此。因此,在我的脖子上并可能关闭这个话题之前要三思而后行。

#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);
void insert(Node*,int);

Node* createNode(int);
void inOrder(Node* root);
void postOrder(Node *root);

int main(void) {

    BSTree* bs_tree;
    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);
    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;
//  Node** root_ptr;
    //*root_ptr=root;
    for(iterv=left;iterv<=right;iterv++)
    {

        insert(root,marr[iterv]);

    }
    return root;
}
Node* createNode(int key)
{
        Node* tree_node;
        tree_node=malloc(sizeof(Node));
        //printf("Used malloc here for key: %d\n",key);
        tree_node->data=key;
        tree_node->leftChild=NULL;
        tree_node->rightChild=NULL;
        tree_node->parent=NULL;
        return tree_node;
}
void insert(Node* root,int key)
{
        if(root==NULL)
    {
        root=createNode(key);
        //return root;
    }
    else if(root->leftChild!=NULL && root->rightChild!=NULL)
        {
            if(key<root->data)

                        insert(root->leftChild,key);
                        else

                       insert(root->rightChild,key);
        }
        else if(root->leftChild!=NULL && root->rightChild==NULL)
        {
            if(key>root->data)
            {
                Node* tnode=createNode(key);
                root->rightChild=tnode;
                tnode->parent=root;
                return;
            }
            else if(key<root->data)
                insert(root->leftChild,key);

        }
        else if(root->leftChild==NULL && root->rightChild!=NULL)
        {
            if(key<root->data)
            {
                Node* tnode=createNode(key);
                root->leftChild=tnode;
                tnode->parent=root;
                return;
            }
            else if(key>root->data)
                insert(root->rightChild,key);
        }
        else
        {
            if(key<root->data)
            {
                Node* tnode=createNode(key);
                root->leftChild=tnode;
                tnode->parent=root;
                return;
            }
            else if(key>root->data)
            {
                Node* tnode=createNode(key);
                root->rightChild=tnode;
                tnode->parent=root;
                return;
            }
        }

}

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;
}

【问题讨论】:

  • 在调用insert(root,key)的过程中root自身为NULL会发生什么?
  • 您分配和分配给root 的节点永远不会从insert() 发出。 C 是按值传递; root = ....调用者的 root 没有任何作用。因此,insert(root,marr[iterv]); 最终对createTree 中的root 没有任何作用,并且在执行此操作时会泄漏内存。在这段代码中,几乎每次调用 insert() 都会复制这个问题,我数了 5 个。
  • 然后它会简单地创建第一个节点,正如我在 insert() 函数的开头所指定的那样。
  • insert() 的调用什么也没做。您需要将节点从insert()返回给调用者。
  • @WhozCraig ,那么在这种情况下我应该做些什么改变?

标签: c recursion binary-search-tree


【解决方案1】:

你的问题是这个:在 createTree 中,你将 root 设置为 NULL,然后调用

insert(root, marr[iterv]);

...现在神奇地期望 root 在它之后是非 NULL 的。您需要更改为此调用约定:

insert(&root, marr[iterv]);

...将insert的签名改为void insert(Node**,int);

然后,在插入函数中,使用 *root 代替 root,使用 (*root)->something 代替 root->something。我用这些更改测试了你的程序,它可以工作。

一个额外的 nitpick:整数范围应该是左包含右排除,因此您应该以这种方式调用 createTree:

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

然后有这个循环:

for(iterv=left;iterv<right;iterv++)

那么范围的长度是左右更方便的。

【讨论】:

    【解决方案2】:
     #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);
        void insert(Node*,int);
        Node* createNode(int);
        void inOrder(Node* root);
        void postOrder(Node *root);
    
        int main(void) {
    
            BSTree* bs_tree;
            bs_tree=(BSTree*)malloc(sizeof(BSTree));
            bs_tree->root=NULL;
            bs_tree->size=0;
            /****Taking the input****/
            int num_elem,iterv=0;
            printf("Enter Number of Elements\n");
            scanf("%d\n",&num_elem);
            int *arr=(int*)malloc(sizeof(int)*num_elem);
            for(;iterv<num_elem;iterv++){
                printf("Enter keys\n");
                scanf("%d",&arr[iterv]);
            }
            bs_tree->root=createTree(arr,num_elem-1);
            postOrder(bs_tree->root);
    
            printf("\n");
            inOrder(bs_tree->root);
            return 0;
        }
        Node* createTree(int marr[],int right){
            Node* root =createNode(marr[0]);
            int iterv=1;
            for( ;iterv<=right;iterv++){
                insert(root,marr[iterv]);
            }
            return root;
        }
        Node* createNode(int key){
                Node* tree_node;
                tree_node=(Node*)malloc(sizeof(Node));
                tree_node->data=key;
                tree_node->leftChild=NULL;
                tree_node->rightChild=NULL;
                tree_node->parent=NULL;
                return tree_node;
        }
        void insert(Node* root,int key){
                if(root->leftChild!=NULL && root->rightChild!=NULL){
                    if(key<root->data)
                        insert(root->leftChild,key);
                    else
                       insert(root->rightChild,key);
                }
                else if(root->leftChild!=NULL && root->rightChild==NULL){
                    if(key>root->data){
                        Node* tnode=createNode(key);
                        root->rightChild=tnode;
                        tnode->parent=root;
                        return;
                    }
                    else if(key<root->data)
                        insert(root->leftChild,key);
                }
                else if(root->leftChild==NULL && root->rightChild!=NULL){
                    if(key<root->data){
                        Node* tnode=createNode(key);
                        root->leftChild=tnode;
                        tnode->parent=root;
                    }
                    else if(key>root->data)
                        insert(root->rightChild,key);
                }
                else{
                    if(key<root->data){
                        Node* tnode=createNode(key);
                        root->leftChild=tnode;
                        tnode->parent=root;
                        return;
                    }
                    else if(key>root->data){
                        Node* tnode=createNode(key);
                        root->rightChild=tnode;
                        tnode->parent=root;
                        return;
                    }
                }
        }
        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;
        }
    

    //检查此代码是否有效。

    【讨论】:

    • 是的,它工作得非常好:-) 尽管要记住一件事,因为我相信你可能更适应 C++,在 C 中,不允许在 for 循环中进行初始化。因此,而不是 for(int iterv=0;...) ,它应该是: int iterv; for(iterv=0;...)
    • 实际上我使用new将此代码转换为c++,然后我回滚到malloc
    • @Abhin33t_S 如果它有效,那么您应该作为答案或发表评论,这就是 SO 的工作原理。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多