Huffman tree pointer point to unexpected location - c++

I am stuck on a Huffman Tree problem. I think my code has a clear logic. I first built a priority queue to compare the weight of Node and place the Node with minimum weight at the top of the priority queue.
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
struct Node
{
int weight, depth;
Node *left, *right;
Node(int value):weight(value), left(NULL),right(NULL),depth(0){}
Node(int value, Node* left_leaf_ptr, Node* right_leaf_ptr) : weight(value), left(left_leaf_ptr), right(right_leaf_ptr), depth(0) {}
};
//this struct is used for priority queue
struct Greater
{
bool operator () (Node a, Node b){return a.weight > b.weight;}
};
// find whether the node is a leaf
bool isleaf(Node node) { return node.left == NULL && node.right == NULL; }
// update the depth of Huffman Tree
void update_depth(Node& node,int depth)
{
node.depth=depth;
if (! isleaf(node))
{
depth++;
update_depth(*node.left,depth);
update_depth(*node.right, depth);
}
}
Node build_Huffman_tree(priority_queue<Node, vector<Node>, Greater> weights_queue)
{
while (weights_queue.size() > 1)
{
Node l1=weights_queue.top();
weights_queue.pop();
Node l2 = weights_queue.top();
weights_queue.pop();
Node l3(l1.weight + l2.weight, &l1, &l2);
update_depth(l3, 0);
weights_queue.push(l3);
}
return weights_queue.top();
}
int main()
{
priority_queue<Node, vector<Node>, Greater> weights_queue;
weights_queue.push(Node(1));
weights_queue.push(Node(1));
weights_queue.push(Node(3));
weights_queue.push(Node(5));
Node root = build_Huffman_tree(weights_queue);
return 0;
}
When I run this program in C++ 11, in the second while loop inside the function build_Huffman_tree, it creates a Node of weight 2, depth 4700. What's worse is that this Node seems endless. i.e. its left child tree has weight 2, and this child tree has its left child tree of weight 2, and so on...
So please point out the reason of my program's failure and teach me how to fix it.

Related

Cause of Infinite Loop? (iterative inorder traversal implementation) C++

Question: Implement Inorder Traversal iteratively.
My Attempt: (results in an infinite loop that I haven't been able to debug) any help or suggestions greatly appreciated
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
#include <vector>
#include <stack>
#include <unordered_set>
using namespace std;
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
//iterative sol:
vector<int> sol;
stack<TreeNode*> dfs;
dfs.push(root);
unordered_set<TreeNode*> visited;
visited.insert({root});
TreeNode* temp;
while (!dfs.empty()) {
if (dfs.top()->left != nullptr && visited.find(dfs.top()->left) == visited.end()) {
dfs.push(dfs.top()->left);
visited.insert({dfs.top()->left});
}
else {
sol.push_back(dfs.top()->val);
temp = dfs.top();
dfs.pop();
if (temp->right != nullptr && visited.find(temp->right) == visited.end()) {
dfs.push(temp->right);
visited.insert({temp->right});
}
}
}
return sol;
}
};
EDIT: I don't have the specific internal definitions of the TreeNode, but if you want to run the problem, checkout: https://leetcode.com/problems/binary-tree-inorder-traversal/
Here is the problem :
dfs.push(dfs.top()->left);
visited.insert(dfs.top()->left);
You are pushing to stack (then dfs.top() will change) and then accessing dfs.top()->left in the next line.
You are modifying the stack in the first line here
dfs.push(dfs.top()->left);
visited.insert({dfs.top()->left});
what you want to do is to mark the previous dfs.top()->left as visited, but you are adding more element on top of the stack and thus the new dfs.top() is a different one.
To solve this problem you should use store the previous dfs.top()->left in a different variable.
As a best practice, the variable or object you are working on should be immutable, since the stack is not immutable don't use its top while inserting into it or doing some other computations. Instead store your required variable into something immutatble like temp here
temp = dfs.top();
if (temp->left != nullptr && visited.find(temp->left) == visited.end()) {
dfs.push(temp->left);
visited.insert({temp->left});
}
else {
sol.push_back(dfs.top()->val);
dfs.pop();
if (temp->right != nullptr && visited.find(temp->right) == visited.end()) {
dfs.push(temp->right);
visited.insert({temp->right});
}
}
It only takes 2 simple rules to implement an iterative in-order traversal.
If you're at node X, then:
If X has a right child, then move to the right child, and follow as many left links as possible to find the next node.
Otherwise, find the closest ancestor of X on the right, i.e., the closest ancestor whose left subtree contains X. If there is no such ancestor then you're done.
If your tree doesn't have parent links, then you'll need a stack to store the right ancestors, but there's no need for a visited set:
vector<int> inorderTraversal(TreeNode* tree) {
vector<int> ret;
stack<TreeNode *> nextParents;
for(;tree; tree = tree.left) {
nextParents.push(tree);
}
while(!nextParents.empty()) {
tree = nextParents.pop();
ret.push_back(tree->val);
for(tree = tree.right; tree; tree = tree.left) {
nextParents.push(tree);
}
}
return ret;
}

