【问题标题】:C++ Out Of Range When using Vector使用矢量时 C++ 超出范围
【发布时间】:2018-10-13 08:57:09
【问题描述】:

所以我通过将节点放入向量中来创建二叉搜索树 (BST)。这些节点存储3个值,一个用户输入int ID,一个用户输入int年龄,一个用户string输入姓名。

将这些节点插入向量时,它们按升序存储。

目前我正在使用两个节点。

104 10 鲍勃

102 11 史蒂夫

推回第一个节点时,没有问题;但是,当尝试推回第二个节点时,我收到了向量类抛出的 out_of_bounds 错误。

在尝试切换这两个节点的位置时,我认为我的插入函数有问题,但是我无法准确判断问题出在哪里。

#include "BinaryTree.h"
#include <string>
#include <iostream>
#include <vector>

using namespace std;
int index;

struct Node
{
    int ID;
    int age;
    string name;

    Node()
    {

    }

    Node(int id, int Age, string nm)
    {
        this->ID = id;
        this->age = Age;
        this->name = nm;
    }
};

vector<Node> binaryTree;


BST::BST()
{

}



void BST::start()
{
    int choice;


    cout << "What would you like to do?" << endl;
    cout << "1. Add a node to the tree" << endl;
    cout << "2. Delete a node from the tree" << endl;
    cout << "3. Find a node in the tree" << endl;
    cout << "4. Report the contents of the tree" << endl;
    cout << "5. Exit program" << endl;

    cin >> choice;

    if (choice == 1)
    {
        insert();
    }

    if (choice == 3)
    {
        find();
    }

    if (choice == 4)
    {
        report();
    }


}


void BST::insert()
{

    int ID;
    int AGE;

    string NAME;

    cout << "Please enter the ID number, age and name" << endl;
    cin >> ID >> AGE >> NAME;

    Node *tree = new Node(ID, AGE, NAME);

    if (index == 0)
    {
        binaryTree.push_back(*tree);
        index++;
    }

    if (index > 0)
    {
        if ((binaryTree.at(index - 1).ID) < ID)
        {
            binaryTree.push_back(*tree);
            index++;
        }
    }


    if (index > 0)
    {
        if ((binaryTree.at(index - 1).ID) > ID)
        {
            Node *temp = new Node();
            *temp = binaryTree.at(index - 1);
            binaryTree.at(index - 1) = *tree;

            binaryTree.at(index) = *temp;
            index++;
        }
    }

    cout << "Added! Size: " << binaryTree.size() << endl;
    cout << " " << endl;
    start();

不胜感激!谢谢!

【问题讨论】:

  • 你的节点不应该持有 2 个节点吗?
  • @ZivS - 这是i 的孩子是2*i2*i + 1 的表示。因此向量
  • 您正在泄漏内存。您动态分配一个对象,将对象复制到向量中,然后在函数结束时丢失原始对象。你也在if 中做类似的事情。简单地摆脱指针和动态分配将修复内存泄漏。
  • 如果它使用不同的数据结构,它会,但它被存储在一个向量中,它并不完全“需要”它。至少这是我的假设
  • 1) 不就是错字吗:binaryTree.at(index - 1) = *tree; binaryTree.at(index) = *temp;(注意第二个at)?由于index 包含vector 中的元素数量(我认为没有意义,因为std::vector 具有size 方法),最大有效索引为index - 1。 2) 你在所有这些new 调用中泄漏内存,而没有deleteing 你new

标签: c++ vector nodes indexoutofboundsexception push-back


【解决方案1】:

当您执行此操作时,您的矢量不会调整大小:binaryTree.at(index) = *tree;

执行push_back() 然后尝试排序

