Binary Search Tree output in tree structure - c++

I used the code from this post, How to display binary search tree in console properly?. It complies fine on my IDE, but it doesnt print out anything so it basically shows nothing. I want it to print out in the tree structure like the post mentioned I posted here. I think I have the code typed wrong for 3rd argument for the printLevel function in int main(). Would char* x = " " work fine? It does give warning message, but I'm not sure if I do it right.
string printLevel(Node *pRoot, int level, string gap)
{
if (level == 1)
{
if (pRoot == 0)
{
cout << ".. printLevel - " << pRoot << ": " << gap << "-" << gap << "\n";
return gap + "-" + gap;
}
stringstream out;
out << pRoot->data;
//cout << ".. printLevel - " << pRoot << ": " << gap << pRoot->data << gap << "\n";
return gap + out.str() + gap;
}
else if(level > 1)
{
string left = printLevel(pRoot ? pRoot->pLeft : 0, level - 1, gap);
string right = printLevel(pRoot ? pRoot->pRight : 0, level - 1, gap);
//cout << ".. printLevel - " << pRoot << ": '" << left << "', '" << right << "'\n";
return left + " " + right;
}
else return
"";
}
void printLevelOrder(Node* pRoot, int depth)
{
for (int i = 1; i <= depth; i++)
{
string gap = "";
for (int j = 0; j < pow(2, depth - i) - 1; j++)
{
gap += " ";
}
string levelNodes = printLevel(pRoot, i, gap);
cout << levelNodes <<endl;
}
}
in the main
Node *pRoot = NULL;
int inputValue = 0;
char* gap = " ";
// Loop to read in input values
cout << "To build a BST enter positive integer values, followed by -1 \n";
while (inputValue != -1)
{
cin >> inputValue;
if( inputValue != -1)
{
insertIntoTree( pRoot, inputValue);
}
}
cout << endl;
// Display the tree
printLevel(pRoot, inputValue, gap);
printLevelOrder(pRoot, inputValue);

Related

cargo transportation system we are not sure how to display the last part of our task

