Testing if a linked list is equal to each other - c++

I have a set of numbers that are in a linked list. I want to compare them to see if they are the same numbers in a set. Here is my code right now:
bool set::equalset(set second)
{
Data *travel1, *travel2;
travel1 = top;
travel2 = second.topval(); //gets the top value for the second set
while (travel2->next != NULL && travel1->next != NULL)
{
if (!in(travel2->value)) //in checks if the value is in the set
return false;
if (!second.in(travel1->value)) //same idea here
return false;
travel2 = travel2->next;
travel1 = travel1->next;
return true;
}
return false;
}
So what my code does is grab the top values for both of the sets and sets those equal to travel1/2 respectively, then while travel doesn't point to a null value in both sets, it traverses the lists and checks if values from either of the sets are in each other. If a value is not found, it sets it to false. Otherwise, it will be set to true and they are found to be equal.
However, this code only half works - you can easily break it by entering 1, 2 for the first set and 1, 2, 3 for the second set and they will be returned as equal. I would think that the third value (3) would make it return false. What is the missing link here?

Your code has several problems. First, you're not checking the last node. A loop condition like this:
while (travel2->next != NULL && travel1->next != NULL)
will break as soon as one of the enumerators reaches the last node, but never checks it. Further, it will also mean two sets of a single-node-each will always compare true.
Next, You have a hard return after only the first iteration, so there is no conceivable way this ever returned false on two sets that started with the same node value.
travel2 = travel2->next;
travel1 = travel1->next;
return true; // this doesn't belong here.
Next, you pass your parameter by-value, which means the copy constructor is being invoked. I don't know whether you implemented it or not (and if you didn't, you have an entire different problem), but there is no reason to duplicate the list just to see if it is equal to *this*. The function should take a const-reference as the parameter.
bool set::equalset(const set& second)
Finally, your exit condition is correct, but you cannot assume the lists were both exhausted. you have to verify it. You can do this by returning false if either traveler is non-null (and one of them will be if the lists are uneven.
Putting it all together:
bool set::equalset(const set& second)
{
const Data *travel1 = top;
const Data *travel2 = second.top;
while (travel1 && travel2)
{
if (!in(travel2->value)) //in checks if the value is in the set
return false;
if (!second.in(travel1->value)) //same idea here
return false;
travel2 = travel2->next;
travel1 = travel1->next;
}
return !(travel1 || travel2);
}
Optimized for Sorted Lists
If you keep the lists sorted during input and removal methods, you can significantly make this easier, seen below:
bool set::equalset(const set& second)
{
const Data *travel1 = top;
const Data *travel2 = second.top;
while (travel1 && travel2 && travel1->value == travel2->value)
{
travel1 = travel1->next;
travel2 = travel2->next;
}
return !(travel1 || travel2);
}

In the situation you describe, the first set's iterator will be NULL before the third element of the second set is searched for, breaking your while loop. You may as well loop through each set independently. You could also check if both sets have the same number of elements before comparing the elements of each.

You need to adjust your return conditions because as of now, you return true if the first value in both this and second are present in each list.
Do something like this instead:
bool set::equalset(set second)
{
Data *travel1, *travel2;
travel1 = top;
travel2 = second.topval(); //gets the top value for the second set
while (travel2->next != NULL && travel1->next != NULL)
{
if (!in(travel2->value)) //in checks if the value is in the set
return false;
if (!second.in(travel1->value)) //same idea here
return false;
travel2 = travel2->next;
travel1 = travel1->next;
}
return true;
}

with your code if two sets have different number of members. your loop will exit as travel1 or travel2 which has less no. of elements will point to NULL, when other is still not NULL. In your case travel1 will point to NULL and there will still elements to parse in travel2
Check by below code
bool set::equalset(set second)
{
Data *travel1, *travel2;
travel1 = top;
travel2 = second.topval(); //gets the top value for the second set
while (travel2->next != NULL && travel1->next != NULL)
{
if (!in(travel2->value)) //in checks if the value is in the set
return false;
if (!second.in(travel1->value)) //same idea here
return false;
travel2 = travel2->next;
travel1 = travel1->next;
}
if (travel2->next == NULL && travel1->next == NULL)
{
return true;
}
return false;
}
In this code for two set with elements 1 2 2 and 1 2 it will return false

Related

function that returns the number of nodes in a certain level of a binary search tree

I have to create a function getNodesatLevel that returns the number of nodes at a level, however, I'm getting a "may reach end of void function" error. This is for a Binary Search tree, and I'm required to use recursion for this function.
int TreeType::getNodesAtLevel(TreeNode * &node, int level, ItemType * mainArr)
{
int currentLevel = 0;
int NodeCount = 1;
if(currentLevel == level)
{
NodeCount++;
return NodeCount;
}
else if(currentLevel != level)
{
currentLevel++;
if(node->left != NULL)
getNodesAtLevel(node->left, level, mainArr);
if(node->right != NULL)
getNodesAtLevel(node->right, level, mainArr);
}
}
The error is basically what it says on the tin: your function can reach the end without returning a value.
To see why, let's just look at your outer if statement:
if(node->left != NULL)
//...
if(node->right != NULL)
//...
//...
What happens if both node->left and node->right are null? You don't handle this case at all. That's a bug.
Secondly (and arguably most importantly) you call yourself recursively, but don't do anything with the return value of your function. You don't return it, and you don't save it for later either. That means nothing really happens to it. It just gets lost.
Because of this, your function won't return this value at all. That creates situations in which nothing is returned.
So, to fix this, figure out what you want to do with the recursive return value of your function and either a) save it in a temporary variable, or b) simply return it. Which one you choose will depend on what you want your function to count.
Also, make sure you return a value even if both sides of the tree are NULL.

