I'm trying to find the middle element of a linked List, but I'm getting a segmentation fault, and I'm not sure what is going wrong. This is my implementation of the hare rabbit algorithm:
//fast slow pointer method
void ptMiddle(struct node **head_ref)
{
struct node *fast = (*head_ref);
struct node *slow = (*head_ref);
fast = fast->next;
while(fast!=NULL)
{
// printf("%d%d",slow->data,fast->data);
slow = slow->next;
fast = fast->next->next;
}
printf("Middle elemnet is:%d\n",slow->data);
}
int main()
{
struct node * head=NULL;
push(&head,1);
push(&head,2);
push(&head,3);
push(&head,4);
printList(&head);
printf("M:%d\n",middleNode(&head)->data);
printf("here");
append(&head,5);
append(&head,6);
printList(&head);
printf("M:%d\n",middleNode(&head)->data);
printf("here");
ptMiddle(&head);
return 0;
}
Please help out.
Your problem is in the line:
fast = fast->next->next;
Imagine you have two elements in the linked list: A -> B -> NULL, first you start by executing fast = fast->next, which results in fast pointing to B node.
When you enter the while loop, you try to get B->next->next, which results in NULL->next, which clearly doesn't exist.
The implementation is plain wrong, you should make sure to avoid this case. The while could be changed to:
while(fast!=NULL && fast->next != NULL)
and this would fix it.
Keep in mind that in case of a pair number of elements, you'll always get the middle one which is more left. So in A -> B -> NULL you'd get node A.
Related
Hi this is probably a stupid question to ask with a simple solution but I just can't find an answer in the internet.
So I was exercising for an exam and worked on an assignment. The program has the job to find out what the value in the center of a linked list is (if the length of the list is an odd number)
The structdef is:
typedef struct IntList IntList;
struct IntList {
int value;
IntList* next;
};
and my exact problem right now is that I get a segmentation fault when I try using:
list = list->next;
I want to go step by step in a loop to go to the wished list at the nth position (the center) of the linked list.
Someone knows how I have to rewrite this? If you need more Information to help just say so and I will explain more.
With that function I check the length of the list and in my other function I have a loop which only goes to the mid of the length.
int length_list(IntList* list) {
int n = 0;
for(IntList* node = list; node != NULL; node = node->next) n++;
return n;
}
After this loop ends for(IntList* node = list; node != NULL; node = node->next) n++; you surely have node==NULL.
That is not immediatly a problem.
But depending on what you do with the value of n which you return you might have an off-by-one problem. E.g. in a list with exactly one entry (1 is odd after all), the attempt to use a value which is 1 too high could result in an attempt to access a non-existing node.
Because of this I suspect that your problem might be solved by changing the loop to
for(IntList* node = list; node->next != NULL; node = node->next) n++;, so that it ends on the last existing node, instead of behind. The return value will be lower, whatever you do with it will be "more-careful".
That or try something similar with the small code fragment you show and ask about, list = list->next; only do that if the next is not NULL, not if only list is not NULL.
I am working on a Graph problem, so my program has an initialization which sets all connection using an adjacencyList. Currently encountering a really weird bug and was wondering if anyone could give some insights as to what may be happening.
So I have a function that sets a connection
void setConnection(Graph g, int sVertex, int eVertex){
ListNode *newNode = (ListNode *) malloc(sizeof(ListNode*));
newNode->vertex = eVertex;
ListNode *temp = g.list[sVertex-1];
if (temp == NULL){ // Corresponding list is empty
newNode->next = NULL;
g.list[sVertex-1] = newNode;
}
else{ // Insert new node to the front
newNode->next = temp; // set newNode's next to current 'head'
g.list[sVertex-1] = newNode; // Replace head as newNode
}
//printf("Connection set from %d to %d\n", sVertex, g.list[sVertex-1]->vertex);
return;
}
After initialization, I usually attempt to print out the adjacencyList to check if the logic is correct. The function is as follow:
void printGraphList(Graph g){
int i;
ListNode* temp;
for(i=0;i<g.V;i++)
{
printf("|");
printf("%d:\t",i+1);
temp = g.list[i];
while(temp != NULL){
printf("%d -> ",temp->vertex);
temp = temp->next;
}
printf("\n");
}
}
So here's the weird part, the code works fine most of the time, but occasionally crashes randomly when printing the adjancencyList. I debugged it down to
printf("%d -> ", temp->vertex);
For some reason, there are cases where the first node inserted does not have its ->next set to NULL properly. hence in the list traversal, it does not exit properly, and as such the temp->vertex is unobtainable, therefore causing the crash.
I have also debugged setConnection to ensure the links are properly set, like the actual pointer values themselves T.T
Below is an example of a working run, and a problem run. I printed an & before printing the vertex and and # after. As shown in the image, for vertex 7, it should be linked to only vertex 9 and 10, but in the problem run, it looks like the node for 9's next is not set to NULL properly, causing the program to crash in attempt to get node 9's->next->vertex as it does not exist...
As mentioned before, this happens once every 3 to 4 runs and i have no clue whats causing this inconsistency. Any help is appreciated! Thanks in advance.
Problem Example
Working Example
I am understanding recursion and so I tried writing reverse a linked list program. I have written the below function but it says segmentation error (core dumped).
void reverse(){
if (head -> next == NULL){
return;
}
reverse (head -> next);
struct node *q = (struct node*) malloc (sizeof(struct node));
q = head -> next;
q -> next = head;
head -> next = NULL;
}
Please can someone guide me. Thank you.
Shouldn't reverse take an argument? And please be aware that you cannot change a pointer in a function and have that be a lasting change. That is, in a C function, the only lasting changes are those that use *var = something.
Recursion is a way of thinking that's gained by practice. So congratulations on your attempt. It's not correct, but don't be discouraged.
Here are two ways to go about the problem.
Your goal is to subdivide it into a smaller version of itself plus a (hopefully easy and fast to compute) incremental step that takes a solution to the smaller version to a complete solution. This is the essence of recursive thinking.
First try: Think of the list as a head element plus the "rest of the list." I.e.,
L = empty or
= h . R
where h is the head element R is the rest of the list, and dot . is joining a new element to the list. Reversing this list consists of reversing R, then appending h on the end:
rev(L) = empty if L is empty
= rev(R) . h otherwise
This is a recursive solution because we can call the reverse function recursively to solve the slightly smaller problem of reversing R, then add a little work to append h, and that gives us the complete solution.
The problem with this formulation is that appending h is more expensive than you'd like. Since we have a singly linked list with only a head pointer, it's time consuming: traverse the whole list. But it will work fine. In C it would be:
NODE *rev(NODE *head) {
return head ? append(head, rev(head->next)) : NULL;
}
NODE *append(NODE *node, NODE *lst) {
node->next = NULL;
if (lst) {
NODE *p;
for (p = lst; p->next; p = p->next) /* skip */ ;
p->next = node;
return lst;
}
return node;
}
So how to get rid of the bad performance? It's frequently the case that different recursive formulations of a problem have different efficiencies. So some trial and error is often involved.
Next try: Think about the computation in terms of dividing the list into two sublists: L = H T, so rev(L) = rev(T) + rev(H). Here plus + is list concatenation. The key is that if I know rev(H) and want to add a new element at its head, the element to add is the first element in T. If this seems fuzzy, let H = [a, b, c] and T = [d, e]. Then if I already know rev(H) = [c, b, a] and want to prepend the next element at the head, I want d, which is the first element of T. In our little notation, you can write this observation just so:
rev(H + (d . T)) = rev(T) + ( d . rev(H) )
So this looks very good. In both cases (getting the head of T and moving it to the head of rev(H)), I'm only interested in the head of the list, which is very efficient to access.
Of course if T is empty, then rev(H) = rev(L). This is the answer!
Writing this as recursive procedure.
NODE *rev(NODE *t, NODE *rev_h) {
if (t) { // if t has some elements
NODE *tail = t->next; // save the tail of T
t->next = rev_h; // prepend the head to rev(H)
return rev(tail, t); // recur to solve the rest of the problem
}
return rev_h; // otherwise T is empty, so the answer is rev(H)
}
At the start, we don't know anything at all about rev(H), so T is the whole list:
NODE *reversed_list = rev(list, NULL);
The next thing to note is that this function is tail recursive: the recursive call is executed just before the function returns. This is good! It means we can easily rewrite it as a loop:
NODE *rev(NODE *t, NODE *rev_h) {
recur:
if (t) { // if t has some elements
NODE *tail = t->next; // save the tail of T
t->next = rev_h; // prepend the head to rev(H)
rev_h = t; // "simulate" the recursive call
t = tail; // by setting both args
goto recur; // and going back to the start
}
return rev_h; // otherwise T is empty, so the answer is rev(H)
}
You can always do this transformation with tail-recursive calls. You should think hard about why this works.
Now the goto is easily rewritten as a while loop, and we can make rev_h a local variable initialized to NULL, since that's all the initial call does:
NODE *rev(NODE *t) {
NODE *rev_h = NULL;
while (t) { // while t has some elements
NODE *tail = t->next; // save the tail of T
t->next = rev_h; // prepend the head to rev(H)
rev_h = t; // "simulate" the recursive call
t = tail; // by setting both args
}
return rev_h; // otherwise T is empty, so the answer is rev(H)
}
An in-place linked list reverser that needs only a small constant amount of space!
And look! We never had to draw funny box and arrow diagrams or think about pointers. It "just happened" by careful reasoning about how to subdivide the problem into smaller instances of itself, the essence of recursion. It's also a nice way to see that loops are just a special kind of recursion. Cool, no?
I am assuming that you have something like the followings predefined in your .c file
typedef struct node node_t;
struct node {
int some_data;
node_t *next;
};
/* Your linked list here */
typedef struct {
node_t *head;
node_t *foot; /* to keep track of the last element */
} list_t;
In your function, there are a few mistakes you made
not providing any input arguments
access head->next when the program has no idea where to find head
Hence, resulting in the most frustrating error in C -- segmentation fault!
Instead, you should try the following:
void reverse(list_t *mylinkedlist){
if (mylinkedlist->head->next == NULL) {
return;
}
/* do something */
}
I was trying to reverse a linked list, however whenever I execute the following function, I get only the last element. For example, if the list contained 11,12,13 earlier. After executing the function, it contains only 13. Kindly point out the bug in my code
void reverselist() {
struct node *a, *b, *c;
a = NULL;
b = c = start;
while (c != NULL) {
c = b->next;
b->next = a;
a = b;
b = c;
}
start = c;
}
Doesn't your loop guard insure that start is null?
If you aren't using start to identify the first element of the list, then the variable you ARE using is still pointing to what WAS the first element, which is now the last.
c is a helper pointer.
void reverselist()
{
struct node *a, *b, *c;
a=NULL;
b=start;
while(b!=NULL)
{
c=b->next
b->next=a;
a=b
b=c
}
start=a;
}
// You should assume that Node has a Node* called next that
// points to the next item in a list
// Returns the head of the reversed list if successful, else NULL / 0
Node *reverse( Node *head )
{
Node *prev = NULL;
while( head != NULL )
{
// Save next since we will destroy it
Node *next = head->next;
// next and previous are now reversed
head->next = prev;
// Advance through the list
prev = head;
head = next;
}
return previous;
}
I would have made a prepend function, and done the following:
struct node* prepend(struct node* root, int value)
{
struct node* new_root = malloc(sizeof(struct node));
new_root->next = root;
return new_root;
}
struct node* reverselist(struct node* inlist)
{
struct node* outlist = NULL;
while(inlist != NULL) {
struct node* new_root = prepend(outlist, inlist->value);
outlist = new_root;
inlist = inlist->next;
}
return outlist;
}
Have not tested this, but guess you grasp the idea of it. Might be just your variable names, which don't describe anything, but I think this approach is cleaner, and easier to understand what actually happens.
EDIT:
Got a question why I don't do it inplace, so I'll answer it here:
Can you do it inplace? Are you sure you don't wish to keep the
original list?
Do you need to do it inplace? Is the malloc to time consuming/is this a performance critical part of your code? Remember: premature optimization is the root of all evil.
Thing is, this is a first implementation. It should work, and not be optimized. It should also have a test written before this implementation is even thought of, and you should keep this slow, un-optimized implementation until the test passes, and you have proved that it's to slow for your use!
When you have a passing unit test, and proven the implementation to be to slow, you should optimize the code, and make sure it still passes the test, without changing the test.
Also, is it necessary inplace operations which is the answer? What about allocating the memory before reverting it, this way you only have one allocation call, and should hopefully get a nice performance boost.
This way everyone is happy, you have a cleaner code and avoid the risk of having Uncle Bob showing up at your door with a shotgun.
I am trying to figure out an algorithm to delete from the middle of a linked list..
My idea is to traverse the list, find the node right before the node I want to delete, call it Nprev, and set Nprev to Nnext where Nnext is after the node to delete Ndelete.
So Nprev -> Ndelte -> Nnext.
My problem is that I cannot figure out how to traverse this list to find the node before the one I want.
I've been doing this with seg faults because I assign pointers out of range I assume.
Its a very messy algorithm that I have, with many if else statements..
Is there an easier way to do this?
Basically I need to go through the list, apply a function to each node to test if
it is true or false. If false I delete the node.
Deleting first and last is not as hard but middle stumped me.
Please let me know if there are some general ways to solve this problem. I've
been scouring the internet and found nothing I need.
I used this: http://www.cs.bu.edu/teaching/c/linked-list/delete/
but the algorithm before step 4 only deletes the first node in my list
and doesn't do any more.
How can I modify this?
They also give a recursive example but I don't understand it and am intimidated by it.
First you need to find the middle node.
Well take 3 pointers fast, slow, prev
with fast moving with twice the speed of slow and prev storing the address of the node previous of slow.
i.e.
*slow=&head,*fast=&head,prev=Null
traverse the list and when fast=NULL
slow will point to the middle node if number of elements are odd and prev will store the address of node previous of the mid node.
so simply
prev->next=slow->next.
Here an example of something I use to search and remove by index:
Given this struct: (Can also be adapted to other self referencing structs)
struct node
{
S s;
int num;
char string[10];
struct node *ptr;
};
typedef struct node NODE;
Use this to remove an item from somewhere in the "middle" of the list (by index)
int remove_by_index(NODE **head, int n) /// tested, works
{
int i = 0;
int retval = -1;
NODE * current = *head;
NODE * temp_node = NULL;
if (n == 0) {
return pop(head);
}
for (int i = 0; i < n-1; i++) {
if (current->ptr == NULL) {
return -1;
}
current = current->ptr;
}
temp_node = current->ptr;
retval = temp_node->num;
current->ptr = temp_node->ptr;
free(temp_node);
return retval;
}