Here is our code for the task we are almost finishing just the last part we are stuck at
"Fastest: 3 trips (1 Van, 3 Mini-lorry, $645) "
we are not sure how to display the values in the bracket we only able to display 3 trips.
Is there a way to also display the values in the bracket stated as well?
we use
int min = *min_element(vTrips.begin(), vTrips.end());
cout << "Fastest: " << min << " trips" << endl;
but this only display the 3 trips.
#include <iostream>
#include <vector>
#include <iterator>
#include <fstream>
#include<algorithm>
using namespace std;
class CTS //cargo transport system
{
int i;
int cargo, lorryprice, vanprice, lorrysize, vansize, allOps;
public:
void set_cargo(int);
void set_lorryprice(int);
void set_vanprice(int);
void set_lorrysize(int);
void set_vansize(int);
};
void CTS::set_cargo(int total_cargo) {
cargo = total_cargo;
}
void CTS::set_lorryprice(int lorryP) {
lorryprice = lorryP;
}
void CTS::set_vanprice(int vanP) {
vanprice = vanP;
}
void CTS::set_lorrysize(int lorryS) {
lorrysize = lorryS;
}
void CTS::set_vansize(int vanS)
{
vansize = vanS;
}
int main()
{
int cargo, lorryprice, vanprice, lorrysize, vansize, options, i, no_lorry, no_van, cost, trips;
ifstream infile;
infile.open("size.txt");
if (infile.is_open()) {
infile >> cargo;
infile >> lorryprice;
infile >> vanprice;
infile >> lorrysize;
infile >> vansize;
}
CTS run;
run.set_cargo(cargo);
run.set_lorryprice(lorryprice);
run.set_vanprice(vanprice);
run.set_lorrysize(lorrysize);
run.set_vansize(vansize);
infile.close();
options = (cargo / lorrysize) + 1;
no_lorry = (cargo / lorrysize);
no_van = (cargo / vansize) + 3;
if (cargo % lorrysize == 0) {
no_van = -3;
}
if (cargo % lorrysize != 0) {
no_van = ((cargo % lorrysize) / 10) - 3;
}
/*it = numbervan.begin();
for (auto ir = numbervan.rbegin(); ir != numbervan.rend(); ++ir) {
cout << *ir << endl;
}*/
vector<int> vCost, vVan, vTrips, vLorry;
vector <int>::iterator it;
for (i = 1; i < options + 1; i++)
{
int numberlorry = no_lorry;
cout << "Option " << i << ":" << endl;
cout << "Number of Mini-Lorries : " << no_lorry-- << endl;
if (no_van >= -3) {
no_van += 3;
}
cout << "Number of Vans : " << no_van << endl;
int numbervan = no_van;
if (numberlorry > numbervan) {
trips = numberlorry;
}
else {
trips = numbervan;
}
cout << "Trips Needed : " << trips << endl;
cost = (numberlorry * lorryprice) + (no_van * vanprice);
cout << "Total Cost : $" << cost << endl;
vCost.push_back(cost);
vLorry.push_back(numberlorry);
vVan.push_back(numbervan);
vTrips.push_back(trips);
}
int counter = vCost.size() - 1;
//std::vector<int>::reverse_iterator ir = vCost.rbegin();
for (i = 1; i < 4; i++) {
//cout << "Lowest #" << i << ": "<<cost<<endl;
cout << "Lowest #" << i << ": $" << vCost[counter] << "(" << vVan[counter] << " Vans, " << vLorry[counter] << " Mini-Lorry, " << vTrips[counter] << " Trips)" << endl;
counter--;
}
int min = *min_element(vTrips.begin(), vTrips.end()); // this line of code we figured out how to
cout << "Fastest: " << min << " trips" << endl; //display the number of trips using algorithm
return 0;
}
Your design is awkward; you create an instance of CTS run; and never use it.
Assuming that you do your calculations right, you need to know at what index you found min. If you store the iterator returned by min_element(), you can get an index by subtracting vTrips.begin() from it. Then the corresponding elements in your vCost, vLorry and vVan vectors will contain the data you want.
However, it would be easier if you define a struct containing your pre-calculated values, and push that into some vector. In that case, all related data is kept together.

I can't get a value except 0 from my fixed array as input

