c++ - 当我使用 1000 个键值的数据集时出现分段错误,并且由于某种原因,AVL 旋转不会发生在节点周围
问题描述
#include "BST.h"
#include "AVL.h"
#include <iostream>
AVLTree::AVLTree() {
}
int AVLTree::max(int a, int b) {
return (a > b)? a : b;
}
int AVLTree::height(std::shared_ptr<BSTNode>N) const {
if (N == nullptr){
return 0;
}
return N->height_;
}
void AVLTree::fixHeight(std::shared_ptr<BSTNode>& N) {
auto h1 = height(N->left_);
auto h2 = height(N->right_);
N->height_ = (h1 > h2 ? h1 : h2) + 1;
}
int AVLTree::getBalance(std::shared_ptr<BSTNode> N) {
if (N == nullptr)
return 0;
return height(N->left_) - height(N->right_);
}
std::shared_ptr<BSTNode> AVLTree::rightRotate(std::shared_ptr<BSTNode>n){
std::shared_ptr<BSTNode>x = n->left_;
std::shared_ptr<BSTNode>T2 = x->right_;
std::weak_ptr<BSTNode>tempParent = n->parent_;
// Perform rotation
x->right_ = n;
n->left_ = T2;
// Update heights
n->height_ = max(height(n->left_), height(n->right_)) + 1;
x->height_ = max(height(x->left_), height(x->right_)) + 1;
tempParent = x;
// Return new root
return x;
}
std::shared_ptr<BSTNode> AVLTree::leftRotate(std::shared_ptr<BSTNode>n){
std::shared_ptr<BSTNode>y = n->right_;
std::shared_ptr<BSTNode>T2 = y->left_;
std::weak_ptr<BSTNode>tempParent = n->parent_;
// Perform rotation
y->left_ = n;
n->right_ = T2;
// Update heights
n->height_ = max(height(n->left_), height(n->right_)) + 1;
y->height_ = max(height(y->left_), height(y->right_)) + 1;
tempParent = y;
// Return new root
return y;
}
void AVLTree::balance(std::shared_ptr<BSTNode> N) {
if(N != root_){
if(getBalance(N) >= -1 && getBalance(N) <= 1){
if(N != root_){
balance(N->parent_.lock());
}
}
if(getBalance(N) == 2){
if(N->key_ < N->left_->key_){
rightRotate(N);
}
if(N->key_ < N->left_->key_){
N->left_ = leftRotate(N->left_);
rightRotate(N);
}
}
if(getBalance(N) == -2){
if(N->key_ > N->right_->key_){
leftRotate(N);
}
if(N->key_ < N->right_->key_){
N->right_ = rightRotate(N->right_);
leftRotate(N);
}
}
}
N->height_= max( height( N->left_ ), height( N->right_ ) ) + 1;
}
void AVLTree::AVLInsert(int key) {
std::shared_ptr<BSTNode>lastNode;
lastNode = BST::Insert(key);
balance(lastNode);
}
所以我应该实现一个带有 JSON 文件输入的 AVL 树。因此,出于这个原因,我创建了一个 AVLTree 类。这个类的问题是,当我使用 1000 的数据集时,它不起作用,但它适用于 10 的数据集。我的 AVL 旋转似乎也不起作用,因此树永远不会平衡在根周围,但除此之外,它工作得很好。
The BST::Insert(key)
返回最后一个节点,也就是刚刚插入的节点。
我使用智能指针指向每个值并在 BST 中移动它们。我的 BST 类使用智能指针,所以如果有人可以帮助我使用智能指针,我会很高兴。
是的,这是一项任务,但这只是我无法弄清楚的一个小错误。
BSTNode::BSTNode(int key) :
key_(key),
parent_(std::weak_ptr<BSTNode>()),
left_(nullptr),
right_(nullptr) {}
BSTNode::BSTNode(int key, std::weak_ptr<BSTNode> parent) :
key_(key),
parent_(parent),
left_(nullptr),
right_(nullptr) {}
bool BSTNode::IsLeaf() const {
return left_ == nullptr && right_ == nullptr;
}
bool BSTNode::HasLeftChild() const {
return left_ != nullptr;
}
bool BSTNode::HasRightChild() const {
return right_ != nullptr;
}
void BSTNode::DeleteChild(std::shared_ptr<BSTNode> v) {
if (left_ == v) {
left_ = nullptr;
} else if (right_ == v) {
right_ = nullptr;
} else {
std::cerr << "BSTNode::DeleteChild Error: non-child passed as argument\n";
exit(EXIT_FAILURE);
}
}
void BSTNode::ReplaceChild(std::shared_ptr<BSTNode> v, std::shared_ptr<BSTNode> u) {
if (left_ == u || right_ == u) {
std::cerr << "BSTNode::ReplaceChild Error: child passed as replacement\n";
}
if (left_ == v) {
left_ = u;
u->parent_ = v->parent_;
} else if (right_ == v) {
right_ = u;
u->parent_ = v->parent_;
} else {
std::cerr << "BSTNode::ReplaceChild Error: non-child passed as argument\n";
exit(EXIT_FAILURE);
}
}
int BSTNode::height() {
if (this == nullptr){
return -1;
}
return this->height_;
}
int BSTNode::balanceFactor() {
if (this == nullptr){
return 0;
}
return this->right_->height() - this->left_->height();
}
BST::BST() : root_(nullptr), size_(0) {}
std::shared_ptr<BSTNode> BST::Insert(int key) {
if (root_ == nullptr) {
root_ = std::make_shared<BSTNode>(key);
size_++;
return root_;
}
std::shared_ptr<BSTNode> currentNode = root_, lastNode = nullptr;
while (currentNode != nullptr) {
lastNode = currentNode;
if (key < currentNode->key_) {
currentNode = currentNode->left_;
} else {
currentNode = currentNode->right_;
}
}
if (key < lastNode->key_) {
lastNode->left_ = std::make_shared<BSTNode>(key, lastNode);
} else {
lastNode->right_ = std::make_shared<BSTNode>(key, lastNode);
}
size_++;
return lastNode;
}
bool BST::Delete(int key) {
std::shared_ptr<BSTNode> currentNode = root_;
while (currentNode != nullptr) {
if (currentNode->key_ == key) {
if (currentNode->IsLeaf()) {
DeleteLeaf(currentNode);
} else if (currentNode->left_ == nullptr) {
assert(currentNode->right_ != nullptr);
std::shared_ptr<BSTNode> parent = currentNode->parent_.lock();
parent->ReplaceChild(currentNode, currentNode->right_);
size_--; assert(size_ >= 0);
} else if (currentNode->right_ == nullptr) {
assert(currentNode->left_ != nullptr);
std::shared_ptr<BSTNode> parent = currentNode->parent_.lock();
parent->ReplaceChild(currentNode, currentNode->left_);
size_--; assert(size_ >= 0);
} else {
currentNode->key_ = DeleteMin(currentNode);
}
}
currentNode = (key < currentNode->key_) ?
currentNode->left_ : currentNode->right_;
}
return false;
}
int BST::DeleteMin() {
return DeleteMin(root_);
}
void BST::DeleteLeaf(std::shared_ptr<BSTNode> currentNode) {
std::shared_ptr<BSTNode> parent = currentNode->parent_.lock();
if (parent == nullptr) {
// Delete root
root_ = nullptr;
size_--; assert(size_ == 0);
} else {
if (parent->right_ == currentNode) {
parent->right_ = nullptr;
} else if (parent->left_ == currentNode) {
parent->left_ = nullptr;
} else {
std::cerr << "BST::DeleteLeaf Error: inconsistent state\n";
}
size_--; assert(size_ >= 0);
}
}
int BST::DeleteMin(std::shared_ptr<BSTNode> currentNode) {
std::shared_ptr<BSTNode> lastNode = nullptr;
while (currentNode != nullptr) {
lastNode = currentNode;
currentNode = currentNode->left_;
}
int result = lastNode->key_;
std::shared_ptr<BSTNode> parent = lastNode->parent_.lock();
if (parent == nullptr) {
// lastNode is root
if (lastNode->right_ != nullptr) {
root_ = lastNode->right_;
lastNode->right_->parent_.reset();
} else {
root_ = nullptr;
}
} else {
// lastNode under the root
if (lastNode->right_ != nullptr) {
parent->left_ = lastNode->right_;
lastNode->right_->parent_ = parent;
} else {
parent->left_ = nullptr;
}
}
size_--; assert(size_ >= 0);
return result;
}
size_t BST::size() const {
return size_;
}
bool BST::empty() const {
return size_ == 0;
}
bool BST::Find(int key) const {
std::shared_ptr<BSTNode> currentNode = root_;
while (currentNode != nullptr) {
if (currentNode->key_ == key) {
return true;
}
currentNode = (key < currentNode->key_) ?
currentNode->left_ : currentNode->right_;
}
return false;
}
std::string BST::JSON() const {
nlohmann::json result;
std::queue< std::shared_ptr<BSTNode> > nodes;
if (root_ != nullptr) {
result["root"] = root_->key_;
nodes.push(root_);
while (!nodes.empty()) {
auto v = nodes.front();
nodes.pop();
std::string key = std::to_string(v->key_);
if (v->left_ != nullptr) {
result[key]["left"] = v->left_->key_;
nodes.push(v->left_);
}
if (v->right_ != nullptr) {
result[key]["right"] = v->right_->key_;
nodes.push(v->right_);
}
if (v->parent_.lock() != nullptr) {
result[key]["parent"] = v->parent_.lock()->key_;
} else {
result[key]["root"] = true;
}
result[key]["height"] = v->height();
result[key]["balance factor"] = v->balanceFactor();
}
}
result["height"] = root_->height();
result["size"] = size_;
return result.dump(2) + "\n";
}
这是 AVLCommands.cxx
#include <string>
#include "json.hpp"
#include <iostream>
#include <fstream>
#include "BST.h"
#include "AVL.h"
int main(int argc, char** argv) {
std::ifstream file1;
file1.open(argv[1]);
nlohmann::json jsonObject;
if (file1.is_open()) {
file1 >> jsonObject;
} else {
std::cout << "Invalid Arguments";
}
AVLTree avl_tree;
int numOps = jsonObject["metadata"]["numOps"];
if(numOps == 10){
for(int i = 0; i < numOps; i++ ){
std::string num;
if(i < 9){
num = "0" + std::to_string(i+1);
}
else{
num = std::to_string(i+1);
}
avl_tree.AVLInsert(jsonObject[num]["key"]);
}
}
if(numOps == 1000){
for(int i = 1; i <= numOps; i++ ){
std::string num;
if(i < 10 && i > 0){
num = "000" + std::to_string(i);
avl_tree.AVLInsert(jsonObject[num]["key"]);
}
if(i < 100 && i >= 10){
num = "00" + std::to_string(i);
avl_tree.AVLInsert(jsonObject[num]["key"]);
}
if(i < 1000 && i >= 100){
num = "0" + std::to_string(i);
avl_tree.AVLInsert(jsonObject[num]["key"]);
}
if(i == 1000){
num = std::to_string(i);
avl_tree.AVLInsert(jsonObject[num]["key"]);
}
}
}
std::cout << avl_tree.JSON() << "\n";
}
解决方案
推荐阅读
- python - 将 tensorflow 模型转换为 tensorflow lite = ValueError: bad marshal data (unknown type code) 时出错
- php - php函数“exec”不适用于window的systeminfo命令
- mysql - 插入数据库并选择值
- html - CSS位置相对在div元素的高度变化时在页脚下方创建空白
- powershell - 无法通过 SMTP 发送消息
- php - PHP FILTER_VALIDATE_URL 验证失败
- java - 如果字符串具有相同的前缀和后缀,则删除字符串的最后 3 个字符
- mongodb - MongoDB 将 _id 字段替换为现有字段 ID
- django - Django:覆盖预定义的 save() 方法 - 未定义请求
- javascript - Wordpress 主题:响应式菜单栏在 Web 服务器上安装主题时停止