C++ Insert Into Binary Search Tree Using Array - c++

So, within this particular program , I have nodes stored inside an vector of nodes. These nodes contain a user input int ID, int age, and string Name.
This vector is meant to act as a binary search tree that is organized by ID number, and is not worried about being balanced.
Currently I am attempting to write an insert function in which, after the creation of a new node of user input values, it compares it against the root, which is stored at index 1 of the vector.
If it is smaller than the ID at the root, then it is placed into position (root*2). If it is larger than the root, then it is placed into position (root*2 + 1)
However, I am having an extreme amount of difficulty placing into the vector if these two spots are already being taken up by another node.
Is there any way that I could create a loop that would check against the value in the filled spot, and continue looping until it finds an empty spot?
A current example that I'm working with
ID 50, ID 100, ID 75
ID 50 is in position 1.
ID 100 is inserted in position 3, since it is empty (2*1)
ID 75 is attempted to be inserted, but position 3 is filled, so then I need to check it against ID in position 3 using the same algorithm. In this case, since 75 is lower than 100, it would be placed in position 4.
I'm completely stumped as to how to to implement such an algorithm into a loop
Any help would be much appreciated.
Here is my code.
void BST::insert()
{
int ID;
int AGE;
string NAME;
bool done = false;
int root = 1;
cout << "Please enter the ID number, age and name" << endl;
do
{
cin >> ID >> AGE >> NAME;
} while (ID <= 0);
Node *tree = new Node(ID, AGE, NAME);
if (!binaryTree.empty())
{
do
{
Node &n = binaryTree.at(root);
if (n.ID == 0)
{
n.ID = ID;
n.age = AGE;
n.name = NAME;
done = true;
break;
}
else if (ID < n.ID)
{
root = 2 * root;
}
else
{
root = 2 * root + 1;
}
} while (done = true);
}
if (binaryTree.empty())
{
binaryTree.push_back(*tree);
}
start();
}
I am still very new to this language, so any help would be much appreciated!
EDIT:
I fixed some discrepancies and added the code that was suggested, however, now an out_of_bounds exception is being thrown.
Thanks!

My question is essentially, how would I turn such an alogrithm into a
while loop/do while loop, etc
Here's an answer that uses pseudocode. You should re-write the loop on your own with a different constuct such as a while, do while or for loop.
But first, some problems with your code.
You are comparing Node.ID (an int) to NULL to check if a location in the vector is "empty". NULL has the same semantics as 0 so I am going to assume that no IDs will be 0. Your code doesn't actually check this, so you may want to handle that case and/or address these design issues.
I have no idea why you are dynamically allocating memory with new if you are using a vector to store your nodes. This is likely going to lead to a memory leak.
I am assuming you are handling creating a vector of the appropriate size in code you have not posted. If you don't do this, then your code will crash when at throws an exception when root is outside the bounds of the vector.
If it is smaller than the ID at the root, then it is placed into
position (root*2). If it is larger than the root, then it is placed
into position (root*2 + 1)
What if the ID is equal to the ID at the root?
And finally, the code with the goto loop.
int root = 1;
BEGIN LOOP
Node &n = binaryTree.at(root);
if (n.ID == 0)
{
n.ID = ID;
n.age = AGE;
n.name = NAME;
BREAK OUT OF LOOP
}
else if (ID < n.ID)
{
root = 2*root;
}
else
{
root = 2*root + 1;
}
REPEAT

Related

How do I implement linear probing in C++?

I'm new to Hash Maps and I have an assignment due tomorrow. I implemented everything and it all worked out fine, except for when I get a collision. I cant quite understand the idea of linear probing, I did try to implement it based on what I understood, but the program stopped working for table size < 157, for some reason.
void hashEntry(string key, string value, entry HashTable[], int p)
{
key_de = key;
val_en = value;
for (int i = 0; i < sizeof(HashTable); i++)
{
HashTable[Hash(key, p) + i].key_de = value;
}
}
I thought that by adding a number each time to the hash function, 2 buckets would never get the same Hash index. But that didn't work.
A hash table with linear probing requires you
Initiate a linear search starting at the hashed-to location for an empty slot in which to store your key+value.
If the slot encountered is empty, store your key+value; you're done.
Otherwise, if they keys match, replace the value; you're done.
Otherwise, move to the next slot, hunting for any empty or key-matching slot, at which point (2) or (3) transpires.
To prevent overrun, the loop doing all of this wraps modulo the table size.
If you run all the way back to the original hashed-to location and still have no empty slot or matching-key overwrite, your table is completely populated (100% load) and you cannot insert more key+value pairs.
That's it. In practice it looks something like this:
bool hashEntry(string key, string value, entry HashTable[], int p)
{
bool inserted = false;
int hval = Hash(key, p);
for (int i = 0; !inserted && i < p; i++)
{
if (HashTable[(hval + i) % p].key_de.empty())
{
HashTable[(hval + i) % p].key_de = key;
}
if (HashTable[(hval + i) % p].key_de == key)
{
HashTable[(hval + i) % p].val_en = value;
inserted = true;
}
}
return inserted;
}
Note that expanding the table in a linear-probing hash algorithm is tedious. I suspect that will be forthcoming in your studies. Eventually you need to track how many slots are taken so when the table exceeds a specified load factor (say, 80%), you expand the table, rehashing all entries on the new p size, which will change where they all end up residing.
Anyway, hope it makes sense.

