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

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

Related

C++ Insert Into Binary Search Tree Using Array

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

Huffman Tree, recursive function crashes (pointers are not relayed correctly)

struct node {
float weight;
char value;
node* left_child;
node* right_child;
};
void get_codes(node tree, std::string code, std::map<char, std::string> &codes)
{
if(!tree.left_child && !tree.right_child) // leap node
codes[tree.value] = code;
else
{
get_codes(*tree.left_child, code + "0", codes);
get_codes(*tree.right_child, code + "1", codes);
}
}
int main()
{
std::string test {"this is an example of a huffman tree"};
std::vector<char> alphabet = get_alphabet(test);
std::vector<float> weights = get_weights(test, alphabet);
std::priority_queue<node, std::vector<node>, is_node_greater> heap;
for(int i=0; i<alphabet.size(); i++)
{
node x;
x.weight = weights[i];
x.value = alphabet[i];
x.left_child = nullptr;
x.right_child = nullptr;
heap.push(x);
}
while(heap.size() > 1) {
node fg = heap.top(); heap.pop();
node fd = heap.top(); heap.pop();
node parent;
parent.weight = fg.weight + fd.weight;
parent.left_child = &fg;
parent.right_child = &fd;
heap.push(parent);
}
node tree = heap.top(); // our huffman tree
std::map<char, std::string> codes;
get_codes(tree, "", codes);
}
In the first loop, I build a heap (a priority queue) containing all the leap nodes, ie no left child, no right child (nullptr).
In the second loop, while the heap contains more than one node, I take the two with the smallest weights and I create a parent node with these two nodes as children. The parent node's weight is the sum of the two children's.
Then I have my huffman tree, and I have to get huffman codes. That is to say, I need to get a binary code for each leap node assuming bit '0' represents following the left child and bit '1' represents following the right child.
That's what my function get_codes should do, and where the crash occurs. It never enters the 'if' statement so recursivity never stops, so I think either it never comes to leap nodes but it should because each time the function is called on a child tree ; or the leap nodes/nullptr have been lost..? I'm new at C++ so I'm not very experienced with pointers, but this is how I would do the function in an other language.

How to find a certain element of BST, given key?

