I'm having some trouble with the creation of an AVL tree structure in C++ for a university project. So far, I managed to make simple add and delete functions, but here comes the problem! I 've seen some codes here where the checks are made in the add function directly, but I didn't want to copy the code. Is there a way to create a seperate function which does exactly this work? The thing I can't make work is how to make the program understand in which rotation case I have to go.
My code so far is this:
struct node
{
unsigned int target;
struct node *left;
struct node *right;
};
int ClassInvertedIndex::Height(struct node *toCheck)
{
int left, right;
if(toCheck == NULL)
return 0;
left = Height(toCheck->left);
right = Height(toCheck->right);
if(left > right)
return left+1;
else
return right+1;
}
void ClassInvertedIndex::maintainAVL(struct node *toCheck)
{
if(Height(toCheck->left)-Height(toCheck->right) == 2); //Left subtree problem.
if(Height(toCheck->right)-Height(toCheck->left) == 2); //Right subtree problem.
}
bool ClassInvertedIndex::addNode(unsigned int x)
{
return insideAdd(data, x);
}
bool ClassInvertedIndex::insideAdd(struct node *toAdd, unsigned int x)
{
if(toAdd == NULL)
{
toAdd = new struct node;
if(toAdd == NULL)
{
cout << "Could not allocate memory.";
return false;
}
toAdd->left = NULL;
toAdd->right = NULL;
toAdd->target = x;
return true;
}
else if(x < toAdd->target)
{
bool result;
result = insideAdd(toAdd->left, x);
if(result)
{
//maintainAVL(toAdd);
}
return result;
}
else if(x > toAdd->target)
{
bool result;
result = insideAdd(toAdd->right, x);
if(result)
{
//maintainAVL(toAdd);
}
return result;
}
else //x already exists.
{
return false;
}
}
So, in the maintainAVL method, what should I do to decide what rotation I need?
Related
I am looking at the Geeks for Geeks problem Burning Tree:
Given a binary tree and a node called target. Find the minimum time required to burn the complete binary tree if the target is set on fire. It is known that in 1 second all nodes connected to a given node get burned. That is its left child, right child, and parent.
I am getting the following error:
Abort signal from abort(3) (SIGABRT)
This is my code:
class Solution {
// mapping to parent
// returns the target node
Node* createParentMapping(Node* root, int target,
map<Node*, Node*> &nodeToParent) {
Node* res = NULL;
queue<Node*> que;
que.push(root);
nodeToParent[root] = NULL;
while (!que.empty()) {
Node* front = que.front();
if (front->data == target) {
res = front;
}
if (front->left) {
nodeToParent[front->left] = front;
que.push(front->left);
}
if (front->right) {
nodeToParent[front->right] = front;
que.push(front->right);
}
}
return res;
}
// burns the tree
int burnTree(Node* root, map<Node*, Node*> &nodeToParent) {
map<Node*, bool> visited;
queue<Node*> q;
q.push(root);
visited[root] = true;
int ans = 0;
while (!q.empty()) {
bool flag = 0;
int size = q.size();
for(int i = 0; i < size; i++) {
Node* front = q.front();
q.pop();
if (front->left && !visited[front->left]) {
flag = 1;
q.push(front->left);
visited[front->left] = 1;
}
if (front->right && !visited[front->right]) {
flag = 1;
q.push(front->right);
visited[front->right] = 1;
}
if (nodeToParent[front] && !visited[nodeToParent[front]]) {
flag = 1;
q.push(nodeToParent[front]);
visited[nodeToParent[front]] = 1;
}
}
if (flag == 1) {
ans++;
}
}
return ans;
}
public:
int minTime(Node* root, int target) {
map<Node*, Node*> NodeToParent;
Node* targetNode = createParentMapping(root, target, NodeToParent);
int time = burnTree(targetNode, NodeToParent);
return time;
}
};
I am not able to find out the where the problem lies. What am I missing?
The problem is that you have an infinite loop in createParentMapping. A call to que.pop() is missing. Just like you did in burnTree, you should put it right after the line with que.front().
This will solve your problem.
But I should mention this problem can be solved without an extra data structure. Think of how path lengths relate to heights of (sub)trees.
Here is a spoiler solution that performs one recursive traversal of the tree:
class Solution {
int answer;
// Returns:
// when negative: (negated) level at which target was found (= -(depth + 1))
// otherwise: number of levels in the tree (= height + 1)
// Side effect:
// adjusts answer
int scanTree(Node* root, int target) {
if (root == nullptr) return 0; // #levels
int left = scanTree(root->left, target);
int right = scanTree(root->right, target);
if (root->data == target) {
// found target.
answer = max(left, right); // #levels => height
return -1; // negative depth at which target was found
}
if (left < 0) { // Found the target in left subtree
answer = max(answer, right - left);
return left - 1; // Increased negative depth
} else if (right < 0 ) { // Found the target in right subtree
answer = max(answer, left - right);
return right - 1; // Increased negative depth
} else { // No success: return number of levels
return 1 + max(left, right);
}
}
public:
int minTime(Node* root, int target) {
answer = -1;
scanTree(root, target);
return answer;
}
};
Hey I have this template of BinarySearchTreeNode in which i have to implement the following methods
Constructors
Destructor
Empty
leaf
Height
insert
i am done with the constructors and the insert part but i am facing issues with the destructor and the height functions please help me implement these methods
Special care is required for the implementation of method height(). The empty tree has no
height, hence height() must throw a domain_error exception in this case. For interior
nodes, however, if a subtree of a given BinaryTreeNode is empty, then this subtree
contributes a height of zero to the interior node. In other words, the smallest height of any
non-empty BinaryTreeNode is zero. Remember, interior nodes add one to the maximum
height of their subtrees.
Help me with these methods i am super new to DSA and c++ any help is greatly appreciated
#pragma once
#include <stdexcept>
#include <algorithm>
template <typename T>
struct BinaryTreeNode
{
using BNode = BinaryTreeNode<T>;
using BTreeNode = BNode *;
T key;
BTreeNode left;
BTreeNode right;
static BinaryTreeNode<T> NIL;
const T &findMax() const
{
if (empty())
{
throw std::domain_error("Empty tree encountered.");
}
return right->empty() ? key : right->findMax();
}
const T &findMin() const
{
if (empty())
{
throw std::domain_error("Empty tree encountered.");
}
return left->empty() ? key : left->findMin();
}
bool remove(const T &aKey, BTreeNode aParent)
{
BTreeNode x = this;
BTreeNode y = aParent;
while (!x->empty())
{
if (aKey == x->key)
{
break;
}
y = x; // new parent
x = aKey < x->key ? x->left : x->right;
}
if (x->empty())
{
return false; // delete failed
}
if (!x->left->empty())
{
const T &lKey = x->left->findMax(); // find max to left
x->key = lKey;
x->left->remove(lKey, x);
}
else
{
if (!x->right->empty())
{
const T &lKey = x->right->findMin(); // find min to right
x->key = lKey;
x->right->remove(lKey, x);
}
else
{
if (y != &NIL) // y can be NIL
{
if (y->left == x)
{
y->left = &NIL;
}
else
{
y->right = &NIL;
}
}
delete x; // free deleted node
}
}
return true;
}
// Implement theses
BinaryTreeNode() : key(T()), left(&NIL), right(&NIL)
{
}
BinaryTreeNode(const T &aKey) : key(aKey), left(&NIL), right(&NIL)
{
}
BinaryTreeNode(T &&aKey) : key(std::move(aKey)), left(&NIL), right(&NIL)
{
}
~BinaryTreeNode()
{
}
bool empty() const
{
return this == &NIL;
}
bool leaf() const
{
return left == &NIL && right == &NIL;
}
size_t height() const
{
}
bool insert(const T &aKey)
{
if (aKey == key || empty())
return false;
if (aKey < key)
{
if (!left->empty())
return left->insert(aKey);
left = new BinaryTreeNode(aKey);
}
else
{
if (!right->empty())
return right->insert(aKey);
right = new BinaryTreeNode(aKey);
}
return true;
}
};
template <typename T>
BinaryTreeNode<T> BinaryTreeNode<T>::NIL;
For binary search tree to see if the tree has duplicated value or not. I took this post order approach.
My goal was to keep the value of the current node and then use other function traverse the tree to see if there is any matching value to that current value, and if it finds any duplicate value it brings "true value". I choose to use recursion as it seems easier to track. but when I ran the program there was no output coming out.
#include "pch.h"
#include <iostream>
using namespace std;
class BSTNode {
public:
int data;
BSTNode* left;
BSTNode* right;
BSTNode() {};
};
BSTNode* newnode(int newdata) { BSTNode *curr = new BSTNode; curr->data = newdata; curr->left = curr->right = nullptr; return curr; }
void print(BSTNode* root) {
if (root != nullptr) {
print(root->left);
cout << root->data << endl;
print(root->right);
}
}
bool checking(BSTNode* parent, int val) {
if (val == parent->data){
bool left = checking(parent->left, val);
bool right = checking(parent->right, val);
return left||right;
}
else
return false;
}
bool assist(BSTNode* parent) {
if (parent != nullptr) {
assist(parent->left);
assist(parent->right);
return checking(parent, parent->data);
}
else return false;
}
int main() {
BSTNode *test = newnode(1);
test->left=newnode(2);
test->right=newnode(3);
test->left->left=newnode(2);
test->right->right=newnode(5);
print(test);
if (assist(test))
cout << "There is duplicated" << endl;
else
cout << "There is no duplicated" << endl;
return 0;
}
Your checking function should look like this:
bool checking(BSTNode* parent, int val) {
if(parent == nullptr) // point 1
return false;
if (val == parent->data){ // point 2
return true;
}
else{
bool left = checking(parent->left, val);
bool right = checking(parent->right, val);
return left||right;
}
}
Your assist function should look something like this:
bool assist(BSTNode* parent) {
if (parent != nullptr) {
if(checking(parent->left, parent->data)) return true; // point 3
if(checking(parent->right, parent->data)) return true;
return assist(parent->left)||assist(parent->right); // point 4
}
else return false;
}
You need to check for null values.
If val is same, why are you still checking? Just stop
You need to check node's value in the left and right subtree.
Recurse it for the child nodes
If you want to check that parent value is different than child values, you might do:
bool checking(const BSTNode* node, int parent_value) {
if (node == nullptr) { return false; }
if (node->data == parent_value) { return true; }
return checking(node->left, node->data)
|| checking(node->right, node->data);
}
bool assist(const BSTNode* parent) {
if (parent == nullptr) {
return false;
}
return checking(parent->left, parent->data)
|| checking(parent->right, parent->data);
}
You could just go through the BST breadth wise with a Deque. Store the values in a set and check if the value is already in the set, if it is return true otherwise wait for the loop to finish and return true. This had the benefit of hash table lookup for values at thr cost of extra storage in O(n) time. Its also easier to follow in my opinion as it's not recursion.
bool hasDuplicate(BSTNode *parent)
{
if (!parent) return false;
std::dueue<BSTNode*> nodes;
std::unordered_set<int> vals;
nodes.push_back(parent);
while(!nodes.empty()) {
BSTNode *node = nodes.pop_front();
int v = nodes->val;
// Check if value exists and return true
if(vals.find(v) != vals.end()) return true;
// Otherwise insert it
vals.insert(v);
// insert left node if exists
if (node->left) nodes.push_back(node->left);
// insert right node if exists
if (node->right) nodes.push_back(node->right);
}
// no dups found
return false;
}
Sorry for bad indents. Did this on phone lol.
Given a larg n-ary tree, I need to create a recursive function that prints all the ancestors of a leaf for example where the n-ary tree structure is given as
typedef struct sNaryNode
{
int *data;
int nchild;
struct sNaryNode **child;
} NaryNode;
Here is the function I used but that gives a wrong answer:
bool printAncestors(NaryNode *root, int *data)
{
int i=0;
if (root == NULL)
return false;
if (root->data == data)
return true;
do
{
auto b=printAncestors(root->child[i], data);
if(b)
{
cout<<*root->data<<" ";
return true;
}
else
i++;
}
while(i<root->nchild);
}
You're missing a return value at the end, and you may enter the loop and access root->child[i] even if root->nchild is zero.
Both of those will cause undefined behaviour.
I would write this with a for-loop instead:
bool printAncestors(const NaryNode *root, const int *data)
{
if (root == nullptr)
return false;
if (root->data == data)
return true;
for (int i = 0; i < root->nchild; i++)
{
if (printAncestors(root->child[i], data))
{
cout << *root->data << " ";
return true;
}
}
return false;
}
There is a problem in LeetCode. I use a straightforward recursive solution to solve it, but the run time is to long, which is 170ms. Then I found a similar solution, which also is recursive, and the run time of this is just about 10ms. Why?
My solution:
class Solution
{
public:
bool isBalanced(TreeNode* root)
{
if (root == nullptr)
return true;
bool left = isBalanced(root->left);
bool right = isBalanced(root->right);
bool curr = false;
int sub = height(root->left) - height(root->right);
if (sub < 2 && sub > -2)
curr = true;
return left && right && curr;
}
private:
int height(TreeNode* root)
{
if (root == nullptr)
return 0;
int leftHeight = height(root->left);
int rightHeight = height(root->right);
return (leftHeight > rightHeight) ? (leftHeight + 1) : (rightHeight + 1);
}
};
The fast solution I found:
class Solution {
public:
bool isBalanced(TreeNode *root) {
if (root==NULL) return true;
int left = treeDepth(root->left);
int right = treeDepth(root->right);
if (left-right>1 || left-right < -1) {
return false;
}
return isBalanced(root->left) && isBalanced(root->right);
}
int treeDepth(TreeNode *root) {
if (root==NULL){
return 0;
}
int left=1, right=1;
left += treeDepth(root->left);
right += treeDepth(root->right);
return left>right?left:right;
}
};
Thank you!
Your solution calls both isBalanced and height, always. For every single node in the tree.
The faster solution calls treeDepth for every single node, but bails out early and doesn't call isBalanced if it knows the tree is not balanced. It's an optimization to not call unnecessary (recursive/expensive) functions.