I got a task from my lecture to make association program from my data mining class, and i'm using c++ in microsoft visual studio 2017 since that is the only language i understand.
I'm trying to get support result but all i got is 0. i use an algorithm i got from some sites, but i can't implement it to my code because the value is 0.
I think the problem is in the input data reading, the one with for(int i=0;i<n;i++).
this is my code :
#include<iostream>
#include<string>
using namespace std;
int main()
{
float n = 5, support1 = 0, support2 = 0, support3 = 0;
string item1, item2;
//dataset fixed
string tra1[5] = { "milk", "beer" , "coffee" , "sugar" , "detergen" };
string tra2[5] = { "egg", "flour" , "milk" , "sugar" };
string tra3[5] = { "coffee", "butter" , "cigarette" , "sugar" };
string tra4[5] = { "doritos", "tea" , "coconut oil" , "soap" };
string tra5[5] = { "detergen", "milk" , "sugar" , "coca cola" };
cout << "item 1 : "; cin >> item1;//for example coffee
cout << "item 2 : "; cin >> item2;//for example sugar
cout << endl << "------------------------------" << endl;
//i think this is where the problem is
for (int i = 0;i < n;i++)
{
//tra1
if (item1 == tra1[5]) { support1 + 1; }
if (item2 == tra1[5]) { support2 + 1; }
if (item1 == tra1[5] && item2 == tra1[5]) { support3 + 1; }
//tra2
if (item1 == tra2[5]) { support1 + 1; }
if (item2 == tra2[5]) { support2 + 1; }
if (item1 == tra2[5] && item2 == tra2[5]) { support3 + 1; }
//tra3
if (item1 == tra3[5]) { support1 + 1; }
if (item2 == tra3[5]) { support2 + 1; }
if (item1 == tra3[5] && item2 == tra3[5]) { support3 + 1; }
//tra4
if (item1 == tra4[5]) { support1 + 1; }
if (item2 == tra4[5]) { support2 + 1; }
if (item1 == tra4[5] && item2 == tra4[5]) { support3 + 1; }
//tra5
if (item1 == tra5[5]) { support1 + 1; }
if (item2 == tra5[5]) { support2 + 1; }
else if (item1 == tra1[5] && item2 == tra5[5]) { support3 + 1; }
}
//print how many times are coffee and sugar purchased
cout << "Transaction done " << item1 << " : " << support1 << endl;
cout << "Transaction done " << item2 << " : " << support2 << endl;
cout << "Transaction done " << item2 << " dan " << item2 << " : " << support3 << endl;
cout << endl << "------------------------------" << endl;
float result1,result2,result3;
result1 = (support1 / n) * 100;
result2 = (support2 / n) * 100;
result3 = (support3 / n) * 100;
cout << "Item 1 : " << item1 << "\t" << "Item 2 : " << item2 << endl;
cout << "support " << item1 << " : " << result1 << endl;
cout << "support " << item2 << " : " << result2 << endl;
cout << "support " << item1 << " dan " << item2 << " : " << result3 << endl;
return 0;
}
in your code, inside the loop you keep referencing tra2[5] . I think you mean to use tra2[i] instead. The way you have it now you're only looking at one past the last item in your arrays (arrays are 0-based. Valid indices are [0-4])
2 things, you’re for loop is trying to access the 6th index of the array when it’s only initialized to have 5 indicis.
2nd the support1,2,3 variables are initialized to 0 but you never actually increment those variables, which are used as part of your final calculation.
Your for loop needs to change to have “support1 + 1” be “support1+=1”.

Segmentation fault using unordered_map unordered_set on recursive function

