How to print out a BST in C++ - c++

My C++ program creates a binary search tree. I know how to print out the values in pre-order, post-order, and in-order.
However, I want to do something a little more difficult. I want to print out the values the way they would look if someone drew the tree on paper. It would have the root at the center at the top, it's left child right under and to the left of it, and it's right child right under and to the right of it. The rest of the nodes would be drawn accordingly.
How can I do that?

This article contains code for what you need, it seems:
alt text http://www.cpp-programming.net/wp-content/uploads/2007/12/ascii_tree.jpg
Edit: that site went offline
Here's another one exploring some other options.

Here's approximate pseudo-code to do it. The basic idea is walk the tree layer-by-layer, printing all the node in each layer on one line. Each node is separated by twice as much space as the nodes below it. Since the tree is not all of uniform depth, it is artificially padded with virtual nodes to take up the blank spaces where nodes don't exist.
measure the depth of the tree, call that D
have two queues, called Q1 and Q2
enque the top node of the tree in Q1
for (i = D; --i>=0; ){
foreach node in Q1 {
on first iteration of this inner loop, print 2^i - 1 spaces,
else print 2^(i+1) - 1 spaces.
if node == null print blank
else print node.value
if node.left exists enque node.left in Q2
else enque null in Q2
if node.right exists enque node.right in Q2
else enque null in Q2
}
copy Q2 to Q1
clear Q2
print end-of-line
}
Each space that is printed is the width of one numeric field. Suppose the tree has depth D = 4. Then the printing goes like this:
// it looks like this, and the space sequences are
i = 3: -------n 7
i = 2: ---n-------n 3 7
i = 1: -n---n---n---n 1 3 3 3
i = 0: n-n-n-n-n-n-n-n 0 1 1 1 1 1 1 1

void print(node *p,int start)
{
start++;
if (p->right != NULL)
{
print(p->right,start);
}
for (int i = 0; i <= start; i++)
{
cout<<" ";
}
cout << p->value<<endl;
if (p->left != NULL)
{
print(p->left, start);
}
}

One way is to use graphviz. Specifically, use its "dot" program, but getting the output to look exactly as you describe may not be possible.

well, in a terminal it's hard...since it may not fit. But there are graph drawing libraries out there that can make nice pictures for you. There is graphvis that is one of the most popular.
edit:
if you really just wan to print text, graphvis has a markup language that a user can pass to graphvis that in turn makes the nice pictures.

Related

-nan Error when trying to return the index of a class object