Selective Infinite Loop in Making a Tournament Tree

I want to write a program that randomly generates a tournament tree using only the number of challengers. I read into another such problem, but the answer described how ranks would take part and seeding the players, which went a little over head.
The problem I am facing is that my algorithm produces an infinite loop for values between 1 and 4 inclusively. For all values otherwise, the program runs as desired.
My approach was to take in an array of strings for the competitors' names. Then, I would iterate over each position and randomly select a competitor's name to take that spot. Because I am swapping the names, I have to check for duplicates in the array. I believe this is where my code is experiencing issues.
Here is the snippet that actually determines the tree
for(int i = 0; i < no_players;) {
int index = rand() % ((no_players - i) + i);
// randomly choose an element from the remainder
string temp = players[index];
bool unique = true;
// check all the elements before the current position
for(int j = 0; j < i; j++) {
// if the element is already there, it is not unique
if(players[j] == temp)
unique = false;
}
// only if the element is unique, perform the swap
if(unique) {
players[index] = players[i];
players[i] = temp;
i++;
}
}
Any help is much appreciated!

Searching a Sorted List using Binary Search (C#)

The requirement is to search an alphabetically ordered/sorted list (of string type) using a binary search method for a specified string (in the example below it is "yz") and return the results (every string that starts with the specified string and also the index of that string in the list) on a suitable control like a ListBox.
The problem is that the BinarySearch method has to run several times through a loop so that it returns all the matching strings in the list and not just one. This is my main issue. I can't figure out how to write this loop correctly. If you look inside the while loop, you'll see I'm trying to remove the result that's found from the list so it's not found and returned again. This causes the issue of the index of items in the list being changed. So it returns the wrong index for the results. For example, if you run the code below, it should return the indexes: 9, 10, 11 and 12. However, I'm getting 9, 10, 9, 10 because as the items are removed, the list becomes shorter. I could replace the resulting string with another random string instead of removing it completely, but that would mean the list is not sorted in alphabetical order anymore. For the BinarySearch method to work, the list MUST be sorted in alphabetical order.
The BinarySearch method is probably ok and doesn't need any changing. The problem is with the loop. I should mention this is for an assignment at my university so I can't use any shortcut code / built-in functions. I have tried for hours but can't figure this one out.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
string searchString = "yz";
List<string> list1 = new List<string>();
private void btnSearch_Click(object sender, RoutedEventArgs e)
{
if (list1.Count != 0)
{
list1.Clear();
}
list1.Add("ant"); //0
list1.Add("bb"); //1
list1.Add("bc"); //2
list1.Add("bD"); //3
list1.Add("Be"); //4
list1.Add("j"); //5
list1.Add("RRR"); //6
list1.Add("sT"); //7
list1.Add("Uv"); //8
list1.Add("yz"); //9
list1.Add("yza"); //10
list1.Add("yzb"); //11
list1.Add("yzc"); //12
int index = BinarySearch(list1, 0, list1.Count, searchString);
while (index != list1.Count)
{
listBox1.Items.Add("Index: " + index + " File: " + list1[index]);
list1.RemoveAt(index); //Remove from list so we don't find it again
// but this changes the index of the list
index = BinarySearch(list1, 0, list1.Count, searchString);
}
}
//BinarySearch method to search an alphabetically sorted list for a specified string
public int BinarySearch(List<string> strList, int first, int last, string target)
{
int mid; // index of the midpoint
string midStr; // object that is assigned listStr[mid]
int origLast = last;
// save original value of last
while (first < last)
// test for nonempty sublist
{
mid = (first + last) / 2;
midStr = strList[mid];
int indy = midStr.IndexOf(target, StringComparison.OrdinalIgnoreCase);
if (indy == 0)
return mid;// have a match, we're only matching the beginning of the string
else
{
int order = string.Compare(target, midStr, StringComparison.OrdinalIgnoreCase);
if (order < 0)
last = mid; // search lower sublist. Reset last
else
first = mid + 1; // search upper sublist. Reset first
}
}
return origLast; // target not found
}
}
Why dont you, once you get the index of one of the elements, loop up from index until either you get to the last object or to an object that doesnt start from the string, the loop from index-1 until you get to either 0 or you reach an invalid object.
Edit: To modify your code, what I would do is after:
int index = BinarySearch(list1,0,list1.Count,searchString);
instead of doing your while loop that removes the objects, I would do:
for (int n=index;n<list1.Count;n++) {
if (list1[n].IndexOf(searchString,StringComparison.OrdinalIgnoreCase)!=0) break;
listBox1.Items.Add("Index: " + n + " File: " + list1[n]);
}
for (int n=index-1;n>=0;n--) {
//Do same thing as other loop
}
This will just search both ways in the list and perform your action until it gets to an invalid string, which will then break the loop.