I'm relatively new programming c++. I'm implementing a tree like index for a db using unorderd_map on the implementation of the tree data structure to store the children nodes. As im working with tree like structures the construction an search methods are recursive, also i store the pointers of the nodes, so i suspect i may have a sort of not well handled memory issue. I'm getting a segmentation fault. Next is my code and the output of it.
#include <memory>
#include <sstream>
#include <unordered_map>
#include <iostream>
#include <string>
#include <sqlite3.h>
#include "aux_functions.cpp"
#include <math.h>
using namespace std;
class TreeLikeIndex
{
public:
TreeLikeIndex(string attribute, string indices, int indices_count, short int is_leaf, unordered_map<string, TreeLikeIndex*> children);
TreeLikeIndex(string indices, int indices_count);
TreeLikeIndex();
string search(unordered_map<string, string> *);
private:
string indices;
int indices_count;
short int is_leaf;
string attribute;
unordered_map<string, TreeLikeIndex*> children;
};
string TreeLikeIndex::search(unordered_map<string, string> * _tuple)
{
if((*_tuple).empty() || this->is_leaf ) return this->indices;
string att_val = (*_tuple)[this->attribute];
(*_tuple).erase(this->attribute);
TreeLikeIndex * child_with_that_value = this->children[att_val];
return (*child_with_that_value).search(_tuple);
}
class DecisionTreeLikeIndexer
{
public:
DecisionTreeLikeIndexer(string, string, string);
int rebuild_index();
TreeLikeIndex * get_index();
private:
TreeLikeIndex * build_index(unordered_set<string> attributes_list, int depth, string comma_separated_ids, int ids_list_count);
TreeLikeIndex * index;
string source_db_address;
string dest_folder_address;
time_t time_of_last_build;
unordered_set<string> columns_names;
string source_table_name;
unordered_set<string> temp_tables_names;
string id_column_name;
sqlite3 * source_db_connection;
int table_count;
};
int DecisionTreeLikeIndexer::rebuild_index()
{
this->index = this->build_index(this->columns_names, 0, "", 0);
this->time_of_last_build = time(NULL);
return 0;
}
TreeLikeIndex * DecisionTreeLikeIndexer::get_index()
{
return this->index;
}
DecisionTreeLikeIndexer::DecisionTreeLikeIndexer(string source_db_address, string table_name, string dest_folder_address)
{
this->source_db_address = source_db_address;
this->dest_folder_address = dest_folder_address;
this->columns_names = Aux::get_column_names(source_db_address, table_name);
this->source_table_name = table_name;
this->id_column_name = "rowid";
this->source_db_connection = Aux::get_db_connection(this->source_db_address);
// Getting count of this table
sqlite3_stmt* statement;
string query = "SELECT count(*) FROM " + this->source_table_name + ";";
if(sqlite3_prepare(this->source_db_connection, query.c_str(), -1, &statement, 0) == SQLITE_OK)
{
int res = sqlite3_step(statement);
const unsigned char * count_char = sqlite3_column_text(statement,0);
if(res == SQLITE_ROW)
{
stringstream _temp;
_temp << count_char;
_temp >> this->table_count;
}
sqlite3_finalize(statement);
}
else
{
cout << "Error initializating Indexer (Getting initial table count): " << sqlite3_errmsg(this->source_db_connection) << endl;
}
}
TreeLikeIndex * DecisionTreeLikeIndexer::build_index(unordered_set<string> attributes_list, int depth, string comma_separated_ids, int ids_list_count)
{
if( attributes_list.size() <=1 || (depth > 0 && ids_list_count <= 1))
{
Aux::tabs(depth);
cout << "Leaf at depth: " << depth << " Ids are: " << comma_separated_ids << " Ids count: " << ids_list_count << endl;
static TreeLikeIndex * node = new TreeLikeIndex((string)comma_separated_ids, (int)ids_list_count);
return node;
}
string source_table = this->source_table_name;
int count = this->table_count;
if(depth > 0)
{
while(1)
{
source_table = *Aux::get_random_list_of_strings(1).begin();
if(this->temp_tables_names.insert(source_table).second) break;
}
const string create_temp_table_stmnt = "CREATE TEMP TABLE " + source_table + " AS SELECT * FROM " + this->source_table_name + " WHERE " + this->id_column_name + " IN(" + comma_separated_ids + ")";
sqlite3_exec(this->source_db_connection, create_temp_table_stmnt.c_str(),Aux::sqlt_callback,0,NULL);
count = ids_list_count;
Aux::tabs(depth);
cout << "Not root node" << endl;
}
Aux::tabs(depth);
cout << "Source table is: " << source_table << " Table count is: " << count << endl;
Aux::tabs(depth);
cout << "Attributes list is: "; for_each(attributes_list.begin(), attributes_list.end(),[](string v){cout << v << " ";});
cout << endl;
const double E = log2(count) ;
Aux::tabs(depth);
cout << "Entropy of node: " << E << endl;
string best_attribute;
double best_gain;
unordered_set<string> best_attribute_values;
for(string attr: attributes_list)
{
Aux::tabs(depth+1);
cout << "Analysing attribute: " << attr << endl;
const string get_at_count_values_query = "SELECT " + attr + ", count(" + attr + ") FROM " + source_table + " GROUP BY " + attr + ";";
sqlite3_stmt * stmnt;
double weighted_entropy = 0;
unordered_set<string> this_att_values;
if(sqlite3_prepare(this->source_db_connection, get_at_count_values_query.c_str(), -1, &stmnt, 0) == SQLITE_OK)
{
for(;;)
{
int res = sqlite3_step(stmnt);
if(res == SQLITE_DONE || res==SQLITE_ERROR)
{
double gAti = E - weighted_entropy;
Aux::tabs(depth+1);
cout << "Finish computing WE for att: " << attr << " Gain is: " << gAti << endl;
if(gAti > best_gain)
{
Aux::tabs(depth+1);
cout << "Found attribute with better gain." << endl;
best_gain = gAti;
best_attribute = attr;
best_attribute_values.clear();
Aux::tabs(depth+1);
for(string v:this_att_values)
{
best_attribute_values.insert(v);
}
cout << endl;
this_att_values.clear();
}
sqlite3_finalize(stmnt);
//delete &res;
break;
}
if(res == SQLITE_ROW)
{
string val = std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmnt,0)));
int vSize = sqlite3_column_int(stmnt,1);
Aux::tabs(depth+2);
this_att_values.insert(val);
double ratio = double(vSize) / double(count);
weighted_entropy += double(ratio) * double(log2(vSize));
Aux::tabs(depth+2);
cout << "Processing value: " << val << " With vSize: " << vSize << " Current WE is: " << weighted_entropy << endl;
}
}
}
}
Aux::tabs(depth);
cout << "Finish processing attributes list. Best attribute is: " << best_attribute << " Best gain is: " << best_gain << endl;
Aux::tabs(depth);
cout << "Best attribute values are: "; for_each(best_attribute_values.begin(), best_attribute_values.end(), [](string v){cout << v << ",";}); cout << endl;
unordered_map<string, TreeLikeIndex *> children;
for(string val: best_attribute_values)
{
const string get_ids_of_bestatt_val = "SELECT rowid FROM " + source_table + " WHERE " + best_attribute + " = " + val + ";";
int ids_count = 0;
sqlite3_stmt * stmnt;
string ids = "";
bool first = 1;
int next_depth = depth + 1;
unordered_set<string> next_attributes_set;
for(string attr: attributes_list) if(attr != best_attribute) next_attributes_set.insert(attr);
if(sqlite3_prepare(this->source_db_connection, get_ids_of_bestatt_val.c_str(), -1, &stmnt,0) == SQLITE_OK)
{
for(;;)
{
int res = sqlite3_step(stmnt);
if(res == SQLITE_ROW)
{
string id = std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmnt,0)));
if(!first) ids += "," + id;
else ids += id;
ids_count++;
}
if(res == SQLITE_DONE || res == SQLITE_ERROR)
{
Aux::tabs(depth+1);
cout << "Adding branch for val: " << val << endl;
Aux::tabs(depth+1);
cout << " Next attributes are: "; for_each(next_attributes_set.begin(), next_attributes_set.end(), [](string v){cout << v << ",";});
cout << " Depth is: " << next_depth << " Ids are: " << ids << " Ids count: " << ids_count << endl;
sqlite3_finalize(stmnt);
static TreeLikeIndex * temp_child = this->build_index(next_attributes_set, next_depth, ids, ids_count);
pair<string, TreeLikeIndex*> child (val, temp_child);
children.insert(child);
}
}
}
}
Aux::tabs(depth);
cout << "Finish processing node, will return." << endl;
static TreeLikeIndex * no_leaf_node = new TreeLikeIndex(best_attribute, "all", count, 0, children);
return no_leaf_node;
}
}
TreeLikeIndex::TreeLikeIndex(std::string attribute, std::string indices, int indices_count, short int is_leaf, unordered_map<std::string, TreeLikeIndex*> children)
{
this->attribute = attribute;
this->indices = indices;
this->is_leaf = is_leaf;
this->children = children;
this->children.clear();
for(pair<string, TreeLikeIndex*> p: children) this->children.insert(p);
this->indices_count = indices_count;
}
TreeLikeIndex::TreeLikeIndex(string indices, int indices_count)
{
this->indices = indices;
this->indices_count = indices_count;
this->is_leaf = 1;
}
TreeLikeIndex::TreeLikeIndex()
{
this->indices = "";
this->indices_count = 0;
this->is_leaf = 1;
}
int main()
{
string source_db_address = "my_table";
string table_name = "b";
string dest_folder_address = ".";
DecisionTreeLikeIndexer indexer(source_db_address, table_name, dest_folder_address);
indexer.rebuild_index();
}
And the output is:
Source table is: b Table count is: 9
Attributes list is: cant_n_dec cant_n_des cant_n_control
Entropy of node: 3.16993
Analysing attribute: cant_n_dec
Processing value: 1 With vSize: 1 Current WE is: 0
Processing value: 2 With vSize: 4 Current WE is: 0.888889
Processing value: 3 With vSize: 2 Current WE is: 1.11111
Processing value: 4 With vSize: 1 Current WE is: 1.11111
Processing value: 5 With vSize: 1 Current WE is: 1.11111
Finish computing WE for att: cant_n_dec Gain is: 2.05881
Found attribute with better gain.
Analysing attribute: cant_n_des
Processing value: 1 With vSize: 2 Current WE is: 0.222222
Processing value: 2 With vSize: 4 Current WE is: 1.11111
Processing value: 3 With vSize: 2 Current WE is: 1.33333
Processing value: 5 With vSize: 1 Current WE is: 1.33333
Finish computing WE for att: cant_n_des Gain is: 1.83659
Analysing attribute: cant_n_control
Processing value: 1 With vSize: 2 Current WE is: 0.222222
Processing value: 2 With vSize: 3 Current WE is: 0.750543
Processing value: 3 With vSize: 3 Current WE is: 1.27886
Processing value: 5 With vSize: 1 Current WE is: 1.27886
Finish computing WE for att: cant_n_control Gain is: 1.89106
Finish processing attributes list. Best attribute is: cant_n_dec Best gain is: 2.05881
Best attribute values are: 1,2,3,4,5,
Adding branch for val: 1
Next attributes are: cant_n_control,cant_n_des, Depth is: 1 Ids are: 3 Ids count: 1
Leaf at depth: 1 Ids are: 3 Ids count: 1
Segmentation fault
I'm not shure but....
I think the problem can be in the following cycle
for(;;)
{
int res = sqlite3_step(stmnt);
if(res == SQLITE_ROW)
{
string id = std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmnt,0)));
if(!first) ids += "," + id;
else ids += id;
ids_count++;
}
if(res == SQLITE_DONE || res == SQLITE_ERROR)
{
Aux::tabs(depth+1);
cout << "Adding branch for val: " << val << endl;
Aux::tabs(depth+1);
cout << " Next attributes are: "; for_each(next_attributes_set.begin(), next_attributes_set.end(), [](string v){cout << v << ",";});
cout << " Depth is: " << next_depth << " Ids are: " << ids << " Ids count: " << ids_count << endl;
sqlite3_finalize(stmnt);
static TreeLikeIndex * temp_child = this->build_index(next_attributes_set, next_depth, ids, ids_count);
pair<string, TreeLikeIndex*> child (val, temp_child);
children.insert(child);
}
}
I don't understand when terminate (no exit conditions in the for(;;), no return's and no break's in the block).
And I suspect that che segmentation fault is caused by the following instruction
int res = sqlite3_step(stmnt);
when, after the SQLITE_DONE or SQLITE_ERROR case (whith a call to
sqlite3_finalize(stmnt);
), the cycle is iterated again, with a stmnt invalid.
The following can be a solution?
if ( sqlite3_prepare(this->source_db_connection, get_ids_of_bestatt_val.c_str(), -1, &stmnt,0) == SQLITE_OK)
{
while ( sqlite3_step(stmnt) == SQLITE_ROW )
{
ids += ( first ? "" : "," )
+ std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmnt,0)));
ids_count++;
}
Aux::tabs(depth+1);
cout << "Adding branch for val: " << val << endl;
Aux::tabs(depth+1);
cout << " Next attributes are: ";
for_each(next_attributes_set.begin(), next_attributes_set.end(), [](string v){cout << v << ",";});
cout << " Depth is: " << next_depth << " Ids are: " << ids << " Ids count: " << ids_count << endl;
sqlite3_finalize(stmnt);
static TreeLikeIndex * temp_child = this->build_index(next_attributes_set, next_depth, ids, ids_count);
pair<string, TreeLikeIndex*> child (val, temp_child);
children.insert(child);
}

