试图遍历四叉树以确定高度

时间:2018-03-07 04:28:19

标签: c++ recursion tree segmentation-fault traversal

我目前正在尝试自动生成随机生成的房间对象的迷宫,这些房间对象通过4个方向的指针链接 - n,s,e和w。我从Room * home开始,每个新房间都有1/3的机会在其他三个方向的每个方向创建一扇门(它当然有一扇门回到它来自的地方)。这一直持续到所有"离开"有三个指向其他方向的空指针。我相信地图正在被正确创建,因为我能够四处移动"在其中使用另一个功能(不包括在下面)。我的问题是如何找到这个结构的高度。它本质上是一个四叉树。这是我建造迷宫并试图找到高度的代码。执行时出现分段错误。如果我在高度中注释掉四个递归调用中的任何三个,那就没有错。

void buildMaze(Room *newRoom, char d)
{  
    int rando;

    Room *last = newRoom;

    //coming from south
    if(d == 's')
    {
        newRoom = new Room();
        newRoom->southDoor = last;
        last->northDoor = newRoom;

        rando = arc4random_uniform(3);
        if(rando == 1)
           buildMaze(newRoom, 's');//build north room

        rando = arc4random_uniform(3);
        if(rando == 1)
           buildMaze(newRoom, 'w');//build east room

        rando = arc4random_uniform(3);
        if(rando == 1)
           buildMaze(newRoom, 'e');//build west room
    }
    //coming from north
    else if(d == 'n')
    {
        newRoom = new Room();
        newRoom->northDoor = last;
        last->southDoor = newRoom;

        rando = arc4random_uniform(3);
        if(rando == 1)
           buildMaze(newRoom, 'n');//build south room

        rando = arc4random_uniform(3);
        if(rando == 1)
           buildMaze(newRoom, 'w');//build east room

        rando = arc4random_uniform(3);
        if(rando == 1)
           buildMaze(newRoom, 'e');//build west room
    }
    //coming from east
    else if(d == 'e')
    {
        newRoom = new Room();
        newRoom->eastDoor = last;
        last->westDoor = newRoom;

        rando = arc4random_uniform(3);
        if(rando == 1)
           buildMaze(newRoom, 's');//build north room

        rando = arc4random_uniform(3);
        if(rando == 1)
           buildMaze(newRoom, 'n');//build south room

        rando = arc4random_uniform(3);
        if(rando == 1)
           buildMaze(newRoom, 'e');//build west room
    }
    //coming from west
    else if(d == 'w')
    {
        newRoom = new Room();
        newRoom->westDoor = last;
        last->eastDoor = newRoom;

        rando = arc4random_uniform(3);
        if(rando == 1)
           buildMaze(newRoom, 's');//build north room

        rando = arc4random_uniform(3);
        if(rando == 1)
           buildMaze(newRoom, 'n');//build south room

        rando = arc4random_uniform(3);
        if(rando == 1)
           buildMaze(newRoom, 'w');//build east room
    }
    //home room always has 4 doors
    else
    {
        buildMaze(newRoom, 's');//build north room
        buildMaze(newRoom, 'n');//build south room
        buildMaze(newRoom, 'w');//build east room
        buildMaze(newRoom, 'e');//build west room
    }
}

//longest distance from home
int height(Room *r)
{
    int n, s, e, w;
    if (r == nullptr)
        return 0;
    else
    {
        //compute the height of each subtree
        n = height(r->northDoor);
        s = height(r->southDoor);
        e = height(r->eastDoor);
        w = height(r->westDoor);

        //return the largest tree height
        if (n >= s && n >= e && n >= w)
            return (n + 1);
        else if(s >= n && s >= e && s >= w)
            return (s + 1);
        else if(e >= n && e >= s && e >= w)
            return (e + 1);
        else
            return (w + 1);
    }
}

1 个答案:

答案 0 :(得分:0)

正如Will_Panda所说,有无限的递归,因为回到你来自房间的链接意味着你只是在递归循环中走了一圈。

最简单的修复方法是向您Room类添加一个字段,以指示该房间已作为高度计算的一部分被访问过。然后,如果在开始计算之前visited为false,则可以使用它来避免无限递归。 E.g。

//longest distance from home
int height(Room *r)
{
    int n, s, e, w;
    if (r == nullptr)
        return 0;
    else if (r->visited) // already been here
        return 0;
    else
    {
        //compute the height of each subtree
        r->visited = true;
        n = height(r->northDoor);
        s = height(r->southDoor);
        e = height(r->eastDoor);
        w = height(r->westDoor);

        //return the largest tree height
        if (n >= s && n >= e && n >= w)
            return (n + 1);
        else if(s >= n && s >= e && s >= w)
            return (s + 1);
        else if(e >= n && e >= s && e >= w)
            return (e + 1);
        else
            return (w + 1);
    }
}

一旦你知道了高度,就必须再次通过所有房间清理所有访问过的字段

//clear visited fields
void clear_visited(Room *r)
{
    if (r == nullptr)
        return;
    else if (!r->visited) // already cleared
        return;
    else
    {
        r->visited = false;
        clear_visited(r->northDoor);
        clear_visited(r->southDoor);
        clear_visited(r->eastDoor);
        clear_visited(r->westDoor);
    }
}

完全未经测试的代码。