C++ tree with multiple children for telephone number inverse search

I'm trying to write a program to do an inverse search of telephone numbers (user gives a number and program prints out the corresponding person + other numbers that belong to it). Now I have saved the persons' datas in a linked list and am trying to bild up a tree.
Each tree element will save a pointer to a person's data, an index (which is corresponding to a part of the telephone number, for example if the number starts with '0' the index of the root's first child node is '0') and a vector of pointers to it's children.
What I can do so far is saving the first given number in the Tree but there seem to be problems when trying to save more than one number in the tree. Maybe the problem is with the pointers to the children nodes, but i'm not sure there. Here's the said part of the code:
class Tree {
public:
Datensatz *data; //data stored in node
char number; //index of node - part of a telephone number
Tree* wurzel; //root
vector<Tree*> nextEls; //vector of children of node
Tree(int zahl);
/*
div. functions
*/
void add(vector<char>); //called to add telephone number to tree
};
void Tree::hinzufRek(vector<char> telNum)
{
Tree *aktEl = new Tree(); //latest node
aktEl=this->wurzel; //starts with root
int check = 0;
for (int i=0; i<telNum(); i++) {
char h = telNum(i);
if(aktEl->nextEls.size()!=0){
int j;
for (j = 0; j<aktEl->nextEls.size(); j++) {
if (h == aktEl->nextEls[j]->number) { //if latest number already exists in node children...
aktEl = aktEl->nextEls[j];
check = 1;
break;
}
}
if (check == 0) {
aktEl->nextEls.push_back(new Tree(h));
aktEl = aktEl->nextEls[j];
}
}
else { //if there are no current children to latest node
aktEl->nextEls.push_back(new Tree(h));
aktEl = aktEl->nextEls[0];
}
}
}
}
Furthermore, I thought it would be a good idea to delete the Tree* aktEl object at the end of the function, but that only leads to really strange results. I'm not sure if the above code is very clear or if it can be easily understood, but I hope one of you can help me...
Maybe I'm just overseeing something...
Thank you in advance!
roboneko42

Pointer comparision issue

I'm having a problem with a pointer and can't get around it..
In a HashTable implementation, I have a list of ordered nodes in each bucket.The problem I have It's in the insert function, in the comparision to see if the next node is greater than the current node(in order to inserted in that position if it is) and keep the order.
You might find this hash implementation strange, but I need to be able to do tons of lookups(but sometimes also very few) and count the number of repetitions if It's already inserted (so I need fasts lookups, thus the Hash , I've thought about self-balanced trees as AVL or R-B trees, but I don't know them so I went with the solution I knew how to implement...are they faster for this type of problem?),but I also need to retrieve them by order when I've finished.
Before I had a simple list and I'd retrieve the array, then do a QuickSort, but I think I might be able to improve things by keeping the lists ordered.
What I have to map It's a 27 bit unsigned int(most exactly 3 9 bits numbers, but I convert them to a 27 bit number doing (Sr << 18 | Sg << 9 | Sb) making at the same time their value the hash_value. If you know a good function to map that 27 bit int to an 12-13-14 bit table let me know, I currently just do the typical mod prime solution.
This is my hash_node struct:
class hash_node {
public:
unsigned int hash_value;
int repetitions;
hash_node *next;
hash_node( unsigned int hash_val,
hash_node *nxt);
~hash_node();
};
And this is the source of the problem
void hash_table::insert(unsigned int hash_value) {
unsigned int p = hash_value % tableSize;
if (table[p]!=0) { //The bucket has some elements already
hash_node *pred; //node to keep the last valid position on the list
for (hash_node *aux=table[p]; aux!=0; aux=aux->next) {
pred = aux; //last valid position
if (aux->hash_value == hash_value ) {
//It's already inserted, so we increment it repetition counter
aux->repetitions++;
} else if (hash_value < (aux->next->hash_value) ) { //The problem
//If the next one is greater than the one to insert, we
//create a node in the middle of both.
aux->next = new hash_node(hash_value,aux->next);
colisions++;
numElem++;
}
}//We have arrive to the end od the list without luck, so we insert it after
//the last valid position
ant->next = new hash_node(hash_value,0);
colisions++;
numElem++;
}else { //bucket it's empty, insert it right away.
table[p] = new hash_node(hash_value, 0);
numElem++;
}
}
This is what gdb shows:
Program received signal SIGSEGV, Segmentation fault.
0x08050b4b in hash_table::insert (this=0x806a310, hash_value=3163181) at ht.cc:132
132 } else if (hash_value < (aux->next->hash_value) ) {
Which effectively indicates I'm comparing a memory adress with a value, right?
Hope It was clear. Thanks again!
aux->next->hash_value
There's no check whether "next" is NULL.
aux->next might be NULL at that point? I can't see where you have checked whether aux->next is NULL.