C++ Linear Search Algorithm

I have been struggling with the output of a linear search algorithm for a bit of time now. I have the function that searches the list and returns the position, either -1 if it is not found, or the numeric value of where the matching number was found. Any suggestions on how to get this to output correctly?
The output needs to search through testList, see if that number is in stdList, and give its position
Number 1 (34) was located in position 15.
Number 2 (74) was not in the file.
Number 3 (56) was not in the file.
Number 4 (103) was located in position 75.
etc.
Here is the main section of code that I am having problems with.
ARRAY_STANDARD is referring to the size of the array stdList.
stdList is the array being compared against
Position is what is being returned by the function searchList()
testList is referring to the array that is being compared to stdList
value is the element that we are searching for
//Outputs
if (position == -1)
cout << "Number " << testCount+1 << "(" << testList << ")" << " was not in the file." << endl;
else
cout << "Number " << testCount+1 << "(" << testList << ")" << " was located in position " << value << endl;
}
int searchList(int stdList [], int numElems, int value)
{
int index=0;
int position = -1;
bool found = false;
while (index < numElems && !found)
{
if (stdList[index] == value)
{
found = true;
position = index;
}
index++;
}
return position;
}
You seem to have lost a few lines of code in the last edit. What you want to do (pseudo code) is this:
for each element in testList: <<<<< this is the for statement you lost
position = findElement(element, stdList) <<<<< this is the function you were not calling
if(position < 0):
print "not found"
else:
print "found element " element " at position " position
Take it away...
You should change your method in following way:
int searchList(int stdList [], int numElems, int value)
{
int index=0;
while (index < numElems)
{
if (stdList[index] == value)
{
return index;
}
index++;
}
return -1;
}
int searchList(int stdList [], int value)
{
for(int i = 0, length = sizeof(stdList); i < length; ++i)
{
if (stdList[i] == value)
return i;
}
return -1;
}
Successful output.
int results;
for(int i = 0; i < 22; i++)
{
results = searchList(stdList, ARRAY_STANDARD, testList[i]);
if (results == -1)
cout << "Number " << i+1 << "(" << testList[i] << ")" << " was not in the file." << endl;
else
cout << "Number " << i+1 << "(" << testList[i] << ")" << " was located in position " << results+1 << endl;
}