So I'm trying to implement a TREE_SUCCESSOR(X) function for BST where X is the key of the node that I'm trying to find the successor of. So far I have this:
int BinarySearchTree::TREE_SUCCESSOR(node* x)
{
//i dont need a new node, I just need a pointer/reference to x.
node* y = NULL;
//node* parent = NULL;
if (x->right != NULL)
{
return FIND_MIN(x->right);
}
else
{
y = x->parent;
while (y != NULL && x == y->right)
{
x = y;
y = y->parent;
}
return y->key;
}
}
My problem is in the main function:
int main()
{
BinarySearchTree bst;
int num = 0;
cout << "Enter number you want to find the successor of: " <<endl;
cin >> num;
if(BST.root->key == num) //if i'm trying to find the successor of the root
{ TREE_SUCCESSOR(BST.root); }
else
{
while(BST.root->key != num) //if the user input does not equal the root key value
{
????
}
}
I want to find out how to traverse the BST to the node of the BST till the key = num. For example, if the tree had nodes 3,4,5 then TREE_SUCCESSOR(4), should return 5. How would I do this??
EDIT
So I decided used a TREE_SEARCH(key) that would find the node with a certain key and return it... and then pass that node into TREE_SUCCESSOR(X).
Do an in-order traversal.
After finding the element continue the traversal, the next element is the one you need.
You don't need any special case regarding if you're looking for the successor of the root, but you need to treat the case where the element is the last one in the traversal, i.e. the largest one one.
My first approach would be to search for examples on the internet "binary search tree successor".
But if I have a big enough ego, I may want to develop my own algorithm. I would draw a binary search tree. Next I would pick a node an figure out the steps to get to the successor. After I have the steps, I would go through the steps using different nodes on the tree and adjust the algorithm (steps) as necessary.
After I had the algorithm, I would code it up.
But you're not me, so you would want to search the internet for "c++ binary search tree successor function".

Binary Search tree Array implementation C++

I am in the process of implementing a Binary Search tree that gets represented using the Array implementation. This is my code so far: Take note that I have done with the Structure of tree and it is being saved as a Linked List. I want to convert this linked list into an array.
My thoughts on how to go about this are as followed. Make a return_array function. Have the Size of the array set to the Max number of nodes( 2^(n-1)+1) and go through the linked list. Root node would be # position 0 on the array then his L-child = (2*[index_of_parent]+1) and R-child = (2*[index_of_parent]+2). I looked around for a bit and searched to find something that can get me an idea of how I can keep track of each node and how I can go through each one.
Am I overthinking this problem?
Can there be a Recursion?
Also, I'm considering creating a visual tree instead of an array but have no idea how to space it out correctly. If anyone has an idea on how to do that it would be awesome to get a better understanding of that.
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cmath>
using namespace std;
struct node {
int data;
struct node* left;
struct node* right;
};
void inorder(struct node* node){
if(node){
inorder(node->left);
cout << node->data << " ";
inorder(node->right);
}
}
void insert(struct node** node, int key){
if(*node == NULL){
(*node) = (struct node*)malloc(sizeof(struct node));
(*node)->data = key;
(*node)->left = NULL;
(*node)->right = NULL;
printf("inserted node with data %d\n", (*node)->data);
}
else if ((*node)->data > key){
insert((&(*node)->left),key);
}
else
insert((&(*node)->right),key);
}
int max_tree(struct node* node){
int left,right;
if(node == NULL)
return 0;
else
{
left=max_tree(node->left);
right=max_tree(node->right);
if(left>right)
return left+1;
else
return right+1;
}
}
//This is where i dont know how to keep the parent/children the array.
void return_array(struct node* node, int height){
int max;
height = height - 1;
max = pow(2, height) - 1;
int arr [height];
}
int main(){
int h;
struct node* root = NULL;
insert(&root, 10);
insert(&root, 20);
insert(&root, 5);
insert(&root, 2);
inorder(root);
cout << endl;
cout << "Height is: ";
cout << max_tree(root);
h = max_tree(root)
return_array(root, h)
}
Considering that you want to efficiently store a binary search tree, using
l = 2i + 1
r = 2i + 2
will waste space every time your tree encounters a leaf node that is not occurring at the end of the tree (breadth-first). Consider the following simple example:
2
/ \
1 4
/ \
3 5
This (when transformed breadth-first into an array) results in
[ 2, 1, 4, -, -, 3, 5 ]
And wastes two slots in the array.
Now if you want to store the same tree in an array without wasting space, just transform it into an array depth-first:
[ 2 1 4 3 5 ]
To recover the original tree from this, follow these steps for each node:
Choose the first node as root
For each node (including root), choose
a) the left child as the next smaller key from the array after the current key
b) the right child as the next bigger key from the array, being no larger than the smallest parent key encountered when last branching left, and smaller than the direct parent's key when you are currently in it's left branch
Obviously finding the correct b) is slightly more complex, but not too much. Refer to my code example here.
If I'm not mistaken, transforming to and from an array will take O(n) in either case. And as no space is wasted, space complexity is also O(n).
This works because binary search trees have more structure than ordinary binary trees; here, I'm just using the binary search tree property of the left child being smaller, and the right child being larger than the current node's key.
EDIT:
After doing some further research on the topic, I found that reconstructing the tree in preorder traversal order is much simpler. The recursive function doing that is implemented here and here, respectively.
It basically consists of these steps:
As long as the input array has unseen entries,
If the value to insert is greater than the current branch's minimum value and less than the current branch's maximum allowed,
Add a node to the tree at the current position and set it's value to the current input value
Remove current value from input
If there are items left in the input,
Recurse into the left child
Recurse into the right child
The current minimum and maximum values are defined by the position inside the tree (left child: less than parent, right child: greater than parent).
For more elaborate details, please refer to my source code links.
If you want to store the tree node in a array,you had better to start from 1 position of your array!So the relation between the parent and its children should be simple:
parent = n;
left = 2n;
right = 2n + 1;
you should BFS the tree,and store the node in the array(If the node is null you should also store in the array using a flag ex 0),you should get the very array of the tree!
To do this you have to follow these steps.
Create an empty queue.
Make the first node of the list as root, and enqueue it to the queue.
Until we reach the end of the list, do the following.
a. Dequeue one node from the queue. This is the current parent.
b. Traverse two nodes in the list, add them as children of the current parent.
c. Enqueue the two nodes into the queue.
Time Complexity: Time complexity of the above solution is O(n) where n is the number of nodes.

BFS implementation

