C linked list define how to reimplement a list - c

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.

Related

Creating and displaying linear linked list in C(Recursively)

I'm trying to creating linear linked list recursively with c language,
but keep sticking from here and the code is not working with the error "Linker Tools Error LNK2019". Sadly i can't understand what's the matter. Here is my code.
Thanks for your big help in advance.
#include <stdio.h>
#include <stdlib.h>
struct node
{
char num; //Data of the node
struct node *nextptr; //Address of the next node
};
typedef struct node element;
typedef element *link;
link head;
void displayList(); // function to display the list
int main()
{
char s[] = "abc";
link stol(s);
{
link head;
if (s[0] == '\0')return(NULL);
else {
head = (link)malloc(sizeof(element));
head->num = s[0];
head->nextptr = stol(s + 1);
return(head);
}
}
printf("\n\n Linked List : To create and display Singly Linked List :\n");
printf("-------------------------------------------------------------\n");
displayList();
return 0;
}
void displayList()
{
link tmp;
if (head == NULL)
{
printf(" List is empty.");
}
else
{
tmp = head;
while (tmp != NULL)
{
printf(" Data = %d\n", tmp->num); // prints the data of current node
tmp = tmp->nextptr; // advances the position of current node
}
}
}
You redefine a link object called head in your main() function. It hides the global head variable.
Removing the definition inside main would fix your problem, but you should consider passing a link* as a parameter to your displayList function in any case.
I've just noticed this statement return(head); in main(). You program exits prematurely as a result as well.
Everytime I look at your app, I find more issues. If I were you, I'd start by creating a function that adds a node to the list. It's much easier to add new nodes to the front of the list, so you should try that first. Try adding to the tail once you get this running. Adding to the tail is very similar, but you have to 'walkthe list first to get to the last element, exactly as you already do indisplayList()` Another way is keeping the address of the last node* you've added to the list. Like I said, it adds a bit of complexity, so get it working with addToHead first.
void addToHead(link* l, node* n)
{
n->nextptr = l->nextptr;
l->nextptr = n;
}
in your main, you can allocate one new node at a time, as you already do with malloc(). Initialize its contents num with an integer, and let addToHead deal with the pointer stuff. Your use of pointers is terrible, but lists are quite easy, and addToList pretty much shows what can and what should be put in pointers - namely other pointers.
You can remove almost everything in main() before the first printf. You'll have to
start loop:
write a prompt so the user knows what to do using printf()
read input from user using scanf("%d", &n), or equivalent.
break from the loop if user enters a negative value.
malloc() a new node
set its data num = n
call addToHead to add the node.
Loop until user enters an empty string, or -1.
That should take about 8 to 10 lines of code. if in doubt, you will easily find documentation on scanf, with google or on http://en.cppreference.com/w/c.

Deleting Linked LIst in C

I just stuck with the problem couple of hours, trying to find where my code breaks. I know how to delete linked list but something doesn't work.
First it is a very simple struct with a dataype of int and 2 struct *next and *prev.
struct _list_{
struct _list_ *next;
struct _list_ *prev;
float distance;
}
Now i am making a push_front function and it works great. I get the result that i am looking for. But now i am making pop_front function and something is missing.
The function should return the distance and then remove that list from the linked list but i can't make it do it.
here is the code that i wrote
int pop_front(list** header)
{
float number = (*header)->data;
list *head = *header;
list *remove = head;
// This should check if the pointer is pointing at the first element
while (head->prev != NULL) {
head = head->prev;
}
if (head) {
head = head->next;
free(remove);
remove = head;
remove->prev = NULL;
//if i remove the code below then i get this error
//*** Error in `./double_ended_queue.out': double free or
//corruption (fasttop): 0x0000000001d5a050 ***
//Pop up: 3 pointer: 3 Aborted (core dumped)
*header = *remove;
//And with this code i get a Segmentation fault (core dumped
return number;
}
return 0;
}
Any help would be great, thank you.
P.S. checked all the linked list question here and none helped.
Where are you all getting this homework from? The API sux. Here, someone else did have almost the same homework (link pointing to my answer, which has many issues left): Pointer Dequeue - pointer training
Anyways:
Do you want to return int or float? The element data is type float, your variable "number" too, but your function returns int.
int pop_front(list** header)
{
float number = (*header)->data;
so, here you get the value of the element you're trying to remove, but then ...
list *head = *header;
list *remove = head;
// This should check if the pointer is pointing at the first element
while (head->prev != NULL) {
head = head->prev;
}
... you actually SEARCH for the element to remove.
Obviously, you have to do it the other way round:
int pop_front(list** header)
{
list * head = *header;
while (head->prev) head = head->prev;
now, you should check, weather you need to adjust the *header pointer (and do it right away):
if (*header == head) {
*header = head->next;
}
the only thing to do now is to remove the object from the list, get it's value and free it's memory before return.
head->next->prev = NULL;
float retval = head->data;
free(head);
return retval;
}
As exercise left to you: Make sure, that an empty list doesn't crash ;)
/edit: This will also crash for removal of the last element, so you have two exercises left ;)

Swapping 2 Nodes in a Linked List