Depth-first binary search tree traversal to set all values of a tree?

So, I would wonder if it was easy to set all the values of a binary search tree in a simple inorder traversal, my thought being that since inorder traversal hits all the nodes anyway, and saves them in sorted order. Why not make it a generalized 'traverse' function that sets all the values, for instantaneous access later on?
My question:
Is there a way to optimize this? Using iteration instead of recursion (edit: I know it is possible now, using a stack of pointers http://en.wikipedia.org/wiki/Tree_traversal#Implementations)
Can I modify it (or use a similar algorithm) to set successor, predecessor, or height of each node?
#include<iostream>
#include<list>
using namespace std;
class Node{
public:
Node* left;
Node* right;
Node* parent;
int data;
int level;
bool isLeafNode;
bool isLeftChild;
bool hasLeftChild;
bool hasRightChild;
bool hasSibling;
public: Node(int x){
right=NULL;
left=NULL;
parent=NULL;
data = x;
level=0;
isLeafNode=false;
isLeftChild=true;
hasLeftChild=false;
hasRightChild=false;
hasSibling=false;
}
};
class BinarySearchTree{
public:
Node* root;
list<int> inorder;
int total; //total number of nodes
int depth; //maximum level of any node in tree. Level of root is zero
int total_leaf_nodes; //total number of leaf nodes
int total_non_leaf_nodes;
public: BinarySearchTree(){
root=NULL;
total=0;
depth=0;
total_leaf_nodes=0;
total_non_leaf_nodes=0;
}
void traverse(Node* p, int level){ //reset inorder, pass (root,0) to call.
//go left i.e. 'L'
if(p->left!=NULL) traverse(p->left, level+1);
//visit Node i.e. 'V'
total++;
inorder.push_back(p->data); //pushes to last position
p->level=level;
if(level > depth) depth=level;
if(p->left==NULL && p->right==NULL){
p->isLeafNode=true;
total_leaf_nodes++;
}
else{
total_non_leaf_nodes++;
if(p->left!=NULL)p->hasLeftChild=true;
if(p->right!=NULL){
p->hasRightChild=true;
(p->right)->isLeftChild=false;
}
if(p->left!=NULL && p->right!=NULL){
(p->left)->hasSibling=true;
(p->right)->hasSibling=true;
}
}
//go right i.e. 'R'
if(p->right!=NULL) traverse(p->right, level+1);
}
};

Problems with rotations when converting a BST (no recursion) to AVL

I'm working on a university project (Data structures) this weekend and I have to code an AVL tree in C++. I thought that it wouldn't be difficult to code a BST first and then convert it into an AVL. Probably I was wrong... I have two classes, class node and class AVLTree,which is friend of class node. I managed to do the insertions and deletions according to BST's rules (I checked) and also I managed to find the balance factor of its node of the tree (which also worked). However, when I tried the simple left rotations, everything went out of order! Here's my code (first the .h files):
class node
{
public:
node();
private:
int data;
int heightL;
int heightR;
int balance;
node* leftChild;
node* rightChild;
friend class AVLTree; //Only class AVLTree has now access to the private fields of class node
};
class node;
class AVLTree
{
public:
AVLTree();
bool insertNode(int aData);
node* searchNode(int key);
bool deleteNode(int key);
node* findMostLeft(node *aRoot);
node* findMostRight(node *subtree);
void display();
private:
node *root;
void inOrderTraversal(node* pointer);
node* newNode(int aData);
void updateHeightsInserting(int nodeCounter,int aData);
void updateHeightsDeleting(int nodeCounter,int aData);
void updateTreeHeights(node *ptr);
int max(int a,int b);
void balanceTree(node *current,node *previous,node *next);
void slRotation(node* current,node *previous,node *next);
void srRotation(node* current,node *previous,node *next);
void dlRotation(node* current,node *previous,node *next);
void drRotation(node* current,node *previous,node *next);
};
And now the .cpp file of class AVLTree (some methods only)
bool AVLTree::insertNode(int aData)
{
node *current,*next,*ptr;
bool isLeftChild;
int nodeCounter=0;
current=next=root;
ptr=newNode(aData);
if(ptr==NULL) //Couldn't allocate memory
{
return false;
}
if(current==NULL) //Inserting the first node in our tree (root==NULL)
{
root=ptr;
return true; //Successful insertion of root
}
do
{
if(aData<current->data) //If the node we want to insert has data smaller than the current node's data, then repeat the procedure for the left child of the current node
{
next=current->leftChild;
isLeftChild=true;
nodeCounter++;
}
else if(aData>current->data) //If the node we want to insert has data bigger than the current node's data, then repeat the procedure for the right child of the current node
{
next=current->rightChild;
isLeftChild=false;
nodeCounter++;
}
if(next==NULL)
{
if(isLeftChild)
{
current->leftChild=ptr;
}
else
{
current->rightChild=ptr;
}
updateHeightsInserting(nodeCounter,aData);
return true;
}
current=next; //Repeat the procedure for the next node
}while(next!=NULL); //Repeat the procedure until there's no next node, meaning we enter the if(next==NULL) statement
}
The method for updating heights:
void AVLTree::updateHeightsInserting(int nodeCounter,int aData)
{
node *current,*next,*previous;
current=next=previous=root;
do
{
if(aData<current->data)
{
if(current->heightL<nodeCounter)
{
current->heightL=nodeCounter;
}
next=current->leftChild;
nodeCounter--;
}
else if(aData>current->data)
{
if(current->heightR<nodeCounter)
{
current->heightR=nodeCounter;
}
next=current->rightChild;
nodeCounter--;
}
current->balance=current->heightR-current->heightL;
if(abs(current->balance)>1)
{
if(abs(next->heightR-next->heightL)<1) //We use <1, because the hight of the next node hasn't been increased yet-If the next node isn't problematic it means the current node is
balanceTree(current,previous,next);
}
previous=current;
current=next;
}while(next->data!=aData);
}
A trial code for rotation (It doesn't work!)
void AVLTree::slRotation(node *current,node *previous,node *next)
{
if(current==root) //previous=current
{
node *temp;
root=next; //next=current->rightChild
temp=next->leftChild;
next->leftChild=current;
current->rightChild=temp;
}
else
previous->rightChild=next;
current->rightChild=NULL;
next->leftChild=current;
}
And the Balancing method:
void AVLTree::balanceTree(node *current,node *previous,node *next)
{
if(current->balance>1) //if the tree is right heavy
if(next->balance>0) //if the tree's right subtree is right heavy
slRotation(current,previous,next); //perform Simple Left Rotation
else //if the tree's right subtree is left heavy
dlRotation(current,previous,next); //perform Double Left Rotation
else //if the tree is left heavy
if(next->balance<0) //if the tree's left subtree is left heavy
srRotation(current,previous,next); //perform Simple Right Roation
else //if the tree's left subtree is right heavy
drRotation(current,previous,next); //perform Double Right Rotation
updateTreeHeights(root);
}
I also use the updateTreeHeights (this is tested, too and works well without the rotations) method here that isn't efficient, I know, but I didn't have a better idea!
void AVLTree::updateTreeHeights(node *ptr) //Visits the nodes by level recursively (post-order traversal), so that it can calculate the balance of each node
{
if(ptr==NULL)
return;
updateTreeHeights(ptr->leftChild);
updateTreeHeights(ptr->rightChild);
if(ptr->leftChild==NULL && ptr->rightChild==NULL)
{
ptr->heightL=ptr->heightR=0;
}
else if(ptr->leftChild==NULL)
{
ptr->heightR=max(ptr->rightChild->heightL,ptr->rightChild->heightR)+1;
ptr->heightL=0;
}
else if(ptr->rightChild==NULL)
{
ptr->heightL=max(ptr->leftChild->heightL,ptr->leftChild->heightR)+1;
ptr->heightR=0;
}
else
{
ptr->heightL=max(ptr->leftChild->heightL,ptr->leftChild->heightR)+1;
ptr->heightR=max(ptr->rightChild->heightL,ptr->rightChild->heightR)+1;
}
ptr->balance=ptr->heightR-ptr->heightL;
}
Sorry for the long post! It's the first time in my life I use an AVL tree, let alone programming it! Hope you can help!
Problem solved! I messed up with the right and left pointers in double rotations!

Implementation issue in deleting the node of a binary search tree in c++

I have implemented delete method for a Binary Search Tree by referring the pseudo code from CLRS. Below is the buggy implementation. Initially when I delete the leaf node it works but when I am deleting the root node the code fails. Specifically - Value of new root node is coming in the transplant method but in the delete_node method it again shows old node value.
Could someone please point out the error. Thanks in advance.
class bst {
public:
struct node
{
int data;
struct node* ltson;
struct node* rtson;
struct node* parent;
}*btroot;
// replaces the subtree rooted at node u with the subtree rooted at node v
void transplant(bst T, struct node* u, struct node *v) {
if(u->parent==NULL){
T.btroot = v;
}
else if(u->parent->ltson == u)
u->parent->ltson = v;
else
u->parent->rtson = v;
if(v!=NULL)
v->parent = u->parent;
}
void delete_node(bst T,struct node* z) {
struct node * y;
if(z->ltson==NULL)
transplant(T,z,z->rtson);
else if(z->rtson==NULL)
transplant(T,z,z->ltson);
else {
y = minimum(z->rtson);
if(y->parent!=z) {
transplant(T,y,y->rtson);
y->rtson = z->rtson;
y->rtson->parent = y;
}
transplant(T,z,y);
cout<< (T.btroot->data)<<endl; //Old value of root is being printed
y->ltson = z->ltson;
y->ltson->parent = y;
}
}
};
I think you a missing a while loop or an iterator to traverse through the binary tree. This will look up for the node that needs to be deleted and then delete it regardless of its current position.

Why when printing the preorder traversal of a BST my program does nothing

I'm trying to make a code that allows me to enter a tree node and then indicate its preorder traversal, but do not understand what happens. What am I doing wrong?
This is my code:
#include <stdio.h>
#include<iostream>
#include<queue>
#define MAX 100
#include <vector>
#include <stdlib.h>
typedef struct node {
struct node *parent;
struct node *left;
struct node *right;
int value;
} Node;
typedef struct tree {
Node *root;
} Tree;
void findPlace(Node *_toAdd, Node *_current) {
// set this node to the parent so we dont have to do it later (may change next recursion)
_toAdd->parent = _current;
// compare value of node we're adding to current node
if(_toAdd->value < _current->value)
// add the element to the left subtree
if(_current->left == NULL) // if no left subtree yet, add it right here
_current->left = _toAdd;
else // otherwise continue recursion to left subtree
findPlace(_toAdd, _current->left);
else
// add the element to the right subtree
if(_current->right == NULL) // if no right subtree yet, add it right here
_current->right = _toAdd;
else // otherwise, continue recursing to the right subtree
findPlace(_toAdd, _current->right);
}
Node *addNode(int _val, Tree* _tree) {
Node *newNode = (Node *)malloc(sizeof(Node));
newNode->value = _val;
// if the tree is empty, this is the new root
if(_tree->root == NULL)
_tree->root = newNode;
// otherwise, we need to find the right place to put it
else
findPlace(newNode, _tree->root);
// return reference to the node
return newNode;
}
void preOrder(Node *);
int main() {
// create a tree to fool around with
Tree *myTree = (Tree *)malloc(sizeof(Tree));
// Add some values to the tree
addNode(7, myTree);
addNode(3, myTree);
addNode(7, myTree);
addNode(11, myTree);
addNode(6, myTree);
addNode(8, myTree);
addNode(12, myTree);
addNode(0, myTree);
addNode(2, myTree);
addNode(9, myTree);
printf("Pre-Order Traversal: "); preOrder(myTree->root); printf("\n");
return 0;
}
void preOrder(Node *_root)
{
printf("%d ", _root->value);
if(_root->left != NULL)
preOrder(_root->left);
if(_root->right != NULL)
preOrder(_root->right);
}
It is assumed that calling preorder action, it should print the tree in that order but the program simply terminates and does not print anything, im stuck with this please help me, and excuse my English
I think your issue is that you don't have anything stalling the exiting of the program...just use cin
int x;
cin >> x;
return 0;