Хорошо, я отлаживаю это в течение нескольких часов, и я никуда не уйду. Я пытаюсь проверить прямое двоичное дерево, использующее рекурсию.
При тестировании я получаю переполнение стека при третьем вызове в основной функции print_attributes (см. Ниже). Быстрый просмотр стоп-кадра показывает, что он содержит сотни вызовов высоты binTree binTree (узел Node <T> *) (также отмечено ниже). Когда я "перехожу к" вызову из стека вызовов, он принимает меня к размеру (узлу <T> * node) вызов leftside = size (node-> слева) (также отмечено ниже). Я не знаю, что это должно указывать, потому что ни одна из этих функций не вызывает друг друга.
Здесь изображение того, что компилятор говорит правильно, когда происходит переполнение стека (я использую 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
Класс 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
Главный:
#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;
}
Во-первых, в вашем классе binTree
size()
и height()
имеют следующую строку:
if (root = 0)
Очевидно, что это должно быть ==
.
Фактическая проблема, по-видимому, вызвана вашей функцией insert
. Он принимает первый параметр, node
по ссылке. Поэтому, когда вы вызываете его со insert(root, t)
, node
заканчивается ссылкой на root
. Когда новый узел распределяется во insert
, root
устанавливается для указания на новый узел, и это также изменяет ссылку на node
.
Если вы используете отладчик для установки точки останова в верхней части своей функции insert
и выполните шаг, вы можете наблюдать за изменением значений.
Это означает, что root
и node
- одно и то же, поэтому, когда вы устанавливаете node->left = n
или node->right = n
узел заканчивается, указывая на себя.
Все, что вам нужно сделать, чтобы исправить это, - это изменение определения insert
для передачи node
по значению, а не по ссылке:
void insert(Node < T >* node, const T& t) // private version of insert ( )