Good day guys, im new here to C and am trying to learn linked lists. I been trying to swap 2 nodes from within a linked list but so far have been having trouble getting it to work. The code I been trying to use causes an endless circular loop, but I don't think it is because of the if or while statement.
Take a look? Any pointers here? Help would be greatly appreciated.
Basically, the code uses a user input to search for a node based on the data inside, then it should swap the node with the data inside with the next node. Been at this for 3 hours, can anybody help? Thanks!
/conductor is the name im using of the pointer for the current node/
#include <stdio.h>
#include <stdlib.h>
struct node {
int x;
struct node *next;
struct node *prev;
};
struct node *root;
struct node *conductor;
struct node *counter;
struct node *newnode;
struct node *back;
struct node *swapper;
struct node *swappee;
struct node *blanker;
int add = 0;
int initialization = 0;
int query = 0;
int swap ()
{
printf("enter data to search from within the nodes: ");
fflush(stdin);
scanf("%d", &query);
conductor = root;
while ( conductor->next != 0)
{
if(conductor->x == query)
{
printf("\n%d\n", query);
swapper = conductor;
swappee = conductor->prev;
conductor = swappee;
conductor->next = swapper;
break;
}
else
{
conductor = conductor->next;
}
}
mainMenu ();
}
A double linked list (like the one you have) is basically an array of node, each node pointing to its neighbors. Let's say we have nodes -A-B-C-D- (A-B means that A points to B and B points to A). Let's say you want to swap B and C. You have to make 4 changes:
Make A point to C
Make C point to B and A
Make B point to D and B
make D point to B
You make only the second and the third change. So, you need to add A->next = B and D->prev=C. I hope it is clear enough.
Also, you should not fflush input streams.
If you want to swap the data:
if (conductor->x == query) {
int temp = conductor->x;
if (conductor->next)
conductor->x = conductor->next->x;
conductor->next->x = temp;
}
}
Typically that is what you will want to do. If you have a structure with several members instead of the 1 int, swapping the pointers may seem less messy in theory, but it isn't, primarily due to the fact that you must test for existence of a next/previous node so often. In truth, you'd probably want a pointer to a separate structure in such a case.
Given three nodes — previous, current, and next, pointing to current->prev, current, and current->next respectively — you must update at most 6 pointers:
next->prev = previous
previous->next = next
current->prev = next
current->next = next->next
next->next = current
current->next->prev = current
Step 2 is not necessary if previous is NULL.
Step 7 is unnecessary if current->next is NULL.
The entire thing is unnecessary if next is NULL.
If you want to swap with the previous node instead of the next, exchange any instance of the variable previous with the variable next and vice-versa as well as exchanging any instance of ->prev with ->next and vice-versa.
Overall, this requires a fair bit of branching code, which can be slow. This is why it is usually better to swap the data rather than messing with the pointers. It gets even messier when you want to swap with the previous node and you only have a singly-linked list that points to the next node because you must store yet another pointer for the equivalent of previous->prev, assuming previous exists.

C - Linked Lists

I am trying to understand the code of linked lists. I understand how they work.
I am looking at some code to do with dynamic memory and linked lists, I have simplified it here:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
char *word;
struct node *next;
} node;
void display_word(node *start) {
node *start_node = start;
puts("");
for(; start_node != NULL; start_node = start_node->next) {
printf("%s", start_node->word);
}
}
node* create_node(char *input) {
node *n = malloc(sizeof(node));;
n->word = strdup(input);
n->next = NULL;
return n;
}
int main() {
node *start_node = NULL;
node *n = NULL;
node *next_node = NULL;
char word_holder[20];
for(; fgets(word_holder,80,stdin) != NULL; n = next_node) {
next_node = create_node(word_holder);
if(start_node == NULL)
start_node = next_node;
if(n != NULL)
n->next = next_node;
}
display_word(start);
}
So the program creates a linked list of each word the user enters and then it prints it out.
What I dont understand is in the main() function where next_node is assigned to a new node everytime to create a new one, but start_node points to next_node, so it will point to every new node that next_node creates each time? So how is it possible to still keep the list? Shouldn't we lose the old node each time?
Can someone explain please.
When the first node is created, a pointer to it is saved in start.
When subsequent nodes are created, they are added at the end of the list, so start still points to the first node, and through it, the rest of the list.
Step through the code with a debugger, or get out a pencil and paper and draw what's happening as you step through in your brain, and you'll see how it all gets put together.
When the first node is created, a pointer to it is saved in start.
After every iteration of the loop, "n" is set to the node just created, because the last piece of the for loop (;n = next) is executed after every iteration of the loop. So mid loop execution "n" will always be pointing to the previous node. Therefore the statement n->next = next is setting the previous node's "next" pointer to the new node.
So during the second iteration of the loop, n = start, and start->next is set to "next" the node you just created.
I hope this answers your question - every time you are updating "next", you're setting that to be yet another new node. Each node has their own "next" that leads to the next node, so you aren't going to lose anything by doing it this way. I didn't actually test your code but since "Start" points to the first node always, you aren't going to lose any nodes along the way. A debugger should help if you're curious to learn more about how this works!

Single Linked List - Delete From middle

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

Resources