binaryTree.push_back(*tree;)
std::sort(binaryTree.begin(),binaryTree.end(),[](const Node& n1, const Node& n2){//do your comparations});

或者干脆使用std::set

如果你想在不崩溃的情况下使用 std::vector,那么你的 insert() 必须如下所示:

void BST::insert()
{
    int ID;
    int AGE;

    string NAME;

    cout << "Please enter the ID number, age and name" << endl;
    cin >> ID >> AGE >> NAME;

    //Node *tree = new Node(ID, AGE, NAME); // Don't use new here, there is no need in this
    Node tree(ID, AGE, NAME);

    binaryTree.push_back(tree);
    std::sort(binaryTree.begin(), binaryTree.end(), [](const Node& n1, const Node& n2)
          {
              //compare your nodes here
              return (n1.ID > n2.ID);
          });

    cout << "Added! Size: " << binaryTree.size() << endl;
    cout << " " << endl;
    start();
}

但这不会是二叉树。您需要其他数据结构来创建二叉树,std::vector 不能是二叉树。 有一个现成的解决方案,看看std::set,它会插入你需要的元素,你需要将你的自定义比较功能添加到std::set,一切都会好起来的。 这是std::set 的示例:

class Node
{
public:
    Node(int id):ID(id){}
    int ID;
};

class NodeComparator
{
public:
    bool operator()(const Node& n1,const Node& n2)
    {
        return n1.ID < n2.ID;
    }
};

int main()
{
    std::set<Node, NodeComparator> set1;
    set1.insert(10);
    set1.insert(8);
    set1.insert(14);
    set1.insert(2);

    return 0;
}

这是您需要的,std::set 升序排序:

【讨论】:

  • 所以如果我理解正确,我可以删除两个 (index > 0) 语句并将它们替换为单个 std::sort(binaryTree.begin(),binaryTree.end() ,[](const Node& n1, const Node& n2)?
  • 你为什么要在这里使用new?如果您取消引用它并推回它的副本,则不需要这样做......要么持有指向向量中节点的唯一指针,要么只是binaryTree.push_back(Node(ID, AGE, NAME))。如果你有 C++11,你可以使用binaryTree.emplace_back(ID, AGE, NAME)。您不应该将任何newdelete 散布在资源类之外...
  • @ZivS 我同意你的看法,new 之所以使用是因为 OP 在他的代码中这样做了。问题是关于超出范围,而不是关于内存分配。但是好的,我已经修复了它并改进了我的答案。
  • @AlexeyUsachov,你建议他使用delete,这就是为什么我认为你应该改进你的答案。删除了反对票:)
  • @ZivS 谢谢! :)) 我只是想告诉他,如果他使用new,那么在他的上下文中delete 是必要的。
【解决方案2】:

std::vector 有除push_back 之外的方法用于插入元素。具体来说,insert 占据了一个位置,新元素将被插入到该位置。 emplace 更好,因为您甚至不必创建要复制到向量中的元素,只需传递构造函数参数即可。

您可以使用std::lower_bound 找到合适的插入位置。

#include <algorithm>

void BST::insert()
{
    int ID;
    int AGE;
    std::string NAME;

    std::cout << "Please enter the ID number, age and name" << std::endl;
    std::cin >> ID >> AGE >> NAME;

    auto pos = std::lower_bound(binaryTree.begin(), binaryTree.end(), 
        [](const Node& n1, const Node& n2) { return (n1.ID > n2.ID); });

    binaryTree.emplace(pos, ID, AGE, NAME);

    std::cout << "Added! Size: " << binaryTree.size() << endl;
    std::cout << " " << std::endl;
    // start(); // dubious, see below
}

顺便说一句,您知道startinsert 方法泄露了您以后可能想要更改的假设。将所有内容包含在start 中会更好,例如:

void BST::start()
{
    std::cout << "What would you like to do?" << std::endl;
    std::cout << "1. Add a node to the tree" << std::endl;
    std::cout << "2. Delete a node from the tree" << std::endl;
    std::cout << "3. Find a node in the tree" << std::endl;
    std::cout << "4. Report the contents of the tree" << std::endl;
    std::cout << "5. Exit program" << std::endl;

    for(int choice; (std::cin >> choice) && (choice != 5);)
    {   
        switch (choice)
        {
        case 1: insert(); break;
        case 3: find(); break;
        case 4: report(); break;
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-14
    • 1970-01-01
    • 2018-06-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多