i was recently solving a bfs problem where each node is a different arrangement of elements of an array. but i was unable to come up with a suitable data structure to keep track of the visited nodes in the expanded tree. generally the nodes are different strings so we can just use a map to mark a node as visited but what DS should i use in the above case?
Consider the following pseudocode:
type Node; // information pertaining to a node
type Path; // an ordered list of nodes
type Area; // an area containing linked neighboring nodes
type Queue; // a FIFO queue structure
function Traverse(Area a, Node start, Node end) returns Path:
Queue q;
Node n;
// traverse backwards, from finish to start
q.push(end); // add initial node to queue
end.parent = end; // set first node's parent to itself
while (not q.empty()):
n = q.pop(); // remove first element
if (n == start) // if element is the final element, we're done
break;
for (Node neighbor in a.neighbors(n)): // for each neighboring node
if (neighbor.parent != Null): // if already visited, skip
continue;
neighbor.parent = n; // otherwise, visit
q.push(neighbor); // then add to queue
Path p; // prepare to build path from visited list
for (Node previous = Null, current = n;
previous != current;
previous = current, current = current.parent):
p.add(current); // for each node from start to end, add node to p
// Note that the first node's parent is itself
// thus dissatisfying the loop condition
return p;
The "visited list" is stored as the node's parent. Coding this to C++, you would probably handle most of the nodes as references or pointers since this pseudocode relies on referential behavior.
You start with an Area, which is a field of Nodes. The area knows where each node is in relation to the others. You start at one specific Node, the "start" node, and push it into a queue.
Traversing the area is as simple as getting the list of neighboring nodes from the Area, skipping them if they're already visited, and setting their parent and adding them to the queue otherwise. Traversal ends when a node removed from the queue equals the destination node. You could speed up the algorithm a little by doing this check during the neighbor loop, when the node is initially encountered.
NOTE: You do not need to generate every possible node within the area before beginning the traversal, the Area requires only that once it has created a node, it keeps track of it. This might help your situation where it appears you use permutations of strings or arrays: you could push the starting and ending nodes into the Area, and it could generate and cache neighbor nodes on the fly. You might store them as vectors, which can be compared for equality based on their order and contents with the == operator. See this example.
The traversal goes backwards rather than forwards because it makes rebuilding the path easier (rather than ending up at the end node, with each parent the node before it, you end up at the start node, with each parent the node after it)
Data Structure Summary
Node would need to keep track of enough information for Area to identify it uniquely (via an array index or a name or something), as well as a parent node. The parent nodes should be set to NULL before the traversal to avoid weird behavior, since traversal will ignore any node with its parent set. This keeps track of the visited state too: visited is equivalent to (parent != NULL). Doing it this way also keeps you from having to keep track of the entire path in the queue, which would be very computationally intensive.
Area needs to maintain a list of Node, and needs a neighbor map, or a mapping of which nodes neighbor which other nodes. It's possible that this mapping could be generated on the fly with a function rather than being looked up from a table or some more typical approach. It should be able to provide the neighbors of a node to a caller. It might help to have a helper method that clears the parents of every node as well.
Path is basically a list type, containing an ordered list of nodes.
Queue is whatever FIFO queue is available. You could do it with a linked list.
I like how the syntax highlighting worked on my Wuggythovasp++.
At least as a start, you could try using/implementing something like Java's Arrays.toString() and using a map. Each arrangement would result in a different string, and thus it'll at least get somewhere.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author VAISAKH N
*/
public class BFSME {
public static String path = "";
public static String add = "";
public static void findrec(String temp, String end, String[][] m, int j) {
if (temp.equals(m[j][1])) {
add = m[j][0] + temp + end + "/";
end = temp + end;
System.out.println(end);
path = path + add;
temp = "" + add.charAt(0);
System.out.println("Temp" + temp);
for (int k = 0; k < m.length; k++) {
findrec(temp, end, m, k);
}
}
}
public static void main(String[] args) {
String[][] data = new String[][]{{"a", "b"}, {"b", "c"}, {"b", "d"}, {"a", "d"}};
String[][] m = new String[data.length][2];
for (int i = 0; i < data.length; i++) {
String temp = data[i][0];
String end = data[i][1];
m[i][0] = temp;
m[i][1] = end;
path = path + temp + end + "/";
for (int j = 0; j < m.length; j++) {
findrec(temp, end, m, j);
}
}
System.out.println(path);
}
}
Just for the purpose of understanding, i have provided my sample code here (its in C#)
private void Breadth_First_Travers(Node node)
{
// First Initialize a queue -
// it's retrieval mechanism works as FIFO - (First in First Out)
Queue<Node> myQueue = new Queue<Node>();
// Add the root node of your graph into the Queue
myQueue.Enqueue(node);
// Now iterate through the queue till it is empty
while (myQueue.Count != 0)
{
// now, retrieve the first element from the queue
Node item = myQueue.Dequeue();
Console.WriteLine("item is " + item.data);
// Check if it has any left child
if (item.left != null)
{
// If left child found - Insert/Enqueue into the Queue
myQueue.Enqueue(item.left);
}
// Check if it has right child
if (item.right != null)
{
// If right child found Insert/Enqueue into the Queue
myQueue.Enqueue(item.right);
}
// repeat the process till the Queue is empty
}
}
Here sample code is give with reference of http://en.wikipedia.org/wiki/Binary_tree
as tree is a type of graph it self.
Here is BFS implementation using C++ STL(adjacency lists) for Graph. Here three Array and a Queue is used for complete implementation.
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
//Adding node pair of a Edge in Undirected Graph
void addEdge( vector<int> adj[], int u, int v){
adj[u].push_back(v); // 1st push_back
adj[v].push_back(u); //2nd push_back
//for Directed Graph use only one push_back i.e., 1st push_back() rest is same
}
//Traversing through Graph from Node 0 in Adjacency lists way
void showGraph( vector<int>adj[], int size){
cout<<"Graph:\n";
for(int i=0; i<size ; i++){
cout<<i;
for( vector<int>::iterator itr= adj[i].begin() ; itr!=adj[i].end(); itr++){
cout<<" -> "<<*itr;
}
cout<<endl;
}
}
//Prints Array elements
void showArray(int A[]){
for(int i=0; i< 6; i++){
cout<<A[i]<<" ";
}
}
void BFS( vector<int>adj[], int sNode, int N){
// Initialization
list<int>queue; //Queue declaration
int color[N]; //1:White, 2:Grey, 3:Black
int parentNode[N]; //Stores the Parent node of that node while traversing, so that you can reach to parent from child using this
int distLevel[N]; //stores the no. of edges required to reach the node,gives the length of path
//Initialization
for(int i=0; i<N; i++){
color[i] = 1; //Setting all nodes as white(1) unvisited
parentNode[i] = -1; //setting parent node as null(-1)
distLevel[i] = 0; //initializing dist as 0
}
color[sNode] = 2; //since start node is visited 1st so its color is grey(2)
parentNode[sNode] = -1; //parent node of start node is null(-1)
distLevel[sNode] = 0; //distance is 0 since its a start node
queue.push_back(sNode); //pushing start node(sNode) is queue
// Loops runs till Queue is not empty if queue is empty all nodes are visited
while( !queue.empty()){
int v = queue.front(); //storing queue's front(Node) to v
// queue.pop_front();//Dequeue poping element from queue
//Visiting all nodes connected with v-node in adjacency list
for(int i=0; i<adj[v].size() ;i++){
if( color[ adj[v][i] ] == 1){// if node is not visited, color[node]==1 which is white
queue.push_back(adj[v][i]); //pushing that node to queue
color[adj[v][i]]=2; //setting as grey(2)
parentNode[ adj[v][i] ] = v; //parent node is stored distLevel[ adj[v][i] ] = distLevel[v]+1; //level(dist) is incremented y from dist(parentNode)
}
}//end of for
color[v]=3;
queue.pop_front();//Dequeue
}
printf("\nColor: \n");showArray(color);
printf("\nDistLevel:\n");showArray(distLevel);
printf("\nParentNode:\n");showArray(parentNode);
}
int main(){
int N,E,u,v;//no of nodes, No of Edges, Node pair for edge
cout<<"Enter no of nodes"<<endl;
cin>>N;
vector<int> adj[N]; //vector adjacency lists
cout<<"No. of edges"<<endl;
cin>>E;
cout<<"Enter the node pair for edges\n";
for( int i=0; i<E;i++){
cin>>u>>v;
addEdge(adj, u, v); //invoking addEdge function
}
showGraph(adj,N); //Printing Graph in Adjacency list format
BFS(adj,0,N); /invoking BFS Traversal
}