Equality operator for linked lists C++ - 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)

Related

Why am I unable to enter elements in the linked list while the function is working otherwise?

I wrote a program to merge two sorted linked list into one and this function was the one I used to do it but it's not working. The code of the function is as follows is as follows:
void combine(Node **temp, Node *temp_1, Node *temp_2){
while(temp_1 != NULL || temp_2 != NULL){
if(temp_1->data > temp_2->data){
push(temp, temp_2->data);
temp_2 = temp_2->next;
}
else{
push(temp, temp_1->data);
temp_1 = temp_1->next;
}
}
while(temp_1 != NULL){
push(temp, temp_1->data);
temp_1 = temp_1->next;
}
while(temp_2 != NULL){
push(temp, temp_2->data);
temp_2 = temp_2->next;
}
}
Now, this code doesn't add anything to the final linked list. If I write something like
push(temp, temp_1->data);
it will add elements just fine so the problem isn't definitely with the push function. Can someone tell me what is the problem with the above code?
The full code is in the following URL:
https://ide.geeksforgeeks.org/FZ8IS4PADE
The issue is the while condition:
while(temp_1 != NULL || temp_2 != NULL){
This will allow the execution of the body of the loop when just one of those two pointers is null, and this will result in undefined behaviour on the first statement in that body:
if(temp_1->data > temp_2->data){
The || should be an &&. This will fix your issue.
Other remarks on your code
Don't use NULL for comparing your pointer variables against, but nullptr
The use of push makes your code inefficient: at every push, your code is starting an iteration through the whole list to find the end of it. Since you actually know what is the last node (since it was created in the previous iteration of the loop) this is a waste of time. Instead, keep a reference to the tail of the list that is being created. As there is no tail at the start of the combine process, it might be useful to create a "sentinel" node that comes before the real list that will be returned.
Use better variable names. temp is not temporary at all. It is the result that the caller wants to get: this name is misleading.
Avoid code repetition. The last two loops are the same except for the list that is copied from, and this code is again similar to the parts in the main loop. So create a function that does this job of copying a node from a source list to the end of another list, and that advances both pointers.
Here is what that would look like:
void copyNode(Node **source, Node **targetTail) {
*targetTail = (*targetTail)->next = new Node((*source)->data);
*source = (*source)->next;
}
void combine(Node **result, Node *head_1, Node *head_2){
Node *sentinel = new Node(0); // Dummy
Node *current = sentinel;
while(head_1 != nullptr && head_2 != nullptr){
if(head_1->data > head_2->data){
copyNode(&head_2, &current);
}
else{
copyNode(&head_1, &current);
}
}
if (head_1 == nullptr) {
head_1 = head_2;
}
while (head_1 != NULL) {
copyNode(&head_1, &current);
}
*result = sentinel->next;
delete sentinel;
}

Check if 2 nodes are adjacent in binary tree using linkedlish C++

Sorry for the bad English.
I'm creating a binary tree project by using a linked list in C++. And Im trying to make a boolean method to check if 2 nodes are adjacent or not?
And I'm trying to use the recursion method as I'm using the linked list to do this, but it seems I did it wrong.
Here is how I declare the Node
Struct Node{
string name;
int data;
Node *right, *left;
}
And here is how I declare the checking function:
bool checkadjacent(node* Node, string& u, string& v) {
if(!Node){
return false;
}
if (Node && Node->right) {
string current = Node->name;
string right = Node->right->name;
if (current == u && right == v)
return true;
else if (current == v && right == u)
return true;
}
if (Node && Node->left) {
string current = Node->name;
string left = Node->left->name;
if (current == u && left == v)
return true;
else if (current == v && left == u)
return true;
}
if (Node->left){
if(checkadjacent(Node->left, u, v)){
return true;
}
}
if (Node->right){
if(checkadjacent(Node->right, u, v)){
return true;
}
}
}
Note: "it seems I did it wrong" is not an explanation of how your code fials. Always describe what your code is SUPPOSED to do and what it is ACTUALLY doing.
Having said that, I'm assuming your code does not compile. I put together a (possibly non-comprehensive) list of errors and other problems with your code, aswell as a corrected version of your code. However, I would advise you to watch some tutorials about C++ (or C if you want, since your code is basically C code), because your code shows some serious misunderstandings and neglection. Apart from that, your basic idea seems correct except for the last bullet point in the following list.
List of problems:
It's struct not Struct (capitalization matters in C++). (This is necessary for correctness/syntax)
In the declaration of Node you capitalize the name of the Node. Later, you call it node and instead capitalize the name of the object which instantiates Node (to be consistent, I called the struct Node and it's instantiation node). (This is necessary for correctness/syntax)
First you check whether Node is actually pointing to a struct: if(!Node). This is good, but there is no need to check the same thing again later: if (Node && Node->right) and if (Node && Node->left) just leave out the first part in both conditions: if (node->right) and if (node->left). (This is for style)
Then you can also leave out the 3rd and 4th if statements and put their block into the 1st and 2nd if blocks respectively. (This is for style)
Do not declare the variables current, right and left inside the if blocks, instead declare them at the beginning of the function. (This is for style)
For the algorithm to work you have to return false if none of the if none of the if statements are executed (this is a guess; I did not test this and you WILL have to try that yourself). (This is necessary for correctness/semantics)
Here's the full code (note that I did NOT test this code, as your problem was clearly faulty syntax and not algorithm design.
bool checkadjacent(Node* node, string& u, string& v) {
string current, left, right;
if (!node) {
return false;
}
if (node->right) {
current = node->name;
right = node->right->name;
if (current == u && right == v)
return true;
else if (current == v && right == u)
return true;
// recursion
if (checkadjacent(node->right, u, v)) {
return true;
}
}
if (node->left) {
current = node->name;
left = node->left->name;
if (current == u && left == v)
return true;
else if (current == v && left == u)
return true;
// recursion
if (checkadjacent(node->left, u, v)) {
return true;
}
}
return false;
}
Also note:
I did not change the definition of Node.
Apart from string your code is just C code. In C++ you have the possibility to create a class for the binary tree which would be a lot more readable.
There are no linked lists in any parts of the code above (neither in the code you posted). The fact that the node have left and right child nodes, does not make it a linked list (in particular it's not a list because it is not 1-dimensional).
Again, I did NOT test this code; you can do that yourself.

Readability of for-loops without counters

I recently wrote an implementation for a simple linked list, and at several points in my code it looks like
Node* current_node = head;
while (current_node != nullptr) {
if (current_node->data == query) {
// perform some action
break;
}
current_node = current_node->next;
}
And I just recently thought I could re-implement this as
for (Node* current_node = head; current_node != nullptr; current_node = current_node->next) {
if (current_node->data == query) {
// perform some action
break;
}
}
I know that both are syntactically correct, and that any performance differences should be negligible, but I was wondering if having an equality condition in the check is generally implemented in a for-loop? Previously I have only used inequalities (ex: >, <, etc.) in for-loops. Which version is more conventional/readable?
It's not a bad practice to loop through a linked list via for loop, but you can improve it to:
std::list<type> list;
auto it = std::find(begin(list), end(list), query);
if (it != end(list))
// perform some action

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.

How to check whether a linked list is circular or not? [duplicate]

This question already has answers here:
How to detect a loop in a linked list?
(29 answers)
Closed 5 years ago.
How can I find whether a singly linked list is circular/cyclic or not? I tried to search but couldn't find a satisfactory solution. If possible, can you provide a pseudo-code or Java-implementation?
For instance:
1 → 3 → 5 → 71 → 45 → 7 → 5, where the second 5 is actually the third element of the list.
The standard answer is to take two iterators at the beginning, increment the first one once, and the second one twice. Check to see if they point to the same object. Then repeat until the one that is incrementing twice either hits the first one or reaches the end.
This algorithm finds any circular link in the list, not just that it's a complete circle.
Pseudo-code (not Java, untested -- off the top of my head)
bool hasCircle(List l)
{
Iterator i = l.begin(), j = l.begin();
while (true) {
// increment the iterators, if either is at the end, you're done, no circle
if (i.hasNext()) i = i.next(); else return false;
// second iterator is travelling twice as fast as first
if (j.hasNext()) j = j.next(); else return false;
if (j.hasNext()) j = j.next(); else return false;
// this should be whatever test shows that the two
// iterators are pointing at the same place
if (i.getObject() == j.getObject()) {
return true;
}
}
}
A simple algorithm called Floyd's algorithm is to have two pointers, a and b, which both start at the first element in the linked list. Then at each step you increment a once and b twice. Repeat until you either reach the end of the list (no loop), or a == b (the linked list contains a loop).
Another algorithm is Brent's algorithm.
Three main strategies that I know of:
Starting traversing the list and keep track of all the nodes you've visited (store their addresses in a map for instance). Each new node you visit, check if you've already visited it. If you've already visited the node, then there's obviously a loop. If there's not a loop, you'll reach the end eventually. This isn't great because it's O(N) space complexity for storing the extra information.
The Tortoise/Hare solution. Start two pointers at the front of the list. The first pointer, the "Tortoise" moves forward one node each iteration. The other pointer, the "Hare" moves forward two nodes each iteration. If there's no loop, the hare and tortoise will both reach the end of the list. If there is a loop, the Hare will pass the Tortoise at some point and when that happens, you know there's a loop. This is O(1) space complexity and a pretty simple algorithm.
Use the algorithm to reverse a linked list. If the list has a loop, you'll end up back at the beginning of the list while trying to reverse it. If it doesn't have a loop, you'll finish reversing it and hit the end. This is O(1) space complexity, but a slightly uglier algorithm.
I you count your Nodes and get to the *head again.
How about following approach:
Sort the link list in ascending order by following any standard algorithms.
Before sort: 4-2-6-1-5
After Sort: 1-2-4-5-6
Once sorted, check for each node data and compare with link node's data, something like this:
if(currentcode->data > currentnode->link->data)
i.e. circular = true;
At any comparison, if any of "currentnode->data" is greater than "currentcode->link->data" for a sorted link list, it means current node is pointed to some previous node(i.e circular);
Guys, i dont have setup to test the code.Let me now if this concept works.
Use the Tortoise-Hare algorithm.
A algorithm is:
Store the pointer to the first node
Traverse through the list comparing each node pointer to this pointer
If you encounter a NULL pointer, then its not circularly linked list
If you encounter the first node while traversing then its a circularly linked list
#samoz has in my point of view the answer! Pseudo code missing. Would be something like
yourlist is your linked list
allnodes = hashmap
while yourlist.hasNext()
node = yourlist.next()
if(allnodes.contains(node))
syso "loop found"
break;
hashmap.add(node)
sorry, code is very pseudo (do more scripting then java lately)
Start at one node and record it, then iterate through the entire list until you reach a null pointer or the node you started with.
Something like:
Node start = list->head;
Node temp = start->next;
bool circular = false;
while(temp != null && temp != start)
{
if(temp == start)
{
circular = true;
break;
}
temp = temp->next;
}
return circular
This is O(n), which is pretty much the best that you will able to get with a singly linked list (correct me if I'm wrong).
Or to find any cycles in the list (such as the middle), you could do:
Node[] array; // Use a vector or ArrayList to support dynamic insertions
Node temp = list->head;
bool circular = false;
while(temp != null)
{
if(array.contains(temp) == true)
{
circular = true;
break;
}
array.insert(temp);
temp = temp->next;
}
return circular
This will be a little bit slower due to the insertion times of dynamic arrays.
Here is a nice site on which the different solutions can copied.
find loop singly linked list
This is the winner on that site
// Best solution
function boolean hasLoop(Node startNode){
Node slowNode = Node fastNode1 = Node fastNode2 = startNode;
while (slowNode && fastNode1 = fastNode2.next() && fastNode2 = fastNode1.next()){
if (slowNode == fastNode1 || slowNode == fastNode2) return true;
slowNode = slowNode.next();
}
return false;
}
This solution is "Floyd's
Cycle-Finding Algorithm" as published
in "Non-deterministic Algorithms" by
Robert W. Floyd in 1967. It is also
called "The Tortoise and the Hare
Algorithm".
It will never terminate from the loop, it can also be done in following solution:
bool hasCircle(List l)
{
Iterator i = l.begin(), j = l.begin();
while (true) {
// increment the iterators, if either is at the end, you're done, no circle
if (i.hasNext()) i = i.next(); else return false;
// second iterator is travelling twice as fast as first
if (j.hasNext()) j = j.next(); else return false;
if (j.hasNext()) j = j.next(); else return false;
// this should be whatever test shows that the two
// iterators are pointing at the same place
if (i.getObject() == j.getObject()) {
return true;
}
if(i.next()==j)
break;
}
}
Try this
/* Link list Node */
struct Node
{
int data;
struct Node* next;
};
/* This function returns true if given linked
list is circular, else false. */
bool isCircular(struct Node *head)
{
// An empty linked list is circular
if (head == NULL)
return true;
// Next of head
struct Node *node = head->next;
// This loop would stope in both cases (1) If
// Circular (2) Not circular
while (node != NULL && node != head)
node = node->next;
// If loop stopped because of circular
// condition
return (node == head);
}