Checking for a cycle in an undirected graph using DFS?

So, I made the following code for DFS:
void dfs (graph * mygraph, int foo, bool arr[]) // here, foo is the source vertex
{
if (arr[foo] == true)
return;
else
{
cout<<foo<<"\t";
arr[foo] = true;
auto it = mygraph->edges[foo].begin();
while (it != mygraph->edges[foo].end())
{
int k = *it;
if (arr[k] == false)
{
//cout<<k<<"\n";
dfs(mygraph,k,arr);
//cout<<k<<"\t";
}
it++;
}
}
//cout<<"\n";
}
Now, I read up that in an undirected graph, if while DFS, it returns to the same vertex again, there is a cycle. Therefore, what I did was this,
bool checkcycle( graph * mygraph, int foo, bool arr[] )
{
bool result = false;
if (arr[foo] == true)
{
result = true;
}
else
{
arr[foo] = true;
auto it = mygraph->edges[foo].begin();
while (it != mygraph->edges[foo].end())
{
int k = *it;
result = checkcycle(mygraph,k,arr);
it++;
}
}
return result;
}
But, my checkcycle function returns true even if their is no cycle. Why is that? Is there something wrong with my function? There is no execution problem, otherwise I would have debugged, but their seems to be something wrong in my logic.
Notice that your function doesn't quite do what you think it does. Let me try to step through what's happening here. Assume the following relationships: (1,2), (1,3), (2,3). I'm not assuming reflexibility (that is, (1,2) does not imply (2,1)). Relationships are directed.
Start with node 1. Flag it as visited
Iterate its children (2 and 3)
When in node 2, recursively call check cycle. At this point 2 is also flagged as visited.
The recursive call now visits 3 (DEPTH search). 3 is also flagged as visited
Call for step 4 dies returning false
Call for step 3 dies returning false
We're back at step 2. Now we'll iterate node 3, which has already been flagged in step 4. It just returns true.
You need a stack of visited nodes or you ONLY search for the original node. The stack will detect sub-cycles as well (cycles that do not include the original node), but it also takes more memory.
Edit: the stack of nodes is not just a bunch of true/false values, but instead a stack of node numbers. A node has been visited in the current stack trace if it's present in the stack.
However, there's a more memory-friendly way: set arr[foo] = false; as the calls die. Something like this:
bool checkcycle( graph * mygraph, int foo, bool arr[], int previousFoo=-1 )
{
bool result = false;
if (arr[foo] == true)
{
result = true;
}
else
{
arr[foo] = true;
auto it = mygraph->edges[foo].begin();
while (it != mygraph->edges[foo].end())
{
int k = *it;
// This should prevent going back to the previous node
if (k != previousFoo) {
result = checkcycle(mygraph,k,arr, foo);
}
it++;
}
// Add this
arr[foo] = false;
}
return result;
}
I think it should be enough.
Edit: should now support undirected graphs.
Node: this code is not tested
Edit: for more elaborate solutions see Strongly Connected Components
Edit: this answer is market as accepted although the concrete solution was given in the comments. Read the comments for details.
are all of the bools in arr[] set to false before checkcycle begins?
are you sure your iterator for the nodes isn't doubling back on edges it has already traversed (and thus seeing the starting node multiple times regardless of cycles)?

