二进制搜索树没有匹配的函数调用

时间:2018-07-22 04:44:56

标签: c++

我尝试用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);
}

2 个答案:

答案 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_bstmain()的呼叫是错误的。具体来说,您有:

    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);(这只是冰山一角),因此您无需在此处使用解析运算符

您正在同时向insertprint_bst传递参数bst,这是类型BST而不是node_t *的对象。您想要传递给他们的是tree,但是您不能因为tree private

一种解决方法是编写一个简单的访问器函数,以返回tree的地址以供在函数中使用,例如

  public:
    ...
    node_t *get_root (void) { return tree; }    /* tree accessor */

现在您可以按以下方式同时呼叫insertprint_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);
}