I need to compare each node of one BST with all the nodes of another BST.
Similar to how you'd do comparison in an array:
string arr[10];
string arr2[10];
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
compare(arr[j], arr2[i]);
}
}
but instead of the outer for loop you're traversing in bst1, and instead of the inner for loop, you're traversing in bst2. then comparing node of bst1 with all nodes of bst2, then moving on to the next node of bst1 and comparing that with all of bst2 and so on
Can't seem to wrap my head around how to implement the traversals. Any help would be appreciated
The idea is to call traverse on the root node of Tree1 and for each node in it, pass it to another function compare which is called on root node of Tree2 and compares the passed node with every node in it.
#include <iostream>
struct Node
{
int val;
Node *left, *right;
};
void compare(Node *curr2, Node *curr1)
{
if (curr2 == nullptr)
return;
compare(curr2->left, curr1);
if (curr2->val == curr1->val) // replace with your comparison function
cout << "Match found for " << curr1->val << endl;
compare(curr2->right, curr1);
}
void traverse(Node *curr1, Node *root2)
{
if (curr1 == nullptr)
return;
traverse(curr1->left, root2);
compare(root2, curr1);
traverse(curr1->right, root2);
}
int main()
{
Node *root1, *root2;
traverse(root1, root2);
}
Related
I've been working on this project for a bit now and I'm running into this issue that I can't solve.
As a preface, the program builds a binary tree from data from a file, then the tree can grow, and the new complete information is written over that original file.
To do this all with a single information vector, I'm having my input vector be ordered in level order, however (as far as I understand, please correct me if I'm wrong), in order to do this, I need to have the NULL spaces accounted for in my vector, and to rewrite everything correctly I need faux-NULL (nodes that fill space but don't contain any actual information other than pointers) nodes on my tree.
When the tree grows, then, I'm trying to complete and balance it with "NULL" nodes, and I do so recursively with an in-order traversal and the depth in mind. When I run this, however, I'm getting a Segmentation Fault, and when I run it step by step with the debugger, I'm getting
Cannot open file: ../../../../../src/gcc-4.9.2/libgcc/unwind-sjlj.c
specifically. It occurs when, during the recursive traversal, the algorithm adds a node, and upon reaching the "return" portion of the node's memory allocator, the error pops up and the program breaks.
Is this an error with my code or is it an error with Code::Blocks' libraries?
Relevant code:
struct Node
{
int idx; //idx is information relevant to the program but not to the structure
std::string phrase;
Node* left, * right;
};
Node* newNode(std::string data, int idx) //memory allocator
{
Node* node = new Node;
node->phrase = data;
node->idx = idx;
node->left = node->right = NULL;
return (node); //right here is where the debugger gives me the error
}
// Function to insert nodes in level order
Node* insertLevelOrder(std::string arr[], int idx[], Node* root,int i, int n)
{
// Base case for recursion
if (i < n)
{
Node* temp = newNode(arr[i],idx[i]);
root = temp;
// insert left child
root->left = insertLevelOrder(arr,idx,root->left, 2 * i + 1, n);
// insert right child
root->right = insertLevelOrder(arr,idx,root->right, 2 * i + 2, n);
}
return root;
}
int calcularProfundidad(Node * root) //Sorry for the spanglish--this is "calculateDepth"
{
if (root == NULL)
{
return 0;
}
int h1 = calcularProfundidad(root->left); //recursively calculate depth of left subtree
int h2 = calcularProfundidad(root->right); //and of right subtree
return 1 + max(h1,h2);
}
void rellenarNulos(Node * root, int prof, int counter) //fills "empty spaces" with "faux-NULL" nodes
{
if(counter == prof) //if reaches depth, stops, if not, adds more nodes
return;
if(root->left == NULL && counter < prof)
{
Node * auxNode = newNode("NULL",0); //error in this call
root->left = auxNode;
}
if(root->right == NULL && counter < prof)
{
Node * auxNode2 = newNode("NULL",0);
root->right = auxNode2;
}
rellenarNulos(root->left,prof,counter++);
rellenarNulos(root->right,prof,counter++);
}
#include <iostream>
#include <fstream>
#include <string>
#include "arbLib.hpp"
using namespace std;
int main()
{
//Builds tree from file
int N;
fstream myfile ("test.txt");
if (!myfile.is_open())
{
cout << "Unable to open file" << endl;
return 0;
}
myfile >> N; //N is the number of nodes
string words[N];
for(int i=0;i<N;i++)
myfile >> words[i];
int nums[N];
for(int j=0;j<N;j++)
myfile >> nums[j];
myfile.close();
//Builds tree from these vectors that are level order
Node *root = insertLevelOrder(words,nums,root,0,N);
int prof = calcularProfundidad(root); //calculates depth
rellenarNulos(root,prof,1); //here is where the program dies
inOrder(root);
destroyTree(root);
cout << endl;
return 0;
}
I am writing a symulator of a B-tree.
I read here stackoverflow that the best way is use a queue to make a level order traversal. But i have no idea how to do it.
I work on implementation in c++ from geeksforgeeks.
Perhaps someone knows how to rebuild inorder traversal(code below) to level order traversal.
Classes and constuctors :
class BTreeNode
{
int *keys; // An array of keys
int t; // Minimum degree (defines the range for number of keys)
BTreeNode **C; // An array of child pointers
int n; // Current number of keys
int j;
bool leaf; // Is true when node is leaf. Otherwise false
public:
BTreeNode(int _t, bool _leaf); // Constructor
// A utility function to insert a new key in the subtree rooted with
// this node. The assumption is, the node must be non-full when this
// function is called
void insertNonFull(int k);
// A utility function to split the child y of this node. i is index of y in
// child array C[]. The Child y must be full when this function is called
void splitChild(int i, BTreeNode *y);
// A function to traverse all nodes in a subtree rooted with this node
void traverse();
// A function to search a key in subtree rooted with this node.
BTreeNode *search(int k); // returns NULL if k is not present.
// Make BTree friend of this so that we can access private members of this
// class in BTree functions
friend class BTree;
};
// A BTree
class BTree
{
BTreeNode *root; // Pointer to root node
int t; // Minimum degree
public:
// Constructor (Initializes tree as empty)
BTree(int _t)
{ root = NULL; t = _t; }
// function to traverse the tree
void traverse()
{ if (root != NULL)
cout << "root";
root->traverse(); }
// function to search a key in this tree
BTreeNode* search(int k)
{ return (root == NULL)? NULL : root->search(k); }
// The main function that inserts a new key in this B-Tree
void insert(int k);
};
Inorder traversal :
void BTreeNode::traverse()
{
// There are n keys and n+1 children, travers through n keys
// and first n children
int i;
for (i = 0; i < n; i++)
{
// If this is not leaf, then before printing key[i],
// traverse the subtree rooted with child C[i].
if (leaf == false)
C[i]->traverse();
cout << " " << keys[i];
}
// Print the subtree rooted with last child
if (leaf == false)
C[i]->traverse();
}
Here you can see the Depth-First-Search algorithm (wiki) recursive implementation.
For level-by-level traversal you probably need the Breadth-First-Search (wiki).
To achieve this, we will perform 2 steps.
First step: write recursion-free DFS:
void BTreeNode::traverse()
{
std::stack<BTreeNode*> stack;
stack.push(this);
while (!stack.empty())
{
BTreeNode* current = stack.top();
stack.pop();
int i;
for (i = 0; i < n; i++)
{
if (leaf == false)
stack.push(current->C[i]);
cout << " " << current->keys[i];
}
if (leaf == false)
stack.push(current->C[i]);
}
}
Second step: use queue instead of stack:
void BTreeNode::traverse()
{
std::queue<BTreeNode*> queue;
queue.push(this);
while (!stack.empty())
{
BTreeNode* current = queue.front();
queue.pop();
int i;
for (i = 0; i < n; i++)
{
if (leaf == false)
stack.push(current->C[i]);
cout << " " << current->keys[i];
}
if (leaf == false)
stack.push(current->C[i]);
}
}
So, it's done!
Specifically, the goal here is to create a linked structure that has some number of nodes, between 5 and 2 million. Don’t worry that this number is large or that values may wrap around past the max size of integer. If you have created your linked structure correctly, a modern computer can breeze through this code very quickly. Notice that the comments describe exactly how this main should work. Here are the highlights:
Create three loops
The first loop creates the linked structure, hooking together the “next” fields of each node and giving each node an integer value between 0 and the randomly chosen size.
The second loop adds up all of the nodes and counts them. Counting the nodes in this case should be used only as check to make sure you are not missing one.
The third loop traverses all nodes again, this time deleting them.
Node.h
class Node {
public:
Node();
Node(const Node& orig);
virtual ~Node();
bool hasNext();
Node* getNext();
void setNext(Node* newNext);
int getValue();
void setValue(int val);
private:
Node* next;
int value;
};
#endif
Node.cpp
include "Node.h"
include <iostream>
Node::Node() {
next = NULL;
}
Node::Node(const Node& orig) {
next = orig.next;
value = orig.value;
}
Node::~Node() {
}
bool Node::hasNext(){
if (next != NULL)
return true;
else
return false;
}
Node* Node::getNext(){
return next;
}
void Node::setNext(Node* newNext){
if(newNext == NULL)
next = NULL;
else
next = newNext->next;
}
int Node::getValue(){
return value;
}
void Node::setValue(int val){
value = val;
}
main.cpp
include <cstdlib>
include <iostream>
include "Node.h"
include <time.h>
using namespace std;
int main(int argc, char** argv) {
//This is the node that starts it all
Node *tail;
Node* head = new Node();
//select a random number between 5 and 2,000,000
srand(time(NULL));
int size = (rand() % 2000000) + 5;
int total = 0;
int counter = 0;
//print out the size of the list that will be created/destroyed
cout << "The total size is: " << size << endl;
head->setValue(0);
tail = head;
Node *newNode = new Node;
for (int i = 1; i < size; i++){
Node *newNode = new Node;
newNode->setValue(i);
newNode->setNext(NULL);
tail->setNext(newNode);
tail = newNode;
}
//Create a list that counts from 0 to 2,000,000
//Link all of the nodes together
//A for loop is easiest here
cout << head->getNext()->getValue();
Node* current = head;
while (current != NULL){
counter += current->getValue();
cout << current->getValue();
current = current->getNext();
total++;
}
//Traverse the list you created and add up all of the values
//Use a while loop
//output the number of nodes. In addition, print out the sum
//of all of the values of the nodes.
cout << "Tracked " << total << " nodes, with a total count of " << counter << endl;
//Now loop through your linked structure a third time and
//delete all of the nodes
//Again, I require you use a while loop
cout << "Deleted " << total << " nodes. We're done!" << endl;
return 0;
}
It is printing out the total size then...
I am getting a Seg fault:11.
I am also missing some parts in the main, I am confused on how to write these as well.
it should be next = newNext; instead of next = newNext->next;
void Node::setNext(Node* newNext){
if(newNext == NULL)
next = NULL;
else
next = newNext;
}
First of all, avoid using getter functions in your Abstract Data Type. Those should be reserved for your client test application; keep them out of your ADT. Instead, pass any values in as parameters as re: the prototype. Second, avoid void returning methods in your classes. Rather, return a bool or int. Zero or false for error, and true or some non-zero integer for your success message.
That aside, I was looking up ways to use classes to build nodes, and your post came up. Interesting start. We'll see where we go with this.
Ciao,
Lewsutt
I'm trying to wrap my head around how to write an algorithm to sort a linked list, but I'm having a hard time coming up with something that will work. What we need to do have a linked list that contains a name in a string, and an int for hours. After displaying the list and the sum of the hours, we then have to sort the list in ascending order by the hours in a queue. I have the list and all it's functioned stored in a class object, as you will see. I cleared the whole function of what I had in hopes of coming up with a fresh idea but nothing is coming to mind. I initially was going to create a second linked list that had the sorted list, but then I began to wonder if it was possible to sort it within the same list. Here is my code as of posting.
#include <iostream>
#include <ctime>
using namespace std;
// OrderedLL class
template<class T>
class OrderedLL
{
private:
struct NODE
{
string sName;
int sHours;
NODE *next;
};
NODE *list;
NODE *rear;
public:
// Constructor
OrderedLL () { list = rear = NULL;}
// Insert item x -------------------------------------
void Insert(string x, int y)
{
NODE *r;
// Create a new node
r = new(NODE); r->sName = x; r->sHours = y;
r->next = NULL;
// Inserts the item into the list
r->next = list;
list = r;
}
// Display the linked list --------------------------
void display()
{ NODE *p = list;
while( p != NULL)
{ cout << p->sName << "/" << p->sHours << "-->"; p = p->next;}
cout << "NULL\n";
}
// Delete x from the linked list --------------------
void DeleteNode(T x)
{
NODE *p = list, *r = list;
while( p->info != x) {r=p; p=p->next; }
if( p == list)
{ // delete the first node
list = p->next; delete(p);
}
else
{ r->next = p->next; delete(p);}
}
// Sort by hours ------------------------------------
void sortHours()
{
NODE *p, *q;
}
// Display the total hours --------------------------
friend T totHours(OrderedLL LL)
{
NODE *p;
int total = 0;
p = LL.list;
while(p != NULL)
{
total += p->sHours;
p = p->next;
}
cout << "Total spending time = " << total << endl;
}
}; // end of OrderedLL class
int main(void)
{
// Declare variables
time_t a;
OrderedLL<int> unsortedLL;
OrderedLL<int> sortedLL;
int inHours;
string inName;
// Displays the current time and date
time(&a);
cout << "Today is " << ctime(&a) << endl;
// Asks the user to enter a name and hours 5 times, inserting each entry
// into the queue
for(int i = 0; i < 5; i++)
{
cout << "Enter name and Time: ";
cin >> inName >> inHours;
unsortedLL.Insert(inName, inHours);
}
// Displays the unsorted list
cout << "\nWaiting List-->";
unsortedLL.display();
totHours(unsortedLL);
// Calls for the function to sort the list into a queue by hours
unsortedLL.sortHours();
unsortedLL.display();
return 0;
} // End of "main"
As always thanks to anyone who can help
Try sorting the linked-list like you are sorting an integer array. Instead of swapping the nodes, swap the contents inside the nodes.
If you don't care about efficiency you can use any sorting algorithm. What's different between linked lists and arrays is that the swap operation, to swap the position of two elements while sorting, will be a lot slower because it has to run through the links of the list.
An O(n²) bubble sort is easy to implement with a linked list since it only swaps an element with its neighbor.
If you care about efficiency you can look into implementing the merge sort algorithm even if it's a little more complicated.
You should insert like this
void Insert(string x, int y)
{
NODE *r;NODE *temp;
// Create a new node
r = new NODE; r->sName = x; r->sHours = y;r->next = NULL;
if(list==null)//check if list is empty
{
list=r;//insert the node r in the list
}
else
{
temp=list;
while(temp->next!=null)temp=temp->next;//reach to the end of the list
temp->next=r;//insert it at the end of the list
}
}
No need of rear pointer..just check if list->next is null,if yes you are at the end
and your sorthour function should be
void sortHours()
{
for(NODE* n=list;n->next!=null;n=n->next)//get each of the node in list 1 by 1 except the last one i.e. n
{
for(NODE* n1=n->next;n1!=null;n1=n1->next)//compare the list n node with all the nodes that follow it i.e.n1
{
if(n->sHours > n1->sHours)//if one of the node is the less than n
{
//swap n and n1
node temp=*n;
n->age=n1->age;
n->name=n1->name;
n1->age=temp.age;
n1->name=temp.name;
}
}
}
}
here in this code the compiler print error :
132 C:.... `createlist' undeclared (first use this function)
(Each undeclared identifier is reported only once for each function it appears in.)
and repeat it again in all calls in main function :(
what's the problem ?? plzzzz help me
#include<iostream>
#include<string>
using namespace std;
template <typename T>
struct Node
{
T num;
struct Node<T> *next;
// to craet list nodes
void createlist(Node<T> *p)
{ T data;
for( ; ; ) // its containue until user want to stop
{ cout<<"enter data number or '#' to stop\n";
cin>>data;
if(data == '#')
{ p->next =NULL;
break;
}
else
{ p->num= data;
p->next = new Node<T>;
p=p->next;
}
}
}
//count list to use it in sort function
int countlist (Node<T> *p)
{
int count=0;
while(p->next != NULL)
{ count++;
p=p->next;
}
return count;
}
// sort list
void sort( Node<T> *p)
{ Node<T> *p1, *p2; //element 1 & 2 to compare between them
int i, j , n;
T temp;
n= countlist(p);
for( i=1; i<n ; i++)
{ // here every loop time we put the first element in list in p1 and the second in p2
p1=p;
p2=p->next;
for(j=1; j<=(n-i) ; j++)
{
if( p1->num > p2->num)
{ temp=p2->num;
p2->num=p1->num;
p1->num=temp;
}
}
p1= p1->next;
p2= p2->next;
}
}
//add new number in any location the user choose
void insertatloc(Node<T> *p)
{ T n; //read new num
int loc; //read the choosen location
Node<T> *locadd, *newnum, *temp;
cout <<" enter location you want ..! \n";
cin>>loc;
locadd=NULL; //make it null to checked if there is location after read it from user ot not
while(p->next !=NULL)
{ if( p->next==loc)
{ locadd=p;
break;
}
p=p->next;
}
if (locadd==NULL)
{cout<<" cannot find the location\n";}
else //if location is right
{cout<<" enter new number\n"; // new number to creat also new location for it
cin>>n;
newnum= new Node/*<T>*/;
newnum->num=n;
temp= locadd->next;
locadd->next=newnum;
newnum->next=temp;
}
locadd->num=sort(locadd); // call sort function
}
// display all list nodes
void displaylist (Node<T> *p)
{
while (p->next != NULL)
{
cout<<" the list contain:\n";
cout<<p->num<<endl;
p=p->next;
}
}
};//end streuct
int main()
{
cout<<"*** Welcome in Linked List Sheet 2****\n";
// defined pointer for structer Node
// that value is the address of first node
struct Node<int>*mynodes= new struct Node<int>;
// create nodes in mynodes list
cout<<"\nCreate nodes in list";
createlist(mynodes);
// insert node in location
insertatloc(mynodes);
/* count the number of all nodes
nodescount = countlist(mynodes);
cout<<"\nThe number of nodes in list is: "<<nodescount;*/
// sort nodes in list
sort(mynodes);
// Display nodes
cout<<"\nDisplay all nodes in list:\n";
displaylist(mynodes);
system("pause");
return 0;
}
createlist is a method of your Node class, but inside main() you're calling it as a function. I recommend either treating Node like a C-struct and implementing those methods as functions taking a struct like Thomas mentions, which is how your code is structured anyway, or reading a tutorial on C++ classes.
My guess is you are missing a closing '}' for your node structure:
template <typename T>
struct Node
{
T num;
struct Node<T> *next;
}; // <--- add this line.
createlist is defined to take a parameter of Node<T> *p but you are passing it an instance of struct Node<int>*
createlist is a member method of Node. You are attempting to access Node::createlist from main. You cannot do this (even if you add "Node::" scoping to your call), because createlist is not a static method.
Change it to:
// to create list nodes
static void createlist(Node<T> *p)
and:
// create nodes in mynodes list
cout<<"\nCreate nodes in list";
Node::createlist(mynodes);
Or pull createlist out of the Node class entirely, and make it into its own function.