Equality operator for linked lists C++

I am trying to create a linked list class and I'm having trouble determining how to check the equality of two lists using the operator== (equality operator). How would I go about going through each node and checking if elements within them are equal in their respective positions?
bool List::operator==(const List& list2) const {
if(mySize != list2.mySize){
return false;
}
if(myFirst == list2.myFirst){
if(myFirst == NULL){
return true;
}
Node * nPtr1 = myFirst;
Node * nPtr2 = list2.myFirst;
while(nPtr1 != NULL){
//what can I do here to check the equality of each element in both lists?
}
}
}
According to your code, myFirst is a pointer, so the following is wrong:
if(myFirst == list2.myFirst)
Unless a node is equal to another node ONLY if it is the same node (pointer wise).
You have a special case when the lists are empty which you kind of captured:
if(myFirst == nullptr && list2.myFirst == nullptr)
{
return true;
}
That would be the empty case.
Otherwise, you got the while properly, and if your items (Node) can simple be compared you would do:
p = myFirst;
q = list2.myFirst;
while(p != nullptr)
{
if(*p != *q) // this is what you're asking about, right?
{
return false;
}
p = p->next; // not too sure how you have a Node separated from the List
q = q->next; // and check next/previous items...
}
return true;
Note that if nodes can only be equal if they have the same pointer then the compare becomes:
if(p != q) // this is a test of pointers instead of objects
P.S. Someone mentioned using a recursive algorithm. That's an idea and conceptually it's great. When using such in the real world, though, you notice that it can be (much) slower. It has to very heavily use the stack and with very large lists, it could break your software.
while(nPtr1 != NULL){
if(nPtr1 != nPtr2){
return false;
}
nPtr1=nPtr1->next;
nPtr2=nPtr2->next;
}
return true;
But this is the way to check if the two lists are identical (nPtr1 and nPtr2 are pointing to the same list). If you really want to compare lists by content you have to compare content like:
if(nPtr1->content != nPtr2->content)
and also change your first pointer check:
if(myFirst->content == list.myFirst->content)

How to add children to BST

