BST Path Traversal Confusion [C++] - c++

I've created a method called pathTo which returns a string of the path taken to find a string x. Here is the method:
string BinarySearchTree::pathTo(BinaryNode* n, const string& x) const
{
if (n == NULL)
{
return "";
}
if (n->value == x)
return x;
if (x.compare(n->value) < 1)
return n->value + " " + pathTo(n->left, x);
else
return n->value +" " + pathTo(n->right, x);
return x;
}
Although the above example works, the above example does not work when I change the last if else statement by checking the right side first instead of the left likeso:
if (x.compare(n->value) > 1)
return n->value + " " + pathTo(n->right, x);
else
return n->value +" " + pathTo(n->left, x);
This provides the wrong path which is what I am confused about. Why is it that the left side needs to be checked first?

Related

How to print a level of a binary search tree?

If we have say, a tree with a depth of 2:
6 <- depth = 0
/ \
/ \
4 9 <- depth = 1
/ \ \
3 5 10 <- depth = 2
And I only want to print the second level, so 3, 5, and 10 (in that order), how would I go about doing this? I'm using the code I wrote for my inorder traversal but I'm stuck on how to track depth of the tree and print when I'm at said depth.
void printLevelNodesHelper(MovieNode * curr, int level){ //helper function
int lvl = level; //store initial value of level
if(curr != NULL){
printLevelNodesHelper(curr->left, level+1);
if(level == lvl){
cout << "Movie: " << curr->title << " " << curr->rating << endl;
}
printLevelNodesHelper(curr->right, level+1);
}
}
void MovieTree::printLevelNodes(int k){ //k is the desired level
MovieNode * curr = root;
if(root == NULL){ //if the tree is empty exit it
return;
}
else if(k == 0){ //print the root's title
cout << "Movie: " << curr->title << " " << curr->rating << endl;
}
else{
printLevelNodesHelper(curr, k);
}
}
Here's the info for my struct and class
struct MovieNode{
int ranking;
string title;
int year;
float rating;
MovieNode* left = NULL;
MovieNode* right = NULL;
};
class MovieTree{
private:
MovieNode* root;
public:
MovieTree();
~MovieTree();
void printMovieInventory();
void addMovieNode(int ranking, std::string title, int year, float rating);
void findMovie(std::string title);
void queryMovies(float rating, int year);
void averageRating();
void printLevelNodes(int k);
};
Some issues:
As your initial call to printLevelNodesHelper gets the desired level as argument, it makes no sense to make recursive calls with level+1. Think about it: when you recur, you actually descend in the tree, coming closer to the desired level, so you should not increase the distance to that level, but decrease it. So you should pass level-1
In printLevelNodesHelper the if condition level == lvl is always going to be true, because neither of these local variables ever change value. As from the previous point we guarantee that eventually we will get a call with level equal to 0, we should check for level == 0 (and so you don't need the lvl variable).
Code:
void printLevelNodesHelper(MovieNode * curr, int level) {
if (curr != NULL) {
printLevelNodesHelper(curr->left, level - 1);
if (level == 0) {
cout << "Movie: " << curr->title << " " << curr->rating << endl;
}
printLevelNodesHelper(curr->right, level - 1);
}
}
With this change, the code for MovieTree::printLevelNodes does not need to deal with the boundary cases of root == NULL or k == 0. Both of these are well managed in the above helper function. On the other hand, you might want to add some protection against the infinite recursion that would occur if printLevelNodes is called with a negative value of k:
void MovieTree::printLevelNodes(int k) {
if (k >= 0) printLevelNodesHelper(root, k);
}

List and count the most weight path from the root to the leafs of a binary tree

I have to return the number of nodes and the weight of the most weight path from the root to some leaf. Note that the tree is not a Binary Search Tree, is unsorted.
i.e.:
6
/ \
9 6
/ / \
3 1 19
Then, I have to return the integer 6 + 6 + 19 = 31 and print the node 6 - 6 - 19
So, this is my code:
int heavierPath ( Node * tree ) {
if ( ! tree ) return 0;
int leftWeight = heavierPath( tree->left );
int rightWeight= heavierPath( tree->right );
if ( leftWeight >= rightWeight ) {
if ( tree->left )
cout << tree->left->value << endl;
return tree->value + leftWeight;
}
else {
cout << tree->right->value << endl;
return tree->value + rightWeight;
}
};
And the result is 31, but I see all the nodes values in the terminal.
How can I do to fix it and print only the elements that lies in the heavier path? (only recursive)
Thanks!
This appears to work after I edited it.
Take a look at: http://ideone.com/OGcyun as an example.
Your problem:
Consider the graph as:
6
/ \
9 6
/ / \
3 1 19
Number each node so:
0
/ \
1 2
/ / \
3 4 5
Consider the case where you are at node 1.
You ask for the better path which gives you leftWeight = 3 and rightweight = 0 and you print the "better" path, 3. which isn't part of the end result.
The solution
To solve this problem, I passed up additional data up in a retstruct which contain the path (the heaviest path up to this point), value (to make printing easier), sum (to determine the better path).
Then I changed the function to:
retstruct* heavierPath ( Node * tree ) {
if ( ! tree ) return new retstruct();
//Get both paths
retstruct* leftWeight = heavierPath( tree->left );
retstruct* rightWeight= heavierPath( tree->right );
//Find the "heavier" path
if ( leftWeight->sum >= rightWeight->sum ) {
//Delete lighter path
delete_retstruct(rightWeight);
//Pass up the better path with the correct data
return new retstruct(leftWeight, tree->value, tree->value + leftWeight->sum);
} else {
//Delete lighter path
delete_retstruct(leftWeight);
//Pass up the better path with the correct data
return new retstruct(rightWeight, tree->value, tree->value + rightWeight->sum);
}
};
Added the delete_retstruct function:
void delete_retstruct (retstruct* path) {
if (path->path == NULL) {
delete path;
} else {
delete_retstruct(path->path);
}
}
and the printPath function:
void printPath (retstruct* path) {
if (path->path != NULL) {
std::cout << " - " << path->value;
printPath(path->path);
}
}
This is used like so:
retstruct* path = heavierPath(tree);
//Print sum
std::cout << "Sum: " << path->sum << std::endl;
//Print path
std::cout << "Path: " << path->value;
printPath(path->path);
std::cout << std::endl;
Output:
Sum: 31
Path: 6 - 6 - 19
My suggestion is to make two functions,first function will find the leaf where path from root to it is maximum. So assuming you have pointer to such leaf here is the function to print the path.
bool print(struct node *r, struct node *leaf)
{
if (r == NULL)
return false;
//will print if it is leaf or on path to leaf
if (r == leaf || print(r->left, leaf) || print(r->right, leaf) )
{
printf("%d ", r->val); // this will print in reverse order
// if you want to print from root, store values in stack and then print the value after the function call
return true;
}
return false;
}
The problem is that you are mixing printing the node with finding the sum. The later has to visit all child-nodes while printing only has to visit the ones in the path.
Below is a possible solution:
#include <iostream>
#include <unordered_map>
struct Node
{
Node(int value = 0, Node* left = nullptr, Node* right = nullptr) :
value{value},
left{left},
right{right}
{}
int value;
Node* left;
Node* right;
};
std::unordered_map<Node*, int> map;
int pathSum(Node* node)
{
if (node == nullptr)
{
return 0;
}
else if (map.find(node) == map.end())
{
return (pathSum(node->left) > pathSum(node->right))
? (map[node] = node->value + pathSum(node->left))
: (map[node] = node->value + pathSum(node->right));
}
else
{
return map[node];
}
}
void printPath(Node* node)
{
if (node == nullptr)
{
return;
}
std::cout << node->value << std::endl;
if (pathSum(node->left) > pathSum(node->right))
{
printPath(node->left);
}
else
{
printPath(node->right);
}
}
int main() {
Node* tree = new Node(6,
new Node(9,
new Node(3)),
new Node(6,
new Node(1),
new Node(19)));
std::cout << "Biggest Sum: " << pathSum(tree) << std::endl;
std::cout << "Biggest Sum Path: " << std::endl;
printPath(tree);
return 0;
}
In recursive solutions such as this, it's a good idea to cache the results hence the std::unordered_map. The code has been tested at Ideone.

Depth first search (C++)

I've created a class that contains a vector of Linked Lists. Each Linked List represents a vertice in my graph. The Nodes connected to my linked lists are considered the edges between these vertices. I'm trying to create a DFS function for my graph, but am having trouble with setting the colors of my vertices. I realize there are a lot of problems with my code, but i'm trying to solve one in particular. My DFSit() function ends up in an infinite loop because the color attribute for my list isn't actually getting set to "gray". Any idea why this would be?
void Graph::DFS()
{
int i = 0;
while (i != myvector.size())
{
DFSit(myvector[i], myvector[i].val);
myvector[i].color = "black";
i++;
}
}
void Graph::DFSit(AdjList x, int root)
{
if (x.color == "white")
{
cout << "tree edge ( " << root << "," << x.val << ") " << endl;
}
if (x.color == "gray")
{
cout << "Back Edge ( " << root << "," << x.val << ") " << endl;
return;
}
x.color = "gray";
AdjNode *temp = new AdjNode();
temp = x.front;
int i = 0;
int value;
while (temp != NULL)
{
value = temp->getValue();
while (i != myvector.size())
{
if (value == myvector[i].val)
{
DFSit(myvector[i], root);
}
i++;
}
temp = temp->next;
}
}
Normaly, the proper implementation of the DFS rutine is made with a stack, but this could work also.
I think that you are coloring the node AdjList x and this coloring is not save because you are passing it by val and not by ref.
try changing void Graph::DFSit(AdjList x, int root) into void Graph::DFSit(AdjList& x, int root)

To find height of a binary search tree

/*
* To find the Height of a BST tree
*/
public void findHeight(){
if(this.root == null){
System.out.println("BST Tree is Empty ");
}
else
findHeight(this.root);
}
public int findHeight(Tnode temp){
if(temp == null){
System.out.println("BST Tree is Empty ");
return -1;
}
else{
return 1 + Math.max(findHeight(temp.getLeft()) ,findHeight(temp.getRight()) ) ;
}
}
Program is running infinitely.Not able to find the reason , It would be helpfull ,if some one guides me
Thanks in advance
Are you sure the findHeight() function doesn't return anything? Are you expecting anything from that function? Posting more code would help.
"BST Tree is Empty" will also be printed at every terminal leaf of the tree.
To find out what's going on, you could add some debugging output:
private spaces(int len){
String s = " ";
while (s.Length < len) {
s += " ";
}
return s.substring(0, len);
}
public int findHeight(Tnode temp, int nesting, String msg){
String margin = spaces(2*nesting);
if(temp == null){
System.out.println(margin + msg + ": no sub-tree to explore");
return -1;
}
else{
System.out.println(margin + msg);
int hl = findHeight(temp.getLeft(), nesting + 1, "left");
int hr = findHeight(temp.getRight(), nesting + 1, "right");
return 1 + (hl >= hr ? hl : hr) ;
}
}
Your endless recursion might be due to some error in your tree structure. If your left/right child references are never null, the recursion won't terminate.

c++ trying to find the distance between 2 nodes

I am currently working on a function that has 1 helper function, the main function takes in 2 strings and searches for the first one (which becomes a reference as if it was m_root) and a second one to be searched in the tree. once they are searched, my helper function is supposed to search for the 2nd city and count the distance it had to travel as if a truck was going towards that city.
int Stree::distance(string origin_city, string destination_city)
{
int total_distance = 0;
Node *new_root = m_root;
new_root = find_node(m_root, origin_city);
total_distance = get_distance(new_root, total_distance, destination_city);
return total_distance;
}
int Stree::get_distance(Node* cur, int distance, string destination)
{
Node *tmp = cur;
if(cur == NULL)
return 0;
if(cur->m_city == destination || tmp->m_city == destination)
{
//cout << distance + cur->m_parent_distance << endl;
return distance += cur->m_parent_distance;
}
if(tmp->m_left != NULL)
{
//cout << "checking left" << endl;
tmp = cur->m_left;
return get_distance(cur->m_left, distance, destination) ;
}
else
{
//cout << "checking right" << endl;
return get_distance(cur->m_right, distance, destination);
}
}
In a cursory glance, I don't see anywhere that you modify or increment distance, whether it be the distance variable or something like:
return 1 + get_distance(cur->m_right, distance, destination);
So I would make sure that in an algorithmic sense, each step walked is counted, otherwise it will certainly return 0 every time.