How to display binary search tree in console properly?

I'm trying to display a BST in console. That's my code (it's a modified version of code found here: Printing Level Order Binary Search Tree Formatting):
string printLevel(node *root, int level, string gap) {
if (!root) {
return gap + "-" + gap;
}
if (level==1) {
stringstream out;
out<<root->value;
return gap + out.str() + gap;
} else if (level>1) {
string leftStr = printLevel(root->left, level-1, gap);
string rightStr = printLevel(root->right, level-1, gap);
return leftStr + " " + rightStr;
} else return "";
}
void printLevelOrder (node* root, int depth) {
for (int i=1; i<=depth; i++) {
string gap="";
for (int j=0; j<pow(2,depth-i)-1; j++) {
gap+=" ";
}
string levelNodes = printLevel(root, i, gap);
cout<<levelNodes<<endl;
}
}
For example result should be like that:
4
1 6
- 2 5 -
- - - 3 - - - -
But instead it is:
4
1 6
- 2 5 -
- - 3 - - -
If I undestand correctly, the recursion stops when the program makes it to the empty leaf and therefore there are lacking " - " on the lower levels in the result. But how do I know how much of those I should draw on the lower levels? How to make this work?
I instrumented the code to see where it went awry (since running a debugger in a browser...), you can see it live here. The reproduced function is:
string printLevel(node *root, int level, string gap) {
if (root == 0) {
cout << ".. printLevel - " << root << ": " << gap << "-" << gap << "\n";
return gap + "-" + gap;
}
if (level==1) {
stringstream out;
out<<root->value;
cout << ".. printLevel - " << root << ": " << gap << root->value << gap << "\n";
return gap + out.str() + gap;
} else if (level>1) {
string leftStr = printLevel(root->left, level-1, gap);
string rightStr = printLevel(root->right, level-1, gap);
cout << ".. printLevel - " << root << ": '" << leftStr << "', '" << rightStr << "'\n";
return leftStr + " " + rightStr;
} else return "";
}
And here is the bit of interesting output:
.. printLevel - <none>: -
.. printLevel - <none>: -
.. printLevel - { 3, <none>, <none> }: 3
.. printLevel - { 2, <none>, { 3, <none>, <none> } }: '-', '3'
.. printLevel - { 1, <none>, { 2, <none>, { 3, <none>, <none> } } }: '-', '- 3'
So, the issue is that you short-circuit whenever root is 0, which is actually an issue: - is not the right output unless level is 1.
The only difference between root being 0 and root not being 0 is that you cannot read the value out of it (and thus get to replace it by -); however you only really read that value when level is 1 (beware, you might try to read left or right too), therefore there is no reason to test for root == 0 unless you are in the level == 1 branch.
Let us slightly reorder things then:
string printLevel(node *root, int level, string gap) {
if (level==1) {
// if (root == 0) {
// cout << ".. printLevel - " << root << ": " << gap << "-" << gap << "\n";
// return gap + "-" + gap;
// }
stringstream out;
out<<root->value;
cout << ".. printLevel - " << root << ": " << gap << root->value << gap << "\n";
return gap + out.str() + gap;
} else if (level>1) {
// string leftStr = printLevel(root ? root->left : 0, level-1, gap);
// string rightStr = printLevel(root ? root->right : 0, level-1, gap);
cout << ".. printLevel - " << root << ": '" << leftStr << "', '" << rightStr << "'\n";
return leftStr + " " + rightStr;
} else return "";
}
Note: I "highlighted" the modified lines with "comments".
And now, the tree prints properly.
void BinaryTree::Display(TreeNode *current, int indent)
{
if (current != nullptr)
{
Display(current->left, indent + 4);
if (indent > 0)
cout << setw(indent) << " ";
cout << current->value << endl;
Display(current->right, indent + 4);
}
}
prints tree left to right instead of top down.
1
2
3
4
5
6
7
8
12
18
Here is my code. It prints very well,maybe its not perfectly symmetrical.
little description:
1st function - prints level by level (root lv -> leaves lv)
2nd function - distance from the beginning of new line
3rd function - prints nodes and calculates distance between two prints;
void Tree::TREEPRINT()
{
int i = 0;
while (i <= treeHeight(getroot())){
printlv(i);
i++;
cout << endl;
}
}
void Tree::printlv(int n){
Node* temp = getroot();
int val = pow(2, treeHeight(root) -n+2);
cout << setw(val) << "";
prinlv(temp, n, val);
}
void Tree::dispLV(Node*p, int lv, int d)
{
int disp = 2 * d;
if (lv == 0){
if (p == NULL){
cout << " x ";
cout << setw(disp -3) << "";
return;
}
else{
int result = ((p->key <= 1) ? 1 : log10(p->key) + 1);
cout << " " << p->key << " ";
cout << setw(disp - result-2) << "";
}
}
else
{
if (p == NULL&& lv >= 1){
dispLV(NULL, lv - 1, d);
dispLV(NULL, lv - 1, d);
}
else{
dispLV(p->left, lv - 1, d);
dispLV(p->right, lv - 1, d);
}
}
}
Input:
50-28-19-30-29-17-42-200-160-170-180-240-44-26-27
Output: https://i.stack.imgur.com/TtPXY.png