I'm trying to make/create a BST, but it doesn't seem to work properly. I've literally been sitting here for hours trying to figure out what's going on. It's gotten to the point where I've drawn a million diagrams to figure this out, yet my code fails me. I need to pass in a root node into a function. Then I need to traverse through the tree until I find that the parent string parameter of the function coincides with the tree parent node's string. If I do find it, I must insert the string into the parent, and create two new children from that parent. If I can't find the parent string, then I return false.
bool insertNode(BSTNode *n, char* parentQ, char* leftQ, char* rightQ)
{
if(n->Q == parentQ)
{
n->left = new BSTNode(leftQ);
n->right = new BSTNode(rightQ);
return true;
}
else if(n->Q != parent)
{
insertNode(n->left,parentQ,leftQ,rightQ);
insertNode(n->right,parentQ,leftQ,rightQ);
}
else
return false;
}
Also I need to make another method that takes the tree that I have established, and corrects the strings. So the method modifies the parent string, if found, and looks at its children, if found, and replaces those strings with those found in the method parameters. It's sort of like adding a subtree without screwing the entire tree up. Thanks in advance!
bool changeNode(BSTNode *n,char* parentQ, char* leftQ, char* rightQ)
{
if(n->Q == leftQ)
{
n->Q = parentQ;
n->left = new BSTNode(leftQ);
n->right = new BSTNode(rightQ);
return true;
}
else if(n->Q == rightQ)
{
n->Q = parentQ;
n->left = new BSTNode(leftQ);
n->right = new BSTNode(rightQ);
return true;
}
else if(n->Q != leftQ)
{
changeNode(n->left,parentQ,leftQ, rightQ);
}
else if(n->Q != rightQ)
{
changeNode(n->right,parentQ,leftQ,rightQ);
}
return false;
}
You didn't even mention what the error was, example input / expected output, but shouldn't you be checking whether the current node actually has a left and right child, before calling the function with those children?
else if(n->Q != parentQ) // <--- you have a typo in this line, "parent"
{ // (and you don't even need the 'if')
insertNode(n->left,parentQ,leftQ,rightQ);
insertNode(n->right,parentQ,leftQ,rightQ);
// in this case you return nothing! corrupted return value
}
^ this seems very error-prone, especially null-pointer. You should turn it into something like:
else
{
if(n->left != NULL) // take a look at nullptr if you have C++11
if(insertNode(n->left,parentQ,leftQ,rightQ)) return true;
if(n->right != NULL)
if(insertNode(n->right,parentQ,leftQ,rightQ)) return true;
return false;
}
Otherwise your true return never gets propagated back beyond the first return, so then you're always returning false unless in the only case where the root of the tree is actually the node you were searching for.
Also, do not compare two char arrays using ==, unless n->Q is actually an std::string. You should use if(strcmp(n->Q, parentQ) == 0) otherwise.
Your second piece of code, however, is just a mess. You need to take a better look at what exactly will be happening on your else if's and see if it is actually doing what you want (hint: it isn't), as you currently only execute at most 1 of the code blocks, even if more than one condition is true.

If condition , doesn't code execute code properly

This code takes a string from a dialog box , and compares it to data in a list,and if succesfull sets the selection on the element from list .
The problem i am having is with the if , it works if i only search the first element , if i try to search any other , it just ignore the if condition and goes till the end o the list .
void CMFC1Dlg::OnBnClickedButton6()
{
CString variable;
cautare.GetWindowTextA(variable);
variable = variable.MakeLower();
if(variable!="")
{
list<Contact*>::iterator seek;
bool flag = TRUE;
int i = 0 ;
while(flag)
{
seek = agenda.first_element();
if( ((CString)((*seek)->getLastName().c_str())).MakeLower() == variable ||
((CString)((*seek)->getFirstName().c_str())).MakeLower() == variable ||
((CString)((*seek)->getFirstAndLastName().c_str())).MakeLower() == variable ||
((CString)((*seek)->getLastAndFirstName().c_str())).MakeLower() == variable)
{
contactsVariable.SetCurSel(i);
this->OnLbnSelchangeList1();
flag=FALSE;
}
advance(seek,i);
i++;
if (i == agenda.list_size())
{
flag = FALSE;
}
}
}
else
MessageBox("No text on input ", "Error", MB_ICONERROR | MB_OK);
cautare.SetFocus();
cautare.SetWindowTextA("");
}
You are setting seek = agenda.first_element(); at the beginning of every iteration of the while loop. Move that statement outside the loop and it should work.
EDIT: You would also need to change the seek call to only seek 1, rather than i, since you're no longer throwing out the result of the previous seeks.
You should move seek = agenda.first_element(); out of the while loop.
Since you are iterating over a list of elements, why not use the begin() and end() method of the associated list. So you can iterate over each element and don't need to advance the iterator in each loop.
The code could look like this
list<Contract*>::iterator seek = agenda.begin();
while (flag && (seek != agenda.end())) {
// do the comparison
seek++;
}
You are only ever comparing the first element move advance(seek,i); like this:
while(flag)
{
seek = agenda.first_element();
advance(seek,i);
...