我尝试用c ++编程一个二进制搜索树,使用一个用于null节点的构造函数,该结构将主数组插入到其中并打印结果,至少这是我们的初衷。如前所述,我遇到了这两个错误,需要将它们更正为规格。需要做的是创建一个node_t *构造函数,并将该数组插入二进制搜索树中。 错误:没有匹配的函数可以调用“ BST :: insert(BST&,std :: array :: value_type&)” 错误:没有匹配的函数可以调用'BST :: print_bst(BST&)'
#include <cstdio>
#include <cstdlib>
#include <array>
using namespace std;
/*
* Define a node structure for double linked list.
*/
class BST
{
private:
typedef struct node {
int val;
struct node* left;
struct node* right;
} node_t;
node_t* tree;
public:
BST() { tree = NULL; }
node_t* newNode(int val);
node_t* insert(node_t* cur_root, int val);
node_t* find_node(int val, node_t* root);
node_t* find_val(int val, node_t* root);
node_t* delete_node(int val, node_t* root);
void delete_bst(node_t* root);
void print_bst(node_t* root);
node_t* find_max(node_t* root);
};
// Creates a new node from a given value, allocating heap memory
// for it.
BST::node_t* BST::newNode(int val)
{
node_t* newNode = new node;
newNode->val = val;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
// Inserts a new value into a given binary search tree,
// allocating heap memory for it.
BST::node_t* BST::insert(BST::node_t* cur_root, int val)
{
if(cur_root == NULL) { return newNode(val); }
if( val <= cur_root->val )
cur_root->left = insert(cur_root->left, val);
else if( val > cur_root->val)
cur_root->right = insert(cur_root->right, val);
return cur_root;
}
BST::node_t* BST::find_node(int val, BST::node_t* root) {
if (root == NULL || root->val == val) { return root; }
else if (root->val <= val) {
return find_node( val, root->left );
}
else { return find_node( val, root->right ); }
return root;
}
BST::node_t* BST::find_max(BST::node_t* root)
{
if(root == NULL)
return NULL;
while(root->right != NULL)
{
root = root->right;
}
return root;
}
// Deletes node and reorders bst
BST::node_t* BST::delete_node(int val, BST::node_t* root)
{
if( root == NULL ) return root;
else if( val <= root->val )
root->left = delete_node( val, root->left );
else if( val > root->val )
root->right = delete_node( val, root->right );
else
{
// No child
if( root->right == NULL && root->left == NULL )
{
delete root;
root = NULL;
}
// One child
else if(root->right == NULL)
{
node_t* temp = root;
root = root->left;
delete temp;
}
else if( root->left == NULL )
{
node_t* temp = root;
root = root->right;
delete temp;
}
// Two child
else
{
node_t* temp = find_max(root->left);
root->val = temp->val;
root->left = delete_node(temp->val, root->left);
}
}
return root;
}
// Given a pointer to the root, frees the memory associated with
// an entire tree.
void BST::delete_bst(BST::node_t* root) {
if(root != NULL)
{
delete_bst( root->left );
delete_bst( root->right );
delete(root);
if( root->left != NULL)
root->left = NULL;
if( root->right != NULL)
root-> right = NULL;
root = NULL;
}
}
/* Given a pointer to the root, prints all of
* the values in a tree.
*/
void BST::print_bst(BST::node_t* root)
{
if (root != NULL) {
printf("%d ", root->val);
print_bst(root->left);
print_bst(root->right);
}
}
int main()
{
BST bst;
array<int, 9> ai = {17, 9, 23, 5, 11, 21, 27, 20, 22};
for( size_t i = 0; i < ai.size(); ++i)
{
bst.insert(bst, ai[i]);
}
BST::print_bst(bst);
}
答案 0 :(得分:2)
error: no matching function for call to 'BST::insert(BST&, std::array::value_type&)' error: no matching function for call to 'BST::print_bst(BST&)'
错误表明您在insert
中对print_bst
和main()
的呼叫是错误的。具体来说,您有:
for( size_t i = 0; i < ai.size(); ++i)
{
bst.insert(bst, ai[i]);
}
BST::print_bst(bst);
一个明显的问题是BST::print_bst(bst);
。从语法的角度来看,您不需要bst.print_bst(bst);
(这只是冰山一角),因此您无需在此处使用解析运算符
您正在同时向insert
和print_bst
传递参数bst
,这是类型BST
而不是node_t *
的对象。您想要传递给他们的是tree
,但是您不能因为tree
是 private 。
一种解决方法是编写一个简单的访问器函数,以返回tree
的地址以供在函数中使用,例如
public:
...
node_t *get_root (void) { return tree; } /* tree accessor */
现在您可以按以下方式同时呼叫insert
和print_bst
:
for (size_t i = 0; i < ai.size(); i++)
bst.insert (bst.get_root(), ai[i]);
bst.print_bst (bst.get_root());
putchar ('\n'); /* make your program POSIX compliant with final '\n' */
}
从编译的角度来看,您还应该使用-Wshadow
进行编译,以确保您不会在其他范围内隐藏或尝试重新声明变量。您在这里遇到了这个问题:
BST::node_t* BST::newNode(int val)
{
node_t* newNode = new node;
newNode
遮盖了成员函数newNode
,例如
public:
...
node_t* newNode(int val);
您可以简单地将在newNode
中声明的新节点更改为newnode
(或其他任何与您的成员函数不冲突的节点)。虽然这不是这里使用的方式的问题,但是如果您不检查阴影名称,它可能会咬住您。
在BST
对象中,tree
是指向二进制树的开头的指针,但是您永远不会将二进制树的开头(或其他任何与此相关的东西)分配给{{1} }。您最终用tree
一遍又一遍地调用insert
并返回了cur_root == NULL
,该地方没有使用过,所以结果是return newNode(val);
总是cur_root
。相反,您需要检查是否NULL
并将tree == NULL
设置为tree = newNode (val);
。如果您只想返回指针return (tree = newNode (val));
,例如
/* Inserts a new value into a given binary search tree,
* allocating heap memory for it.
*/
BST::node_t *BST::insert (BST::node_t *cur_root, int val)
{
if (tree == NULL) /* you must assign 1st node to tree */
return (tree = newNode(val));
if (cur_root == NULL)
return (cur_root = newNode(val));
if (val <= cur_root->val )
cur_root->left = insert (cur_root->left, val);
else if (val > cur_root->val)
cur_root->right = insert (cur_root->right, val);
return cur_root;
}
注意:保持参数顺序一致。不要交换订单,这只会使事情变得非常混乱,例如
node_t* insert(node_t* cur_root, int val);
node_t* find_node(int val, node_t* root);
一种方法或另一种方法。我更喜欢(node_t* cur_root, int val)
,但这取决于您。如果您更喜欢(int val, node_t* root)
,请使用它,但要保持一致。
您的BST::delete_bst
在释放值以将其设置为NULL
后尝试访问值,例如
// Given a pointer to the root, frees the memory associated with
// an entire tree.
void BST::delete_bst(BST::node_t* root) {
if(root != NULL)
{
delete_bst( root->left );
delete_bst( root->right );
delete(root);
if( root->left != NULL)
root->left = NULL;
if( root->right != NULL)
root-> right = NULL;
root = NULL;
}
}
到root->left = NULL;
,root-> right = NULL;
和root = NULL;
时,这些内存块不再存在。
相反,您可以使用以下内容,并在末尾设置tree = NULL;
/* Given a pointer to the root, frees the memory associated with
* an entire tree.
*/
void BST::delete_bst (BST::node_t *root)
{
if (root != NULL) {
delete_bst (root->left);
delete_bst (root->right);
delete(root);
}
tree = NULL;
}
您可以通过在Linux上使用诸如valgrind
之类的内存错误检查程序来找到这些问题。 (但是很明显,您的代码必须先编译才能完成)。每个操作系统都有类似的程序。
这是您的大部分逻辑问题。您需要纠正一些清理问题,例如,如果声明一个构造函数,然后还要声明一个析构函数。如果声明构造函数或析构函数,则还应该声明一个 copy-constructor ,请参见Rule of Three
此外,请确保程序的输出符合POSIX,并且始终提供最终的'\n'
。否则,从控制台运行时,您的提示将停留在输出的最后一行的末尾。您可以简单地在putchar ('\n');
的末尾加上main()
(因为您没有包括<iostream>
),或者为print_bst
编写一个简单的包装函数即可,例如
public:
...
void print_tree (void) { print_bst (tree); putchar ('\n'); };
然后您可以在bst.print_tree();
中致电main()
,而不必担心。
将其完全放在一起,您可以执行以下操作:
#include <cstdio>
#include <cstdlib>
#include <array>
using namespace std;
/*
* Define a node structure for a binary tree list.
*/
class BST
{
private:
typedef struct node {
int val;
struct node* left;
struct node* right;
} node_t;
node_t *tree;
public:
BST() { tree = NULL; }
~BST() { delete_bst (tree); } /* if you define BST(), define ~BST() */
node_t *get_root (void) { return tree; } /* tree accessor */
node_t *newNode (int val);
node_t *insert (node_t* cur_root, int val);
node_t *find_node (node_t* root, int val);
node_t *find_val (node_t* root, int val);
node_t *delete_node (node_t* root, int val);
void delete_bst (node_t* root);
void print_bst (node_t* root);
node_t *find_max (node_t* root);
/* make program output POSIX compliant with final '\n'
* (just create a wrapper for print_bst, or add putchar('\n') in main )
*/
void print_tree (void) { print_bst (tree); putchar ('\n'); };
};
/* Creates a new node from a given value, allocating heap memory for it. */
BST::node_t* BST::newNode (int val)
{
node_t* newnode = new node_t;
newnode->val = val;
newnode->left = NULL;
newnode->right = NULL;
return newnode;
}
/* Inserts a new value into a given binary search tree,
* allocating heap memory for it.
*/
BST::node_t *BST::insert (BST::node_t *cur_root, int val)
{
if (tree == NULL) /* you must assign 1st node to tree */
return (tree = newNode(val));
if (cur_root == NULL)
return (cur_root = newNode(val));
if (val <= cur_root->val )
cur_root->left = insert (cur_root->left, val);
else if (val > cur_root->val)
cur_root->right = insert (cur_root->right, val);
return cur_root;
}
/* determine whether node with value exists in tree
* (don't swap parameter order -- it's confusing)
*/
BST::node_t *BST::find_node (BST::node_t *root, int val)
{
if (root == NULL || root->val == val)
return root;
else if (root->val <= val) {
return find_node (root->left, val);
}
else
return find_node (root->right, val);
return root;
}
/* determine maximum value in the tree */
BST::node_t* BST::find_max (BST::node_t* root)
{
if (root == NULL)
return NULL;
while (root->right != NULL)
root = root->right;
return root;
}
/* Deletes node and reorders bst */
BST::node_t* BST::delete_node (BST::node_t* root, int val)
{
if (root == NULL)
return root;
else if (val <= root->val)
root->left = delete_node (root->left, val);
else if (val > root->val)
root->right = delete_node (root->right, val);
else {
// No child
if (root->right == NULL && root->left == NULL) {
delete root;
root = NULL;
}
// One child
else if (root->right == NULL) {
node_t *temp = root;
root = root->left;
delete temp;
}
else if (root->left == NULL) {
node_t *temp = root;
root = root->right;
delete temp;
}
// Two child
else {
node_t *temp = find_max (root->left);
root->val = temp->val;
root->left = delete_node (root->left, temp->val);
}
}
return root;
}
/* Given a pointer to the root, frees the memory associated with
* an entire tree.
*/
void BST::delete_bst (BST::node_t *root)
{
if (root != NULL) {
delete_bst (root->left);
delete_bst (root->right);
delete(root);
}
tree = NULL;
}
/* Given a pointer to the root, prints all of
* the values in a tree.
*/
void BST::print_bst (BST::node_t *root)
{
if (root != NULL) {
printf ("%d ", root->val);
print_bst (root->left);
print_bst (root->right);
}
}
int main (void) {
BST bst;
array<int, 9> ai = {17, 9, 23, 5, 11, 21, 27, 20, 22};
for (size_t i = 0; i < ai.size(); i++)
bst.insert (bst.get_root(), ai[i]);
bst.print_tree(); /* POSIX comliant output w/final '\n'
* use wrapper function, or just putchar('\n') here
*/
}
使用/输出示例
$ ./bin/arr_bst
17 9 5 11 23 21 20 22 27
内存使用/错误检查
$ valgrind ./bin/arr_bst
==8123== Memcheck, a memory error detector
==8123== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==8123== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==8123== Command: ./bin/arr_bst
==8123==
17 9 5 11 23 21 20 22 27
==8123==
==8123== HEAP SUMMARY:
==8123== in use at exit: 0 bytes in 0 blocks
==8123== total heap usage: 10 allocs, 10 frees, 72,920 bytes allocated
==8123==
==8123== All heap blocks were freed -- no leaks are possible
==8123==
==8123== For counts of detected and suppressed errors, rerun with: -v
==8123== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
始终确认已释放已分配的所有内存,并且没有内存错误。
仔细检查一下,如果还有其他问题,请告诉我。
答案 1 :(得分:0)
好,我修复了插入和打印功能,
#include <cstdio>
#include <cstdlib>
#include <array>
using namespace std;
/*
* Define a node structure for double linked list.
*/
class BST
{
private:
typedef struct node {
int val;
struct node* left;
struct node* right;
} node_t;
node_t* tree;
public:
BST() { tree = NULL; }
node_t* newNode(int val);
node_t* insert(node_t *&cur_root, int val);
node_t* find_node(int val, node_t* root);
node_t* find_val(int val, node_t* root);
node_t* delete_node(int val, node_t* root);
void delete_bst(node_t* root);
void print_bst(node_t* root);
node_t* find_max(node_t* root);
node_t *bstroot;
};
// Creates a new node from a given value, allocating heap memory
// for it.
BST::node_t* BST::newNode(int val)
{
node_t* newNode = new node;
newNode->val = val;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
// Inserts a new value into a given binary search tree,
// allocating heap memory for it.
BST::node_t* BST::insert(BST::node_t *&cur_root, int val)
{
if(cur_root == NULL) {
cur_root = newNode(val);
}
else if( val <= cur_root->val )
cur_root->left = insert(cur_root->left, val);
else if( val > cur_root->val)
cur_root->right = insert(cur_root->right, val);
return cur_root;
}
void BST::print_bst(BST::node_t* root)
{
if (root != NULL) {
printf("%d ", root->val);
print_bst(root->left);
print_bst(root->right);
}
}
int main()
{
BST bst;
array<int, 9> ai = {17, 9, 23, 5, 11, 21, 27, 20, 22};
for( size_t i = 0; i < ai.size(); ++i)
{
bst.insert(bst.bstroot, ai[i]);
}
bst.print_bst(bst.bstroot);
}