安德森树问题

时间:2011-07-06 02:59:06

标签: c++ binary-tree

以为我会用安德森树来做某事。所以我开始移植到C ++这里找到的Julienne Walker版本:http://www.eternallyconfuzzled.com/tuts/datastructures/jsw_tut_andersson.aspx

现在我有插入功能。但问题是,如果我使用优化进行编译,它会崩溃。甚至-O1也会崩溃。

template <class Tv>
class AaTree
{
private:

    template <typename Tdata>
    struct AaNode
    {
        AaNode()
        {
            level = 0;
            link[0] = 0L;
            link[1] = 0L;
        }

        ~AaNode()
        {}


        int level;
        Tdata data;
        AaNode<Tdata>* link[2];
    };


    AaNode<Tv>* root;
    AaNode<Tv>* nil;  // sentinel

    inline AaNode<Tv>* make_node(Tv data, int level)
    {
        AaNode<Tv>* rn = new AaNode<Tv>();
        rn->data = data;
        rn->level = level;
        rn->link[0] = rn->link[1] = nil;
    }

    inline AaNode<Tv>* skew(AaNode<Tv>* t)
    {
        if (t->link[0]->level == t->level && t->level != 0)
        {
            AaNode<Tv>* save = t->link[0];
            t->link[0] = save->link[1];
            save->link[1] = t;
            t = save;
        }

        return t;
    }


    inline AaNode<Tv>* split(AaNode<Tv>* t)
    {
        if (t->link[1]->link[1]->level == t->level && t->level != 0)
        {
            AaNode<Tv>*save = t->link[1];
            t->link[1] = save->link[0];
            save->link[0] = t;
            t = save;
            ++t->level;
        }

        return t;
    }


    AaNode<Tv>* _insert(AaNode<Tv>* root, Tv data)
    {
        if (root == nil)
            root = make_node(data, 1);
        else {
            AaNode<Tv>* it = root;
            AaNode<Tv>* path[64];
            int top=0, dir=0;

            for (;;) 
            {
                path[top++] = it;
                dir = it->data < data;

                if (it->link[dir] == nil)
                    break;

                it = it->link[dir];
            }

            it->link[dir] = make_node(data, 1);

            while (--top >= 0) 
            {
                if (top != 0)
                    dir = path[top - 1]->link[1] == path[top];

                path[top] = skew(path[top]);
                path[top] = split(path[top]);

                    if ( top != 0 )
                    path[top - 1]->link[dir] = path[top];
                else
                    root = path[top];
            }
        }

        return root;
    }       

    void _print(AaNode<Tv>* root)
    {
        if (root != nil)
        {
            _print(root->link[0]);
            printf("level(%d): %d\n", root->level, root->data);
            _print(root->link[1]);
        }
    }


public:
    AaTree()
        : root(0L)
    {
        nil = new AaNode<Tv>();
        root = nil;
    }

    ~AaTree()
    {}

    void Insert(Tv data)
    {
        root = _insert(root, data);
    }

    void Delete(Tv data)
    {
        root = _remove(root, data);
    }

    void Print()
    {
        _print(root);
    }   
};


int main(int argc, char* argv[])
{
    AaTree<int> tree;

    for (int i = 0; i < 100; i++)
        tree.Insert(i);

    tree.Print();

    return 0;
}

3 个答案:

答案 0 :(得分:1)

你的make_node函数声称返回一个值,但不包含return语句。

答案 1 :(得分:0)

在您的情况下,

struct AaNode不应该是模板。尝试删除它,看看会发生什么。

struct AaNode
    {
        AaNode()
        {
            level = 0;
            link[0] = 0L;
            link[1] = 0L;
        }

        ~AaNode()
        {}


        int level;
        Tv  data;
        AaNode* link[2];
    };

但无论如何,make_node()必须返回一个值。我不知道你怎么能编译它。

答案 2 :(得分:0)

  1. 使用正确的构造初始化列表:

    AaNode()
    :
        level(0),
        data(),
        link()
    {
        link[0] = 0L;
        link[1] = 0L;
    }
    
  2. 从函数中删除内联关键字。内联应保留用于非常小的函数(一般准则是最多一行或两行),您尝试内联的函数太大,并且很可能比正常调用效率低。

  3. 您的传票值nil可能应为const static。使用一些易于识别的值来初始化它也没有什么害处,这可能有助于调试。

  4. 在skew()和split()中,在取消引用指针之前,您没有进行任何检查以确保t有效或t的链接有效。

  5. 正如其他人所说,你的make_node不会返回它创建的节点。

  6. insert你的for循环没有检查以确保它不能访问越界内存(&gt;路径的第64个条目)