What I would need is pushing the binary tree in a vector and write out the vector`s contents in the terminal to prove that is works.
I cant seem to make it work , I tried in a few different ways like making funcions that will do that for me. Im a Computer Science student so Im kinda beginnerish , I tried my hardest but I just dont know how to do it.
You gave me a lot of good advice through your posts and answers but, I didn`t find anything in this regard so Im asking for your help.
Here is my binary tree :
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <math.h>
using namespace std;
class Binfa {
public:
int value;
Binfa *left;
Binfa *right;
int depth() {
int leftd = 0, rightd = 0;
if (left == NULL && right == NULL)
return 1;
if (left != NULL)
leftd = left->depth();
if (right != NULL)
rightd = right->depth();
return (max(leftd, rightd) + 1);
}
static double averagedepth(Binfa *node) {
static int db = 0, sum = 0, depth = 0;
if (node != NULL) {
++depth;
Binfa::averagedepth(node->right);
Binfa::averagedepth(node->left);
--depth;
if (node->left == NULL && node->right == NULL) {
++db;
sum += depth;
}
} else {
return 0.0;
}
return (double) sum / db;
}
static double spread(Binfa *node, double average) {
static int db = 0, depth = 0;
static double sum = 0.0;
if (node != NULL) {
++depth;
spread(node->right, average);
spread(node->left, average);
--depth;
if (node->right == NULL && node->left == NULL) {
++db;
sum += ((depth - average) * (depth - average));
}
}
if (db > 1)
return sqrt(sum / (db - 1));
return sqrt(sum);
}
static void print(Binfa *node) {
static int idepth = 0;
if (node != NULL) {
++idepth;
print(node->right);
for (int i = 0; i < idepth; ++i)
printf("---");
printf("%c(%d)\n",
node->value < 2 ? '0' + node->value : node->value,
idepth - 1);
print(node->left);
--idepth;
}
}
};
int main(int argc, char **argv) {
char b;
int in = 0;
int i, egy_e;
Binfa *root = new Binfa();
root->value = '/';
root->left = root->right = NULL;
Binfa *current = root;
if (argv[1] != NULL) {
in = open(argv[1], O_RDONLY);
}
while (read(in, (void *) &b, 1)) {
for (i = 0; i < 8; ++i) {
egy_e = b & 0x80;
if ((egy_e >> 7) == 1) {
if (current->right == NULL) {
current->right = new Binfa();
current->right->value = 1;
current->right->left = current->right->right = NULL;
current = root;
} else {
current = current->right;
}
} else {
if (current->left == NULL) {
current->left = new Binfa();
current->left->value = 0;
current->left->left = current->left->right = NULL;
current = root;
} else {
current = current->left;
}
}
b <<= 1;
}
}
printf("\n");
Binfa::print(root);
printf("melyseg=%d\n", root->depth() - 1);
printf("altag=%f\n", Binfa::averagedepth(root));
printf("szoras=%f\n", Binfa::spread(root, Binfa::averagedepth(root)));
return 0;
}
Related
#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);
}
So I'm supposed to implement an AVL tree with an input of a JSON file. So for that reason, I' created an AVLTree class. The problem with this class is that when I use a dataset of, say, 1000, it doesn't work, but it works for a dataset of 10. My AVL rotations don't seem to work either and so the tree is never balanced around the root but otherwise, it works perfectly.
The BST::Insert(key) returns the last node aka the node that was just inserted.
I use smart pointers to point to each value and to move them around in the BST. My BST class uses smart pointers so I would love it if someone could help me out using smart pointers.
Yes, this is an assignment but it's just a small bug I haven't been able to figure out.
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";
}
And this is the 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";
}
I looked through other questions asked similarly and can not seem to find a relatable cause here is what I think is the relevant code:(EDIT: including all code at request)
main.cpp
#include <iostream>
#include "Pitri.h"
int main()
{
std::cout << "Hello World!\n";
}
Pitri.cpp
#include "Pitri.h"
#include "node.h"
#include "dood.h"
//#include <cstdlib>
#include <iostream>
Pitri::Pitri()
{
this->length = 0;
this->head = NULL;
}
Pitri::~Pitri()
{
}
void Pitri::add(dood data)
{
node* nnode = new node();
nnode->data = data;
nnode->next = this->head;
this->head = nnode;
this->length++;
}
void Pitri::remove(node * t, node* p)
{
if (this->head == t)
{
if (t->next == NULL)
this->head = NULL;
else
this->head = t->next;
t->data.Death();
free(t);
}
else
{
if (t->next == NULL)
p->next = NULL;
else
p->next = t->next;
t->data.Death();
free(t);
}
}
void Pitri::printP()
{
int tallyBr = 0;
node* head = this->head;
int i = 1;
while (head)
{
}
}
void Pitri::printS()
{
}
void Pitri::printBL()
{
}
void Pitri::populate(int x)
{
for (int i = 0; i < x; i++)
{
dood* baby = new dood;
this->add(baby);
}
}
void Pitri::cycle(int x)
{
//Initial definition in the event that the head node reproduces
node* curr = this->head;
node* mate = this->head->next;
for (int i = 0; i < x; i++)
{
int deaths = 0;
int births = 0;
if (head == NULL)
{
cout << "Pitri has gone extinct!" << endl;
break;
}
while (curr)
{
if (rand() % 100 + 1 <= this->mort && this->mort)
{
deaths++;
remove(curr);
}
else if (curr->data.GetAge() == this->ttl && this->ttl)
{
deaths++;
remove(curr);
}
else if (rand() % 100 + 1 <= this->birth && this->birth)
{
births++;
add(curr->data.Reproduce(mate->data));
}
if (curr->next == NULL)
break;
mate = curr;
curr = curr->next;
}
}
}
Pitri.h
#pragma once
class Pitri
{
public:
Pitri();
~Pitri();
int length;
node *head;
void add(dood data);
void remove(node* t);
void printP();
void printS();
void printBL();
void populate(int);
void cycle(int);
int getBB();
int getBL();
int getLL();
private:
int ttl,mort,birth;
};
dood.cpp
#include "dood.h"
//#include <stdio.h>
//#include <stdlib.h>
#include <time.h>
bool dood::init = false;
dood::dood()
{
if (!init)
{
//Set time for random seed
srand(time(0));
init = true;
}
Primary = rand()%2;
//Set Blue eyes to always have Blue recessive.
if (Primary == 0)
Secondary = rand()%2;
else
Secondary = 1;
}
dood::dood(int a, int b)
{
if (!init)
{
//Set time for random seed
srand(time(0));
init = true;
}
Primary = a;
Secondary = b;
}
dood::~dood()
{
}
void dood::Mutate()
{
this->Primary = rand()%2;
//Set Blue eyes to always have Blue recessive.
if (Primary == 0)
Secondary = rand()%2;
else
Secondary = 1;
}
dood dood::Reproduce(dood donor)
{
int dPri = donor.GetPrimary();
int dSec = donor.GetSecondary();
int bPri, bSec;
int punitvalue = rand() % 4 + 1;
//if at least one dood has Brown/Brown...
if((Primary == 0 && Secondary == 0) || (dPri == 0 && dSec == 0))
{
bPri = 0;
// if other is Br/Br
if (Secondary == dSec)
bSec = 0;
//if other is Br/Bl
else if (Primary == dPri)
bSec = punitvalue % 2;
//if other is Bl/Bl
else
bSec = 1;
}
else if ((Primary == 1 && Secondary == 1) || (dPri == 1 && dSec == 1))
{
bSec = 1;
if (dPri == Primary)
bPri = 1;
else
bPri = punitvalue % 2;
}
else
{
if (punitvalue == 4)
{
bPri = 1;
bSec = 1;
}
else
{
bPri = 0;
if (punitvalue % 3 == 0)
bSec = 0;
else
bSec = 1;
}
}
dood baby = new dood(bPri, bSec);
return baby;
}
void dood::Death()
{
}
void dood::Age()
{
age = age + 1;
}
int dood::GetPrimary()
{
return this->Primary;
}
int dood::GetSecondary()
{
return this->Secondary;
}
int dood::GetAge()
{
return age;
}
dood.h
#pragma once
class dood
{
public:
dood();
dood(int, int);
~dood();
void Mutate();
dood Reproduce(dood);
void Death();
void Age();
int GetPrimary();
int GetSecondary();
int GetAge();
private:
// Genetec Traits "0" for brown, "1" for Blue
int Primary;
int Secondary;
int age=0;
//Has rand() been seeded?
static bool init;
};
node.cpp
#include "node.h"
node::node()
{
}
node::~node()
{
}
node.h
#pragma once
class node
{
public:
node();
~node();
node* next;
dood data;
};
I am not using namespace.std anywhere which is the most common issue I see people refer to, and AFAIK node is not predefined anywhere else? can I get some direction?
Thank you WhozCraig, Simple fix of doing my Pitri Class required includes:
#include "node.h"
#include "dood.h"
in the header file and not the CPP file.
So I'm making a binary max heap for my c++ class and I keep encountering this exception saying that I'm returning a nullptr in my class methods. I'm having trouble finding where it could be at in my code so any help would be greatly appreciated. The exception that keeps getting thrown is as follows:
Unhandled exception thrown: read access violation.
**std::_String_alloc<std::_String_base_types<char,std::allocator<char> > ::_Get_data**(...) returned nullptr. occurred
Here's my header file for the tree:
#ifndef HEAP_H
#define HEAP_H
#include <iostream>
#include "THeapNode.h"
class TreeHeap {
private:
THeapNode *root; // the top node of the heap
int next_loc; // the next valid location to place a node
void bubble_up(THeapNode *node); //performs the bubble up operation on the given node
void bubble_down(THeapNode *node); //performs the bubble down operation on the given node
void clear_heap(THeapNode *node); // removes all elements from the heap
public:
TreeHeap(); // the constructor
~TreeHeap(); // the destructor
THeapNode* find_node(const int position); // finds the node in the position given and returns a pointer to it
void insert(const string &item); // creates a node with the string given as the value and places it in the next location
bool Delete(); // removes the root of the heap and returns false if the tree is empty
};
#endif
Here's my Node's .h file:
#ifndef NODE_H
#define NODE_H
#include<string>
using std::string;
struct THeapNode {
string data; // stores a data string
THeapNode *parent; // a pointer to the parent node
THeapNode *rightChild; // a pointer to the right child node
THeapNode *leftChild; // a pointer to the left child node
THeapNode( const string &str );
};
#endif
And here's my .cpp file:
#include "stdafx.h"
#include <cmath>
#include "TreeHeap.h"
#include "THeapNode.h"
TreeHeap::TreeHeap() {
root = NULL;
next_loc = 1;
};
TreeHeap::~TreeHeap() {
THeapNode *current = root;
THeapNode *deleteNode = NULL;
int d = floor(log2(next_loc - 1));
int j = next_loc;
for ( int i = 1; i <= j-1; i++ ) {
while (1) {
int d = floor(log2(next_loc - i));
int power = std::pow(2, d - 1);
if (next_loc == 1) {
deleteNode = current;
j -= 1;
}
else if (next_loc < (std::pow(2, d - 1) * 3)) {
current = current->leftChild;
}
else {
current = current->rightChild;
}
// Update location and depth to reflect traversal
next_loc = std::pow(2, d - 1) + next_loc % power;
d = d - 1;
}
clear_heap(deleteNode);
}
}
void TreeHeap::clear_heap(THeapNode *node) {
if (node == NULL) {
return;
}
node->data = "";
node->leftChild = NULL;
node->rightChild = NULL;
node->parent = NULL;
}
void TreeHeap::insert( const string &value ) {
THeapNode newNode = THeapNode(value);
int loc = next_loc;
if (loc == 1) {
*root = newNode;
}
THeapNode *current = root;
while (1) {
int d = floor(log2(loc));
int power = std::pow(2, d - 1);
if (loc < (power * 3)) {
if (current->leftChild = nullptr) {
*current->leftChild = newNode;
newNode.parent = current;
next_loc += 1;
break;
}
else {
current = current->leftChild;
}
}
else {
if (current->rightChild = nullptr) {
*current->rightChild = newNode;
newNode.parent = current;
next_loc = +1;
break;
}
else {
current = current->rightChild;
}
}
// Update location and depth to reflect traversal
loc = std::pow(2, d - 1) + loc % power;
d = d - 1;
}
std::cout << current->data << "\n";
system("PAUSE");
}
void TreeHeap::bubble_up( THeapNode *node ) {
if (node == NULL) {
return;
}
THeapNode *parent = node->parent;
while ( parent->data < node->data ) {
parent = node->parent;
string temp = parent->data;
parent->data = node->data;
node->data = temp;
}
}
void TreeHeap::bubble_down( THeapNode *node ) {
if (node == NULL) {
return;
}
while( node->data < node->rightChild->data || node->data < node->leftChild->data ){
if (node->rightChild->data > node->leftChild->data) {
THeapNode *right = node->rightChild;
string temp = right->data;
right->data = node->data;
node->data = temp;
}
else if (node->rightChild->data < node->leftChild->data) {
THeapNode *left = node->leftChild;
string temp = left->data;
left->data = node->data;
node->data = temp;
}
}
}
THeapNode* TreeHeap::find_node( const int position ){
int loc = position;
int d = floor(log2(position));
int power = std::pow(2, d - 1);
THeapNode *returnValue = root;
while (returnValue != NULL && 1 < position && position < (next_loc - 1)) {
if (loc == 1) {
return returnValue;
}
else if (loc < ( std::pow( 2, d-1 ) * 3)) {
returnValue = returnValue->leftChild;
}
else {
returnValue = returnValue->rightChild;
}
// Update location and depth to reflect traversal
loc = std::pow(2, d - 1) + loc % power;
d = d - 1;
}
std::cout << returnValue->data<<"\n";
return returnValue;
}
bool TreeHeap::Delete() {
if (next_loc = 1) {
return false;
}
int d = floor(log2(next_loc - 1));
THeapNode *current = root;
THeapNode *usedNode = NULL;
int loc = next_loc - 1;
while ( 1 ) {
int d = floor(log2(loc));
int power = std::pow(2, d - 1);
if (loc == 1) {
usedNode = current;
break;
}
else if (loc < (std::pow(2, d - 1) * 3)) {
current = current->leftChild;
}
else {
current = current->rightChild;
}
// Update location and depth to reflect traversal
loc = std::pow(2, d - 1) + loc % power;
d = d - 1;
}
THeapNode *temp = root;
clear_heap(root);
root = usedNode;
delete temp;
bubble_down(root);
return true;
}
Thanks in advance for any help you've got.
Quick inspection reveals errors in your bubble_up and bubble_down functions.
In bubble_up, you have the following:
THeapNode *parent = node->parent;
while ( parent->data < node->data ) {
parent = node->parent;
string temp = parent->data;
parent->data = node->data;
node->data = temp;
}
This is going to fail when a node bubbles all the way to the top, because it doesn't check for the node being at the root. You need to write:
while (parent != NULL && parent->data < node->data)
In bubble_down, you have this code:
while( node->data < node->rightChild->data || node->data < node->leftChild->data ){
if (node->rightChild->data > node->leftChild->data) {
You don't check to see if the rightChild or leftChild are NULL.
More importantly, that looks like an infinite loop to me because you never change the value of node.
Those are just the errors I saw on a quick read through your code. There might be more.
I am working on an exercise in processing an AVL tree. The debugger shows no errors. I ran the program and it is supposed to output an output text file. However the program crashes every time.
#include <stdio.h>
#include <assert.h>
#include <algorithm>
#include <vector>
using namespace std;
struct node
{
int key;
int height;
node *left, *right;
node(int k)
{
key = k;
height = 1;
left = right = 0;
}
};
void pre_order(node* root)
{
if(root == 0) return;
printf("%d", root->key);
printf(" ");
pre_order(root->left);
pre_order(root->right);
}
void in_order(node* root)
{
in_order(root->left);
printf("%d", root->key);
printf(" ");
in_order(root->right);
}
int height(node* r)
{
return r ? r->height : 0;
}
void update_height(node* root)
{
if(root == 0) return;
int hl = height(root->left), hr = height(root->right);
root->height = std::max(hl, hr) + 1;
}
node* right_rotate(node* ref_root)
{
assert(ref_root && ref_root->left);
node *a = ref_root, *b = ref_root->left;
a->left = b->right;
b->right = a;
update_height(a);
update_height(b);
return b;
}
node* left_rotate(node* ref_root)
{
assert(ref_root && ref_root->right);
node *c = ref_root, *d = ref_root->right;
c->right = d->left;
d->left = c;
update_height(c);
update_height(d);
return d;
}
node* maintain(node* ref_root)
{
if(ref_root == 0) return ref_root;
update_height(ref_root);
node* ret = ref_root;
if(height(ref_root->left) > height(ref_root->right) + 1)
{
node* p = ref_root->left;
if( height(p->left) < height(p->right) )
ref_root->left = left_rotate(p);
ret = right_rotate(ref_root);
}
else if(height(ref_root->right) > height(ref_root->left) + 1)
{
node* p = ref_root->right;
if(height(p->right) < height(p->left)){
ref_root->right = right_rotate(p);
}
ret = left_rotate(ref_root);
}
return ret;
}
node* insert_key(int key, node* ref_root)
{
if(ref_root == 0)
{
return ref_root = new node(key);
}
if(key < ref_root->key){
node* child = insert_key(key, ref_root->left);
ref_root->left = child;
}
else if(key > ref_root->key){
node* child = insert_key(key, ref_root->right);
ref_root->right = child;
}
else
assert(0);
return maintain(ref_root);
}
vector<node*> minimum(node* T) {
vector<node*> x;
node* y = T;
while (y->left != NULL) {
x.push_back(y->left);
}
return x;
}
node* delete_key(int key, node* ref_root)
{
if(key < ref_root->key){
node* child = delete_key(key, ref_root->left);
ref_root->left = child;
}
else if(key > ref_root->key){
node* child = delete_key(key, ref_root->right);
ref_root->right = child;
}
else
{
if(ref_root->left && ref_root->right)
{
vector <node*> y = minimum(ref_root->right);
node* successor = y.back();
node* sParent = y[y.size()-2];
ref_root->key = successor->key;
sParent->left = successor->right;
}
else
{
if(ref_root->left != NULL){
ref_root = ref_root->left;
}
else if(ref_root->right != NULL){
ref_root = ref_root->right;
}
}
}
return maintain(ref_root);
}
int main()
{
node *root = 0;
char op[10] = "";
int k;
while(true)
{
scanf("%s", op);
if(op[0] == 'E') break;
switch(op[0])
{
case 'A': scanf("%d", &k); root = insert_key(k, root); break; //Insert
case 'D': scanf("%d", &k); root = delete_key(k, root); break;//Delete
case 'P': pre_order(root); printf("\n"); break;//preorder
case 'I': in_order(root); printf("\n"); break;//inorder
default: assert(0);
}
}
return 0;
}
There is no check in the in_order function that root is not NULL.
So, I want to take input from a text file, then do some operations in an AVL tree. I could implement insertion, yet I can't build a solution for deletion in my mind. Can you help me? Here is the code.
#include<iostream>
#include<cstdio>
#include<sstream>
#include<algorithm>
#include <fstream>
#include <stdlib.h>
#include <array>
#include <ctime>
using namespace std;
struct node
{
int data;
int height;
struct node *leftchild;
struct node *rightchild;
}*root;
class avlTree
{
public:
int height(node *);
int difference(node *);
node *rrtraversal(node *);
node *lltraversal(node *);
node *lrtraversal(node *);
node *rltraversal(node *);
node* balance(node *);
node* insert(node *, int );
void display(node *, int);
node *del(node *, int);
avlTree()
{
root = NULL;
}
};
int avlTree::height(node *temp)
{
int h = 0;
if (temp != NULL)
{
int l_height = height (temp->leftchild);
int r_height = height (temp->rightchild);
int max_height = max (l_height, r_height);
h = max_height + 1;
}
return h;
}
int avlTree::difference(node *temp)
{
int l_height = height (temp->leftchild);
int r_height = height (temp->rightchild);
int b_factor= l_height - r_height;
return b_factor;
}
node *avlTree::rrtraversal(node *parent)
{
node *temp;
temp = parent->rightchild;
parent->rightchild = temp->leftchild;
temp->leftchild = parent;
return temp;
}
node *avlTree::lltraversal(node *parent)
{
node *temp;
temp = parent->leftchild;
parent->leftchild = temp->rightchild;
temp->rightchild = parent;
return temp;
}
node *avlTree::lrtraversal(node *parent)
{
node *temp;
temp = parent->leftchild;
parent->leftchild = rrtraversal (temp);
return lltraversal (parent);
}
node *avlTree::rltraversal(node *parent)
{
node *temp;
temp = parent->rightchild;
parent->rightchild = lltraversal (temp);
return rrtraversal (parent);
}
node *avlTree::balance(node *temp)
{
int bal_factor = difference (temp);
if (bal_factor > 1)
{
if (difference (temp->leftchild) > 0)
temp = lltraversal (temp);
else
temp = lrtraversal (temp);
}
else if (bal_factor < -1)
{
if (difference (temp->rightchild) > 0)
temp = rltraversal (temp);
else
temp = rrtraversal (temp);
}
return temp;
}
node *avlTree::insert(node *root, int value)
{
if (root == NULL)
{
root = new node;
root->data = value;
root->leftchild = NULL;
root->rightchild = NULL;
return root;
}
else if (value < root->data)
{
root->leftchild = insert(root->leftchild, value);
root = balance (root);
}
else if (value >= root->data)
{
root->rightchild = insert(root->rightchild, value);
root = balance (root);
}
return root;
}
void avlTree::display(node *ptr, int level)
{
int i;
if (ptr!=NULL)
{
display(ptr->rightchild, level + 1);
printf("\n");
for (i = 0; i < level && ptr != root; i++)
cout<<" ";
cout<<ptr->data;
display(ptr->leftchild, level + 1);
}
}
node *avlTree::del(node *root, int x)
{
node *d;
if ( x < root->data){
del(root->leftchild,x);
}
else if (x > root->data){
del(root->rightchild,x);
}
else if ((root->leftchild == NULL) && (root->rightchild == NULL))
{
d=root;
free(d);
root=NULL;
}
else if (root->leftchild == NULL)
{
d=root;
free(d);
root= root->rightchild;
}
else if (root->rightchild == NULL)
{
d=root;
root=root->leftchild;
free(d);
}
return root;
}
int main()
{
ifstream myFile("file.txt");
int a = 0;
std::array<string,512> arrayTest;
int index = 0;
string content;
avlTree avl;
while (myFile >> content){
arrayTest[index] = content;
index++;
}
clock_t startTime = clock();
for(a = 0; a < arrayTest.size();a++){
if(arrayTest[a] == "i"){
root = avl.insert(root, std::stoi(arrayTest[a+1]));
}
}
avl.display(root,1);
clock_t endTime = clock();
clock_t clockTicksTaken = endTime - startTime;
double timeInSeconds = clockTicksTaken / (double) CLOCKS_PER_SEC;
cout << "\n\n" << timeInSeconds << " secs\n";
}
In file, the content is like this. i 1 i 2 i 3 i 4 i 5 d 3
If program sees i, it will do an insert operation. Likewise, if it sees d, it will do a delete operation.
Did you try free() function?
free(node);