树程序中的错误在哪里?

时间:2013-09-03 06:56:05

标签: c++ data-structures binary-search-tree

以下是我在VS2008中编写的两个示例代码。第一个示例代码工作正常,而第二个(树的)产生一些错误。

 1)
#include<iostream>
using namespace std;

struct node{
        int number;
        struct node *right;
        struct node *left;
    }nodeType;

int insert(struct node *,int);

int main(){

        struct node * root=(struct node *)malloc(sizeof(node));
        root->left=NULL;
        root->right=NULL;
        root->number=10;
        insert(root,100);
      cout<<root->right->number; //This works fine

        return 1;
    }

int insert(struct node * leaf,int data){
        leaf->left =(struct node *)malloc(sizeof(node));
        leaf->right =(struct node *)malloc(sizeof(node));
        struct node *temp = leaf;
        temp->right->number=12;
        temp->left->number=11;
        temp->right->right=NULL;
        temp->right->left=NULL;
        temp->left->left=NULL;
        temp->left->right=NULL;
        return 1;
    }





  2)

#include<iostream>
using namespace std;
struct node{
    int number;
    struct node *right;
    struct node *left;
}nodeType;

int insert(struct node *,int);

int main(){

    int data[50];
    int i;
    for(i=0;i<50;i++){
     data[i]=rand()%100;
    }

    struct node * root=(struct node *)malloc(sizeof(node));
    root->left=NULL;
    root->right=NULL;

    root->number = 36;
    for(i=0;i<50;i++){
        insert(root,data[i]);
    }
    cout<<root->right->number; //This doesn't work, and it throws some memory error. Though it assigns a value(it is 41) which goes to the right side in the insert function, the root's right side pointer is not able to point into that memory location. Similar case with root->.... also.
    return 1;
}

int insert(struct node * leaf,int data){

    if(leaf==NULL){
        leaf = (struct node *)malloc(sizeof(node));
        leaf->number=data;
        leaf->left=NULL;
        leaf->right=NULL;
    }
    else if(data>=leaf->number){
        insert(leaf->right,data);
    }
    else if (data<leaf->number){
        insert(leaf->left,data);
    }
    else
    {

    }

    return 1;
}

为什么在第二个程序中它无法指向该位置?

编辑: 我在运行时得到的错误是:

test.exe中0x004114b4处的未处理异常:0xC0000005:Access 违规读取位置0x000000004。

中断继续忽略

2 个答案:

答案 0 :(得分:4)

@whozcraig做了一个限制自己的正确的男子气概工作。我的自我控制能力较差,所以我要谈谈你的代码中没有注意到的一些问题(或者甚至看不到症状)。

首先,您通常不应在C ++代码中使用malloc(也不应使用struct xxx来定义结构的实例)。

其次,maininsert中的代码都在执行应该由node的ctor真正处理的工作(例如,将节点的子指针设置为NULL)。

第三,在insert你正在测试一个永远不会是假的条件,然后添加一个永远不能执行的空else(但无论如何都不做)。

我首先重写node看起来像这样:

struct node{
    int number;
    node *right;
    node *left;

    node(int n) : number(n), right(NULL), left(NULL) {}
};

这样,节点的ctor将其子指针初始化为NULL,并将所需的值放入节点本身。

这让我们可以大大简化其他代码。例如,insert最终看起来像这样:

void insert(node *&leaf, int data){
    if (leaf == NULL)
        leaf = new node(data);
    else if (data < leaf->number)
        insert(leaf->left, data);
    else
        insert(leaf->right, data);
}

由于这是二叉树,实际上只有三种可能:1)没有“当前”节点 - 在这种情况下,我们插入新数据“here”,或2)新数据属于左边当前节点,或3)它属于当前节点的右侧。这段代码直接反映了三方决策过程。

main中的相当多的代码似乎也是不必要的。例如,如果我们只想在树中插入一些数字,则可以很容易地将代码简化为以下内容:

node *root = NULL;

for (int i = 0; i < 50; i++)
    insert(root, rand() % 100);

首先不需要将数据放入数组中 - 我们可以将每个项目直接放入树中生成。

当然,要了解发生了什么,我们可能不仅要打印树中的一个特定节点,而且(可能)打印所有数据。幸运的是,这也很容易做到:

void show(node *tree) {
    if (tree == NULL)
        return;
    show(tree->left);
    std::cout << "\t" << tree->number;
    show(tree->right);
}

这会对树进行简单的有序遍历,在遍历每个节点时打印它们。为了避免泄漏您为树创建的内存,您可能希望执行类似于删除树中节点的操作。主要区别在于,您可能希望进行后序遍历(递归删除两个子节点,然后删除当前节点)。

另一点是,树应该是它自己的一个类,insert作为成员函数(并且可能还有一个dtor来销毁一个树并删除它的所有内容,如果你想要类似于上面的show,也许operator<<过载,等等。)

答案 1 :(得分:3)

第二个插入函数是通过值传递节点指针;不是通过引用或地址。因此,对它的修改不会在函数范围之外进行。

改变这个:

int insert(struct node * leaf,int data)

对此:

int insert(struct node*& leaf,int data)

在原型的实现中。

保留有关在{+ 1}}中使用C ++程序的所有注释。虽然很糟糕,但它与你的问题毫无关系。