Union of two linked lists [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I am trying to develop a friend function for the union of two link lists. Compiler keeps giving me an error saying that Node was not declared in this scope, as well as p,q not declared in this scope. So I added List::Node, but it is not performing the union still
const List getunion(const List&a, const List&b) {
List::Node * p=a.list;
List::Node* q=b.list;
List result;
while (q!=NULL && p!=NULL) {
if(q->value==p->value) {
result.insert(q->value);
q=q->next;
p=p->next;
}
q=q->next;
p=p->next;
}
return result;
}
void insert(int x) {
Node* tmp=new Node;
tmp->value=x;
if(list==NULL || list->value >x){
tmp->next=list;
list=tmp;
}
else {
Node *curr=list;
while (curr->next !=NULL && curr->next->value < x) {
curr=curr->next;
}
tmp->next=curr->next;
curr->next=tmp;
}
Note my insert function adds Nodes in ascending order, and I have tried it out and it does work on test cases, it's when i implement the union function that things go astray...

I take it that you fixed the compile error and now you are wondering why it doesn't work.
You're not merging these two lists correctly. The issues are:
You only insert an item if it's in both lists - that's intersection, not union.
You are advancing both pointers simultaneously.
You need to merge one or the other:
while ( q && p ) {
if( q->value < p->value ) {
result.insert(q->value);
q = q->next;
} else if( q->value > p->value ) {
result.insert(p->value);
p = p->next;
} else {
result.insert(q->value);
q = q->next;
p = p->next;
}
}
Now, once either of those list pointers reaches the end, you still need to add the remaining elements from the other. This will do the trick:
for(; q; q = q->next) result.insert(q->value);
for(; p; p = p->next) result.insert(p->value);
Make sure, also, that you have defined a copy constructor for List. It looks like you're doing your own memory allocation in there, so you must follow the Rule of Three.

Firstly, I am not sure what you code is intended to be doing.
It seems you expect the input to be 2 lists, which you step thru in parallel, constructing a third list if the corresponding values are matching.
This is more like an intersection than a union, tho its harsher than that, since it cares about position.
The insert seems to be a sorted insert.
Anyway, this part is certainly wrong:
if(q->value==p->value) {
result.insert(q->value);
q=q->next;
p=p->next;
}
Remove these q=q->next and p=p->next.
These are causing a double step, since its done inside the if statement, and outside.
Double stepping is bad, since it can take you past the end of a list, causing crashes.

Related

Cycle in Merge K-Sorted LinkedLists [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
My merge k-sorted lists algorithm uses divide and conquer and utilizes merge 2 lists algorithm as a helper in the process.
The issue lies is during an iteration a cycle is created and I can't figure out why.
I traced down the code to the exact place where this happen, but I am still unable to discern the issue.
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2, bool debug=false)
{
ListNode *head = new ListNode(-1);
ListNode *curr = head;
while(l1 && l2)
{
if(l1->val <= l2->val)
{
curr->next = l1;
l1 = l1->next;
}
else
{
curr->next = l2;
l2 = l2->next;
}
curr = curr->next;
}
// some list may be still populated
l1 != NULL ? curr->next = l1 : curr->next = l2;
return head->next;
}
ListNode* mergeKLists(std::vector<ListNode*>& lists)
{
// approach of divide and conquer
int size = lists.size();
int interval = 1;
int tmp_val = 1;
bool debug= false;
while(interval < size)
{
for(int i=0; i<size-interval; i*=2)
{
lists[i] = mergeTwoLists(lists[i], lists[i+interval], debug=debug);
if (i==0)
i++;
}
interval*=2;
}
if (size)
return lists[0];
else
{
ListNode* ret=NULL;
return ret;
}
}
};
For some reason this input [[-10,-9,-9,-3,-1,-1,0],[-5],[4],[-8],[],[-9,-6,-5,-4,-2,2,3],[-3,-3,-2,-1,0]]
provokes an infinite loop.
I get an infinite loop in the second list parameter to the sort 2 lists algorithm.
I believe it happens in some iteration in the lines of code:
curr->next = l2;
l2 = l2->next;
Can somebody give me any hints?
It appears that your mergeTwoLists modifies the two lists passed to it, in such a way that they can come out of it sharing nodes. This would not be a problem (at least not a big problem) if you made sure to set one of them aside and never use it again.
Clearly that's what you intend with the index-juggling in mergeKLists, but there's a bug: you increase i incorrectly. You reuse a list you shouldn't, call mergeTwoLists on two lists that share a node, it creates a loop in the list and iterates forever.
The quick-and-dirty solution is to fix the index arithmetic in mergeKLists. The deeper solution is to be more careful with the pointers in mergeTwoLists so that two lists that go in disjoint come out disjoint.

Insert in Binary Serach Tree Unhandled exception thrown [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I have a function to insert nodes in a binary search tree. I get a crash when I try to insert a node. I use the debugger from VS and it tells me Unhandled exception thrown: write access violation.
m_father was nullptr.
Here is my function to insert:
NOD *INSERT(NOD k)
{
NOD *temp = new NOD(k);
NOD *m_father = NULL;
NOD *x = root;
while (x != NULL)
{
m_father = x;
if (m_father->m_key > x->m_key)
{
x = x->m_right_child;
}
x = x->m_left_child;
}
if (root == NULL)
root = temp;
else if (temp->m_right_child->m_key > m_father->m_key)
{
m_father->m_right_child = temp;
}
m_father->m_left_child = temp;
temp->m_father = m_father;
return 0;
}
And here is how i try to insert a node:
int temp_nod;
cin >> temp_nod;
binary_tree.INSERT(temp_nod);
else if (temp->m_right_child->m_key > m_father->m_key)
temp is copy-constructed here (is it the expected behaviour?). If it's created from a new node, m_right_child might not be assigned yet, so you try to dereference a nullptr.
I'm not sure, but you did you want to check temp key here? I don't see much reason to check child key when choosing the correct place in BST.
Also, as noted in the comments, you assign m_father->left_child always, without a condition. This happens even in an empty list, so again we try to dereference a nullptr. I suppose it should look more like this:
if (root == NULL)
root = temp;
else if (temp->m_right_child->m_key > m_father->m_key)
{
m_father->m_right_child = temp;
temp->m_father = m_father;
}
else
{
m_father->m_left_child = temp;
temp->m_father = m_father;
}
As a side note, if your function does not return anything useful, just make it void.
If root == NULL the only assignment to m_father would be NOD *m_father = NULL;, before the statement m_father->m_left_child = temp;.
EDIT: (Because if root == NULL, then x would also be NULL, so the while loop would not be executed)
EDIT2: else if (temp->m_right_child->m_key > m_father->m_key) => m_father->m_left_child = temp; - the former will not be evaluated if root == NULL, since it is an else if to an if that was true.

Search function - Linked List [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am working on a search function to search a linked list for a specific value. When it finds that value I want to output its position. I cannot seem to get past the first node without getting an error. I think something is wrong with the loops but I'm not sure what.
int NumberList::search(double num)
{
ListNode *nodePtr;
nodePtr=head;
int i=0;
while (nodePtr->value!= NULL)
{
i=i+1;
if (nodePtr->value==num)
return i;
else
nodePtr=nodePtr->next;
}
return 0;
}
Your while loop is incorect. You should be testing that nodePtr is not NULL
while (nodePtr != NULL)
{
i = i + 1;
if (nodePtr->value == num)
return i;
else
nodePtr = nodePtr->next;
}
Also this is a perfect reason to use nullptr instead of NULL when dealing with pointers. If you had use nullptr then
while (nodePtr->value!= nullptr)
Would give you a compiler error as you cannot compare a double to nullptr
I do not know how the corresponding class is defined but I think in any case the function should look the following way
int NumberList::search(double num)
{
ListNode *nodePtr = head;
int i = 0;
while ( nodePtr != NULL && nodePtr->value != num )
{
++i;
nodePtr = nodePtr->next
}
return nodePtr != NULL ? ++i : 0;
}
It is difficult to compare exactly two floating numbers. You should use a method of comparison that for example takes into account an epsilon.
Take also into account that other functions as for example the function that adds nodes to the list can also be wrong.:)
Your while loop condition should be:
while (nodePtr != NULL)
Because of this error you are likely visiting a node who's pointer is NULL And by dereferencing this you are causing undefined behavior.
You don't show the ListNode type but I'm guessing the value is a double.
while (nodePtr->value != NULL)
Here you're checking if the double is not NULL (NULL is essentially 0). But you need to test nodePtr against NULL.
Note: Consider using nullptr instead of NULL, nullptr is the type safe value for a null pointer and would have produced a compilation error.
error: invalid operands of types 'double' and 'std::nullptr_t' to binary 'operator=='

Remove node at the TAIL Linked List C++ [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
All, I'm creating a function that would remove the tail from a linked list. And My function works fine for just one iteration but it doesn't for subsequent ones.
Could anybody shed some light?
Thanks
int List::removeAtTail(){
if(head == NULL)
{
cout << "Node cannot be deleted from an empty linkedList" << endl;
}
if(curr->next= NULL)
{
curr->next=curr;
}
return 0;
}
And also, if I would like to return the element that I deleted, how would I go around at doing that?
There are many ways this can be done, following is one:
int List::removeAtTail(){
while(curr != NULL) {
if(curr->next == NULL) { // depending on your implementation you might use Tail
int temp = *curr;
delete curr;
return temp;
}
curr = curr->next;
}
return 0;
}
Notice how we iterate through the list until we find the last item. At that point we store it in a temporary variable before freeing the memory. Lastly we return the value stored in the temporary variable.

LinkedList used in an interview's test

[EDIT]Fixed my code. Is while(temp != NULL), not while(temp->next != NULL). Sorry to insert wrong code.
Today I've participated an online programming test. The interviewer used Codility to evaluate my code and the other interviewees.
At some moment a question about Linked list was made. It's about to count how many items a linked list has.
I did the only possible approach to do this, AFAIK:
//This is struct declaration
struct SomeStruct
{
int value;
SomeStruct* next;
}
int elementCount(SomeStruct* list)
{
int count = 0;
if(list != NULL)
{
SomeStruct* temp = list;
while(temp != NULL)
{
count++;
temp = temp->next;
}
}
return count;
}
I remember when I send this code as answer for this question, Codility points me out that this solution is wrong because its consume too much time to execute the task.
In my head and in this thread on SO there's no other way to get size of linked list without traversing it, not in a simple way.
Is there a problem with Codility when it says this solution is wrong? Or there are another approaches?
PS: the test allowed using of STL
Your solution is incorrect, since it returns 1 less than the actual count. Just try applying it to a list with 1 element.
Why did you come up with this strange two-tiered structure with an if and and a cycle that checks temp->next? Why not just
unsigned elementCount(const SomeStruct *list)
{
unsigned count = 0;
for (const SomeStruct *temp = list; temp != NULL; temp = temp->next)
++count;
return count;
}
I suspect that you decided to treat the element pointed by the list as the unused and reserved "header" element. Indeed, sometimes it might make sense to do implement lists that way. But I see nothing like that stated in your post. Did they tell you to treat it that way specifically?
well you don't have to evaluate the indirection temp->next twice for each iteration.
you can simply do
int count( SomeStruct const* pNode )
{
int result = 0;
while( pNode != 0 )
{
++result;
pNode = pNode->next;
}
return result;
}
Also, as WhozCraig notes, your code was logically wrong (yielding an off by one result), not just potentially inefficient.
Codility may be using a circularly linked list to check, in this case, your code will never end.
Using STL trivilailzes this though, as it has a List<> with a size method.