简体   繁体   English

C ++二叉树堆栈溢出

[英]C++ Binary Tree Stack Overflow

Alright, I've been debugging this for a few hours now and am getting nowhere. 好了,我已经调试了几个小时,却一无所获。 I'm trying to test a straightforward recursion-using binary tree. 我正在尝试测试一个简单的使用递归的二叉树。

When tested, I get a stack overflow at the third call in main's print_attributes function (noted below). 经过测试,我在main的print_attributes函数中的第三个调用处获得堆栈溢出(如下所示)。 A quick inspection of the callstack shows that it's full of hundreds of calls to binTree's binTree's height(Node < T >* node) (also noted below). 快速检查一下调用堆栈,发现它已经充满了数百个对binTree的binTree的height(Node <T> * node)的调用(也在下面指出)。 When I "go-to" the call from the Call Stack, it takes me to size(Node < T >* node)'s call of leftside = size(node->left) (also noted below). 当我“转到”来自调用堆栈的调用时,它将带我到size(Node <T> * node)的左侧= size(node-> left)的调用(也在下面进行说明)。 I don't know what that's supposed to indicate, because neither of these functions call each other. 我不知道该说些什么,因为这些功能都不互相调用。

Here's an image of what the compiler says right as the stack overflow occurs (I'm using VS2013): http://puu.sh/ca3ti/e00f653282.png 这是当堆栈溢出时编译器正确说出的图像(我正在使用VS2013): http ://puu.sh/ca3ti/e00f653282.png

Then here's an image of the compiler, after breaking, and clicking any of the height() calls in the call stack: http://puu.sh/ca2Qz/d35348ccce.png 然后是下面的编译器图像:中断后,单击调用堆栈中的任何height()调用: http : //puu.sh/ca2Qz/d35348ccce.png

Considering that it (appears to be) inserting nodes into the tree fine just before while using bintree's height()and/or size() function, I have no idea why the same function begins having issues here. 考虑到(似乎是)在使用bintree的height()和/或size()函数之前将节点很好地插入树中,我不知道为什么相同的函数在这里开始出现问题。 I'm sorry for not being able to be able to more clearly explain what the issue is. 很抱歉,我们无法更清楚地说明问题所在。 I've been coding for a few years but I'm really lost with this. 我已经编码了几年了,但是我真的迷失了。 I've tried to provide as much information as I possibly could. 我试图提供尽可能多的信息。 Thank you so much to anyone who takes the time to help with this. 非常感谢抽出宝贵时间为此提供帮助的任何人。

Node Class: 节点类别:

#include "340.h"

#ifndef H_NODE
#define H_NODE

// definition for class of nodes in bin tree

template < class T > class binTree; // forward declaration

template < class T >
class Node {
friend class binTree < T >;         // binTree is friend
public:
    // default constructor
    Node ( const T& x = T ( ), Node < T >* l = 0, Node < T >* r = 0 ) :
        data ( x ), left ( l ), right ( r ) { }
private:
    T data;                         // data component
    Node < T > *left, *right;       // left and right links
};
#endif

NodeTree Class: NodeTree类:

#include "Node.h"

#ifndef H_TREE
#define H_TREE

template < class T > class binTree {
public:
    binTree(Node < T >* emptyroot = nullptr) : // default constructor
        root(emptyroot) { }

    bool empty() const // checks if tree empty
    {
        if (root == 0)
            return true;
        else
            return false;
    }

    unsigned size() const // returns no of nodes
    {
        if (root == 0)
            return 0;
        else
            return size(root);
    }

    unsigned height() const // returns height of tree
    {
        if (root == 0)
            return 0;
        else
            return height(root);
    }

    virtual void insert(const T& t) // inserts a node in shortest subtree
    {
        if (empty())
        {
            Node< T >* n = new Node< T >;
            n->data = t;
            root = n;
        }
        else
            insert(root, t);
    }
protected:
    Node < T >* root; // root of tree
private:
    unsigned size(Node < T >* node) const // private version of size ( )
    {
        unsigned leftside;
        unsigned rightside;

        if (node->left == 0)
            leftside = 0;
        else
            leftside = size(node->left); //******issue(?) here******

        if (node->right == 0)
            rightside = 0;
        else
            rightside = size(node->right);

        return(leftside + rightside + 1);
    }

    unsigned height(Node < T >* node) const // private version of height ( ) 
//*****issue(?) here************
    {
        unsigned leftside;
        unsigned rightside;

        if (node->left == 0)
            leftside = 0;
        else
            leftside = height(node->left);

        if (node->right == 0)
            rightside = 0;
        else
            rightside = height(node->right);

        return 1 + max(leftside, rightside);
    }

    void insert(Node < T >* node, const T& t) // private version of insert ( )
    {
        if (node->left == 0)
        {
            Node< T >* n = new Node< T >;
            n->data = t;
            root = n;

            node->left = n;
            return;
        }
        else if (node->right == 0)
        {
            Node< T >* n = new Node< T >;
            n->data = t;
            root = n;

            node->right = n;
            return;
        }

        unsigned lefth = height(node->left);
        unsigned righth = height(node->right);

        if (lefth <= righth)
        {
            insert(node->left, t);
        }
        else
        {
            insert(node->right, t);
        }       
    }
};

#endif

Main: 主要:

#include "binTree.h"

// vectors used in testing
const vector < int > A { 1, -2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12,
        13, -14, 15 };

// prints out val passed as argument
template < class T > void print ( T& x ) { cout << x << ' '; }

// increments val passed as argument
template < class T > void increment ( T& x ) { x++; }

// decrements val passed as argument
template < class T > void decrement ( T& x ) { x--; }

// prints out attributes, such as size and height of bin tree,
// and prints out data val in each node in inorder, preorder,
// and postorder

template < class T >
void print_attributes ( binTree < T >& tree, const string& name )
{
    cout << name; // print name of tree

    // check if tree is empty
    cout << ": tree is " << ( tree.empty ( ) ? "" : "not " ) << "empty\n";

    // print size and height of tree
    cout << "\tno of nodes    = " << setw ( 2 ) << tree.size ( )
         << "\n\theight of tree = " << setw ( 2 ) << tree.height ( )
         << endl << endl; //*******issue here************

    system("pause");
    return 0;
}

Firstly, in your class binTree , both the size() and height() methods have the following line: 首先,在类binTreesize()height()方法都具有以下行:

if (root = 0)

Obviously this should be == . 显然,这应该是==

The actual stack overflow problem though seems to be caused by your insert function. 实际的堆栈溢出问题似乎是由您的insert函数引起的。 It takes the first parameter, node by reference. 它采用第一参数, node通过引用。 So when you call it with insert(root, t) , node ends up as a reference to root . 因此,当您使用insert(root, t)调用它时, node最终将成为对root的引用。 When a new node is allocated in insert , root is set to point to the new node, and this changes the node reference as well. insert分配新节点时, insert root设置为指向新节点,这也会更改node引用。

If you use the debugger to set a breakpoint at the top of your insert function and step through you can watch the values change. 如果使用调试器在insert函数的顶部设置断点并逐步执行,则可以观察到值的变化。

What this means is that root and node are the same thing, so when you set node->left = n or node->right = n the node ends up pointing at itself. 这意味着rootnode是同一件事,因此,当您设置node->left = nnode->right = n ,节点最终指向自己。

All you should have to do to fix it is change the definition of insert to pass node by value rather than reference: 解决该问题所需要做的就是更改insert的定义以按值而不是引用传递node

void insert(Node < T >* node, const T& t) // private version of insert ( )

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM