C++ 为什么该代码运行于VS而非gcc/g++;?
我正在尝试使用VS2019作为IDE实现一个红黑树。它似乎在VS中工作,但当我尝试使用任何其他方法编译和运行时,每当我的insert函数被多次调用时,它就会导致seg错误。(我尝试过在线编译器并将其发送给朋友)我陷入困境,因为我不知道从哪里开始尝试修复我的错误。我听说VS处理动态内存的方式不同,但我不太确定 下面是我的旋转、BST插入和插入函数C++ 为什么该代码运行于VS而非gcc/g++;?,c++,red-black-tree,C++,Red Black Tree,我正在尝试使用VS2019作为IDE实现一个红黑树。它似乎在VS中工作,但当我尝试使用任何其他方法编译和运行时,每当我的insert函数被多次调用时,它就会导致seg错误。(我尝试过在线编译器并将其发送给朋友)我陷入困境,因为我不知道从哪里开始尝试修复我的错误。我听说VS处理动态内存的方式不同,但我不太确定 下面是我的旋转、BST插入和插入函数 #include <iostream> #include <vector> // default constructor //
#include <iostream>
#include <vector>
// default constructor
// creates empty tree, root is nullptr
class NodeT
{
public:
// public variables
double key;
double value;
NodeT* left;
NodeT* right;
NodeT* parent;
bool isBlack;
// constructors
NodeT()
{
key = 0;
value = 0;
left = nullptr;
right = nullptr;
parent = nullptr;
isBlack = false;
}
NodeT(double keyset, double valueset, bool isBlackset)
{
key = keyset;
value = valueset;
left = nullptr;
right = nullptr;
parent = nullptr;
isBlack = isBlackset;
}
};
class RedBlackTree
{
public:
// default constructor, sets all to null
RedBlackTree();
// insert
// inserts the first parameter key, and value second parameter into the tree
// returns true if done, false if there are duplicates, dont insert
bool insert(double insert_key, double insert_value);
public:
NodeT* root;
void leftrotate(NodeT* to_rotate);
void rightrotate(NodeT* to_rotate);
bool bstinsert(NodeT* insert);
};
RedBlackTree::RedBlackTree()
{
root = nullptr;
}
void RedBlackTree::leftrotate(NodeT* to_rotate)
{
NodeT* new_parent = nullptr;
new_parent = to_rotate->right;
to_rotate->right = new_parent->left;
if (new_parent->left != nullptr)
{
new_parent->left->parent = to_rotate;
}
new_parent->parent = to_rotate->parent;
if (to_rotate->parent == nullptr)
{
root = new_parent;
}
else if (to_rotate == to_rotate->parent->left)
{
to_rotate->parent->left = new_parent;
}
else
{
to_rotate->parent->right = new_parent;
}
new_parent->left = to_rotate;
to_rotate->parent = new_parent;
}
void RedBlackTree::rightrotate(NodeT* to_rotate)
{
NodeT* new_parent = to_rotate->left;
to_rotate->left = new_parent->right;
if (new_parent->right != nullptr)
{
new_parent->right->parent = to_rotate;
}
new_parent->parent = to_rotate->parent;
if (to_rotate->parent == nullptr)
{
root = new_parent;
}
else if (to_rotate == to_rotate->parent->right)
{
to_rotate->parent->right = new_parent;
}
else
{
to_rotate->parent->left = new_parent;
}
new_parent->right = to_rotate;
to_rotate->parent = new_parent;
}
bool RedBlackTree::bstinsert(NodeT* insert)
{
NodeT* parent = root;
NodeT* search = root;
if (root == nullptr)
{
root = insert;
}
else
{
while (search != nullptr)
{
parent = search;
if (insert->key < parent->key)
{
search = parent->left;
}
else if (insert->key > parent->key)
{
search = parent->right;
}
else
{
return false;
}
}
if (insert->key < parent->key)
{
parent->left = insert;
insert->parent = parent;
return true;
}
else if(insert->key > parent->key)
{
parent->right = insert;
insert->parent = parent;
return true;
}
else
{
return false;
}
}
}
bool RedBlackTree::insert(double insert_key, double insert_value)
{
NodeT* y = nullptr;
NodeT* x = new NodeT(insert_key, insert_value, false);
bool dupe = bstinsert(x);
if (dupe == false)
{
return false;
}
while (x != root && x->parent->isBlack == false)
{
if (x->parent == x->parent->parent->left)
{
y = x->parent->parent->right;
if (y == nullptr || y->isBlack == true)
{
if (x == x->parent->right)
{
x = x->parent;
leftrotate(x);
}
x->parent->isBlack = true;
x->parent->parent->isBlack = false;
rightrotate(x->parent->parent);
}
else if (y->isBlack == false)
{
x->parent->isBlack = true;
y->isBlack = true;
x->parent->parent->isBlack = false;
x = x->parent->parent;
}
}
else
{
y = x->parent->parent->left;
if (y == nullptr || y->isBlack == true)
{
if (x == x->parent->left)
{
x = x->parent;
rightrotate(x);
}
x->parent->isBlack = true;
x->parent->parent->isBlack = false;
leftrotate(x->parent->parent);
}
else if (y->isBlack == false)
{
x->parent->isBlack = true;
y->isBlack = true;
x->parent->parent->isBlack = false;
x = x->parent->parent;
}
}
}
root->isBlack = true;
return true;
}
感谢您抽出时间阅读此文章。感谢您的帮助。至少有一个错误会导致未定义的行为:
RedBlackTree::bstinert
函数在本应返回bool
时无法返回值
要验证这是否为错误,可在bstinert
函数结尾前放置一行,以验证这是否为错误
bool RedBlackTree::bstinsert(NodeT* insert)
{
NodeT* parent = root;
NodeT* search = root;
if (root == nullptr)
{
root = insert;
}
else
{
while (search != nullptr)
{
parent = search;
if (insert->key < parent->key)
{
search = parent->left;
}
else if (insert->key > parent->key)
{
search = parent->right;
}
else
{
return false;
}
}
if (insert->key < parent->key)
{
parent->left = insert;
insert->parent = parent;
return true;
}
else if (insert->key > parent->key)
{
parent->right = insert;
insert->parent = parent;
return true;
}
else
{
return false;
}
}
std::cout << "This is undefined behavior\n"; // <-- add this line
}
您不应该忽略此警告。是否尝试使用调试器单步执行
insert
成员函数以查看发生了什么?VS有一个内置的调试器用于Windows@Kaldrr是的,在VS上,我看不出任何错误,我可以插入节点,它们似乎工作正常。出现问题的地方是在另一个编译器上插入多个节点。请发布。这意味着我们应该能够获取您的代码,并且不做任何更改,复制问题。现在,我们不知道RedBlackTree
的构造函数做什么或不做什么。这看起来有点可疑:如果在insert()函数中(x->parent==x->parent->parent->left)
。您确定父级两级深度始终已初始化吗?(我看不到填充它的代码),它可能是未定义的/null。否则我们将需要完整的代码。这会在哪些编译器上失败?-例如,在使用gcc的linux中,您可以使用类似vscode+gdb的IDE对其进行调试。这些指针很可能没有初始化。如果是这样,VisualStudio版本也会被破坏。也许如果你运行一个发布版本,你会发现有一个问题。值得一提的是,实际编译并运行类似的东西意味着OP故意忽略编译器的诊断输出。当遇到函数无法返回声明类型的值时,编译器通常会抱怨。:)
Ah。我想我已经测试过了,所以我认为这不是问题所在。我认为bstinsert现在返回正确的值,现在我在主insert函数中有一个可复制的错误,我现在可以尝试修复它。谢谢你的帮助@仅供参考——不要修复代码并在发布模式下重新编译并运行它。您应该看到抛出了一个异常。这正是未定义行为的含义。
bool RedBlackTree::bstinsert(NodeT* insert)
{
NodeT* parent = root;
NodeT* search = root;
if (root == nullptr)
{
root = insert;
}
else
{
while (search != nullptr)
{
parent = search;
if (insert->key < parent->key)
{
search = parent->left;
}
else if (insert->key > parent->key)
{
search = parent->right;
}
else
{
return false;
}
}
if (insert->key < parent->key)
{
parent->left = insert;
insert->parent = parent;
return true;
}
else if (insert->key > parent->key)
{
parent->right = insert;
insert->parent = parent;
return true;
}
else
{
return false;
}
}
std::cout << "This is undefined behavior\n"; // <-- add this line
}
warning C4715: 'RedBlackTree::bstinsert': not all control paths return a value