So in my intro to CS class, we're learning about classes and I'm having a lot of trouble right now.
This is project 2 part 2:
https://github.com/CSCI1300-StartingComputing/CSCI1300-Spring2022/blob/main/project/project2/project2pt2.md#question0
project 2 part 1 (part 2 builds on a lot of this stuff:https://github.com/CSCI1300-StartingComputing/CSCI1300-Spring2022/blob/main/project/project2/project2pt1.md#question4
I am specifically on number 6 for part 2.
I believe the problem lies in the below snippet of code:
while (k < numbMovies){temp = movies[k].getTitle(); //store movie title into temp arr
//convert temp to lowercase for case insensitivity
while (b < temp.length()){temp[b] = tolower(temp[b]);
b++;
}
//if the title we're searching is found in the movies array
if (temp == title)
{
movieIdx = k; //the kth movie will be our match, so save k as our index
numMatches++; //increment number of matches. if the title is found, this should be one at most
}
k++;
}
There is an issue somewhere with the line temp = movies[k].getTitle();, I think.
What this line is supposed to do is reference an array from the Movie class developed in part 1, store a title found at 'k' from the movies array into a string so that I can compare it to the string being passed into the function (this comparison is done in the line containing if(temp == title).
I then wish to save the value of k when temp == title as movieIdx, so that this can be used further in this function.
I think that the problem is with my referencing of the movies[] array, but I'm not sure what it might be.
Since there are a lot of things going on in this project, I'd be happy to send my files over to anyone who'd be willing to take a look.
Thanks in advance.
FURTHER CONTEXT:
I was attempting to test edge cases by returning 'movieIdx' immediately after setting movieIdx = k, just to see what was going wrong. Example of what I mean:
{
movieIdx = k; //the kth movie will be our match, so save k as our index
numMatches++; //increment number of matches. if the title is found, this should be one at most
return movieIdx;
}
-nan was returned consistently, although if I returned k outside of the first while loop (that contains the other while loops), I'd get the value that was expected (50, in this case, which equals numbMovies). If I returned movieIdx outside of the loop, I got 0.
This told me that there was some issue with the condition if(temp == title). I then did a test where I replaced 'temp' with a hardcoded value that I knew would be passed, "the prestige".
Doing this returned the expected value. I then knew that there must be some issue with 'temp' itself, and I have assumed that the issue therein would probably have to do with how I'm referencing the movies[] array.

Building a binary tree from a string

I'm trying to build a tree from a string. The string is of the form: ((. (.A.E))(.I.O)), where the 5 leaf nodes of the tree are represented with a period.
I'm unable to determine how to solve this problem; I've tried tweaking the solution to a similar problem offered on this website: https://www.geeksforgeeks.org/construct-binary-tree-string-bracket-representation/.
Would really appreciate any help you could provide, as I prepare for coding interviews.
Thanks!
As I see this, there are just some rules to be followed. Based on the character being processed you have the following options:
If it's a "(", it means you must build your tree deeper, either to the left or to the right, based on the actions you took prior to this one
If it's a ".", you should read the next element in the string to determine the node value and after that you should go back one step in the recursion as the "." represents a leaf
If it's a ")", that means you finished building the subtree of a node and so you must go back one step in the recursion again
Some advices about how to implement this:
Write a recursive function that takes a string as input
The function should also return a string representing the string that remains to be further processed
If at any step your string is empty it means that the string given to be processed is not valid
You should check for the ")" every time you finish building the left or right subtree of a node
Hope this helps and good luck at your interviews!
The solution that I came up with is an iterative solution based on a stack. It has a few rules to follow:
push anything that comes to the stack
If you encounter ) of the stack, start removing elements untill you encounter a (, and then pop that out too.
When you pop the elements in step 2, store them in a vector, except ) and (.
Create a tree Node and mark the parent's children as all the elements in the vector.
push the parent Node back onto the stack.
Let's see with your example:
S = "((a($Z))(An))", changed ' ' -> 'a' for clarity.
Note: Stack growing towards the right.
Stack["((a($Z"]
encounter ')'
Stack["((a"], vector<"Z$">
reverse vector -> vector<"$Z">
Parent Node -> N(id='1'), children -> <N(id='$'), N(id='Z')>
push N(1) to stack
Stack["((a1]
encounter ')'
Stack["("], vector<"1a">
reverse vector -> vector<"a1">
Parent Node -> N(id='2'), children -> <N(id='a'), N(id=1)>
push N(2) to stack
Stack["(2(An"]
encounter ')'
...
you can continue this to get to the top. When you are done, i.e. the string is exhausted, you will get exactly one element left in the stack which would be your parent element or the root of the tree.
Code:
Node* solve(string s) {
stack<Node *> st;
int idx = 0, rt = 1;
while (idx < s.size()) {
Node *n = get_node(s[idx]);
st.push(n);
++idx;
if (st.top()->v == ')') {
st.pop();
vector<Node *> child;
while (st.size() && st.top()->v != '(') {
child.push_back(st.top()); st.pop();
}
if (st.top()->v == '(') st.pop();
Node *par = get_node('0' + rt++);
reverse(child.begin(), child.end());
for (Node *t : child) {
t->parent = par;
par->child.push_back(t);
}
st.push(par);
}
}
return st.top();
}
Full Working code
This code is a general implementation, so any node can have as many children, so n-arry tree construction.
eg:
input: ((a($Zk))(An))
output:
Parent: 4: 2 3
Parent: 2: a 1
Parent: 3: A n
Parent: 1: $ Z k

if-statement executing when it shouldn't (kind of)

int trees = 3;
int tree_x, tree_y;
for(int r = 0; r < m_townsize; r++)
{
for(int c = 0; c < m_townsize; c++)
{
if(r == 0 || c == 0 || r == (m_townsize - 1) || c == (m_townsize - 1))
m_town[r][c] = 'W';
while(trees > 0)
{
tree_x = random() % m_townsize;
tree_y = random() % m_townsize;
cout << tree_y << "," << tree_x << endl;
if(m_town[tree_y][tree_x] == ' ')
{
m_town[tree_y][tree_x] = 'T';
trees -= 1;
}
}
}
}
According the code I have written, if there is a space character at the coordinate of the tree, it should place a tree and lower the tree count by 1.
If there is not a space there, it should skip placing a tree, thus not decrementing. This should cause it to pick another set of coordinates and run through again.
However, if you look at this particular output it is running to the if-statement skipping the first option to replace it with a T--since it is a W--but still decrementing by 1. I don't get it. It should skip the statement all together, not skip just the first line. Netbeans tells me my brackets are right, so it shouldn't be an issue with the assignment belonging to the if and the decrement belonging to the while.
If I make a do-while loop it places a whole bunch. I don't know what's happening.
This output placed 2 trees.
You are walking over each coordinate.
If it is on the edge you put a 'W'. Then you randomly place a tree 'T'.
Then you proceed to the next coordinate.
This means you can place some trees in squares before you overwrite with a 'W'.
Finish all the walls before placing trees. Consider a more efficient way to place walls to, like doing each edge instead of loopimg over the middle abd doing nothing.

Traveling a Grid for a Palindrome

I have been trying to solve this problem for quite a bit now and have not been able to come up with anything other than a naive solution. Basically, I am given a character grid of size N in which I have to find the number of distinct paths from the upper-left to the top-right when only traveling down and to the right that give a palindrome.
Here is an example of a grid:
ABCD
BXZX
CDXB
WCBA
There are 12 palindromes in this grid such as "ABXZXBA". My solution was to walk through all paths in the grid and check if that string was a palindrome by keeping a character stack for the first N characters and popping each character for the next N characters and checking if they were the same. This solution times out when N gets too big and I am not sure how to proceed. Any psuedocode or suggestions would be much appreciated.
Just a theory - I haven't tried to work out the code yet:
You could start at the top left and bottom right and keep the paths in sync. As it is a palindrome there would need to be the same letters in the path from the bottom as from the top.
Each time you look for the next step in a path, check to see that there is a matching letter in the reverse step.
The reverse step's available path can be further constrained in that it can't get to the left or above the forward step.
Stop when the paths meet, which is complicated by the fact that they might end up on the same grid location (odd number of rows), or they might just meet up (even number of rows).
The back tracking and stack keeping may be a bit more complicated, as you have to account for (possibly) several choices of reverse step, but it should cut down the number of possibilities. It might be better to think of it as each step in the forward and reverse paths gives you a new (smaller) grid to check for palindromes.
Something like this?
(At least it stops if the path is not forming a palindrome or is out of bounds/sync.)
JavaScript code:
function f(m){
var stack = [[0,0,m.length - 1,m.length - 1,""]],
count = 0;
while(stack.length > 0){
var next = stack.pop(),
y = next[0],
x = next[1],
yr = next[2]
xr = next[3];
if (y - yr > 0 || x - xr > 0){
continue;
} else if (m[y][x] != m[yr][xr]){
continue;
} else if (y == yr && x == xr){
count++;
} else {
stack.push([y + 1,x,yr - 1,xr]);
stack.push([y + 1,x,yr,xr - 1]);
stack.push([y,x + 1,yr - 1,xr]);
stack.push([y,x + 1,yr,xr - 1]);
}
}
return count;
}
Output:
var t = [["A","B","C","D"]
,["B","X","Z","X"]
,["C","D","X","B"]
,["W","C","B","A"]];
console.log(f(t));
12

C++ - solve a sudoku game

I'm new to C++ and have to do a home assignment (sudoku). I'm stuck on a problem.
Problem is that to implement a search function which to solve a sudoku.
Instruction:
In order to find a solution recursive search is used as follows. Suppose that there is a
not yet assigned field with digits (d1....dn) (n > 1). Then we first try to
assign the field to d1, perform propagation, and then continue with search
recursively.
What can happen is that propagation results in failure (a field becomes
empty). In that case search fails and needs to try different digits for one of
the fields. As search is recursive, a next digit for the field considered last
is tried. If none of the digits lead to a solution, search fails again. This in
turn will lead to trying a different digit from the previous field, and so on.
Before a digit d is tried by assigning a field to
it, you have to create a new board being a copy of the current board (use
the copy constructor and allocate the board from the heap with new). Only
then perform the assignment on the copy. If the recursive call to search
returns unsuccessfully, a new board can be created for the next digit to be
tried.
I've tried:
// Search for a solution, returns NULL if no solution found
Board* Board::search(void) {
// create a copy of the cur. board
Board *copyBoard = new Board(*this);
Board b = *copyBoard;
for(int i = 0; i < 9; i++){
for(int j = 0; j < 9; j++){
// if the field has not been assigned, assign it with a digit
if(!b.fs[i][j].assigned()){
digit d = 1;
// try another digit if failed to assign (1 to 9)
while (d <=9 && b.assign(i, j, d) == false){
d++;
// if no digit matches, here is the problem, how to
// get back to the previous field and try another digit?
// and return null if there's no pervious field
if(d == 10){
...
return NULL;
}
}
}
}
return copyBoard;
}
Another problem is where to use the recursive call? Any tips? thx!
Complete instruction can been found here: http://www.kth.se/polopoly_fs/1.136980!/Menu/general/column-content/attachment/2-2.pdf
Code: http://www.kth.se/polopoly_fs/1.136981!/Menu/general/column-content/attachment/2-2.zip
There is no recursion in your code. You can't just visit each field once and try to assign a value to it. The problem is that you may be able to assign, say, 5 to field (3,4) and it may only be when you get to field (6,4) that it turns out there can't be a 5 at (3, 4). Eventually you need to back out of recursion until you come back to (3,4) and try another value there.
With recursion you might not use nested for loops to visit fields, but visit the next field with a recursive call. Either you manage to reach the last field, or you try all possibilities and then leave the function to get back to the previous field you visited.
Sidenote: definitely don't allocate dynamic memory for this task:
//Board *copyBoard = new Board(*this);
Board copyBoard(*this); //if you need a copy in the first place
Basically what you can try is something like this (pseudocode'ish)
bool searchSolution(Board board)
{
Square sq = getEmptySquare(board)
if(sq == null)
return true; // no more empty squares means we solved the puzzle
// otherwise brute force by trying all valid numbers
foreach (valid nr for sq)
{
board.doMove(nr)
// recurse
if(searchSolution(board))
return true
board.undoMove(nr) // backtrack if no solution found
}
// if we reach this point, no valid solution was found and the puzzle is unsolvable
return false;
}
The getEmptySquare(...) function could return a random empty square or the square with the least number of options left.
Using the latter will make the algorithm converge much faster.