C++二进制树堆栈溢出

C++ Binary Tree Stack Overflow

本文关键字:栈溢出 堆栈 二进制 C++      更新时间:2023-10-16

好吧,我已经调试了几个小时了,但没有任何进展。我正在尝试使用二进制树测试一个简单的递归。

测试时,在main的print_attributes函数的第三次调用时,我得到了堆栈溢出(如下所示)。对调用堆栈的快速检查显示,它充满了数百个对binTree的binTree高度(Node<T>*节点)的调用(也在下面说明)。当我从调用堆栈"转到"调用时,它会使我调整(Node<T>*Node)的左侧调用=大小(Node->left)(也在下面说明)。我不知道这意味着什么,因为这两个函数都不相互调用。

以下是编译器在堆栈溢出发生时所说的内容(我使用的是VS2013):http://puu.sh/ca3ti/e00f653282.png

然后是编译器的图像,在中断并单击调用堆栈中的任何height()调用之后:http://puu.sh/ca2Qz/d35348ccce.png

考虑到在使用bintree的height()和/或size()函数之前,它(似乎)将节点插入到树中很好,我不知道为什么同一个函数在这里开始出现问题。我很抱歉不能更清楚地解释问题所在。我已经编码了几年,但我真的很困惑。我已尽力提供尽可能多的信息。非常感谢所有花时间来帮忙的人。

节点类:

#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

节点树类:

#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 " ) << "emptyn";
    // print size and height of tree
    cout << "tno of nodes    = " << setw ( 2 ) << tree.size ( )
         << "ntheight of tree = " << setw ( 2 ) << tree.height ( )
         << endl << endl; //*******issue here************
    system("pause");
    return 0;
}

首先,在类binTree中,size()height()方法都有以下行:

if (root = 0)

显然,这应该是==

然而,实际的堆栈溢出问题似乎是由insert函数引起的。它引用了第一个参数node。因此,当用insert(root, t)调用它时,node最终会作为对root的引用。当在insert中分配新节点时,root被设置为指向新节点,这也会更改node引用。

如果使用调试器在insert函数的顶部设置断点并逐步执行,则可以观察值的变化。

这意味着rootnode是相同的,所以当设置node->left = nnode->right = n时,节点最终指向自己。

要修复它,您只需要更改insert的定义,使其通过值而不是引用传递node

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