Cycle in Merge K-Sorted LinkedLists [closed] - c++

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.

Related

Circular Doubly Linked List - Segmentation fault: 11 [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 6 years ago.
Improve this question
I'm trying to implement a circular doubly linked list but I keep getting a segmentation fault: 11 error (I believe it's because of the add and delete functions). I have no idea whether my code is even close, but I can't get past this error to test it properly. This is the code I have that I believe is involved:
(Circular_DLList.cc)
void Circular_DLList::add_to_tail(int a)
{
if (is_empty()) {
tail = new DLLNode(a);
tail->next = tail;
}
else {
tail->next = new DLLNode(a, tail->next);
}
}
int Circular_DLList::delete_from_tail()
{
if(!is_empty())
{
int a = tail->info;
tail = tail->prev;
tail->next = null;
return a;
}
else
{
tail = 0;
}
return a;
}
Any help would be fantastic, thanks.
One way to find a segmentation fault is by using cout statements throughout your code and compiling and running it. If the cout statement prints something to the console then the segmentation fault happens in a line after the cout statement. Keep doing this to narrow down and locate where the line with the segmentation fault is.
There is more than one problem in your code but here is one of them.
When you add the first element, you do:
tail = new DLLNode(a);
tail->next = tail;
so you leave prev equal to 0 (BTW: use nullptr instead of 0).
If you then delete the element you do:
int a = tail->info;
tail = tail->prev; // tail becomes 0
tail->next = null; // Dereference 0 cause seg fault
return a;
BTW: Your delete function should also delete the DLLNode ! Just changing pointer values isn't sufficient.
So this leads to 3 changes:
1) When adding new elements make sure to always set both nextand prev
2) Remember to delete the DLLNode created with new
3) In your delete function you need a special case for checking whether the list contains exactly one element, i.e. if (tail == tail->next) { .. delete last element .. set tail equal nullptr}

Union of two linked lists [closed]

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.

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.

Splitting linked list so many times puts into stack overflow c++

Oh dear; I seem to have misthought this.
I would like to split a singly-linked list 10,000 times, but evidently (and I didn't know this before you guys helped me) it causes a stack overflow.
I'm really new to this, so is there any way I could still do this and not cause a stack overflow? Using references or something?
Here's the method:
Node* Node::Split()
{
if(next == NULL)
{
return this;
}
Node *newNode = this->next;
if(this->next != NULL)
{
this->next = newNode->next;
}
if(newNode->next != NULL)
{
newNode->next = newNode->next->Split();
}
return newNode;
}
You'll have to write this as a loop rather than a recursive call. Keep track of your position in the original list, and both ends of the new lists, and append nodes alternately to each list.
Make sure your recursion does stop at some point (try a small data set). If it does then you have no problems there and the next thing to do is ask your compiler to increase the stack size for you. The default is quite small (I think it is one megabyte on vc++ 10).

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);
}