Simple linked list with random values - c

Okay so here's the task: Implement a list with 25 ordered random integers between 0 and 100.
My approach: get 25 numbers in an array, order the array and create the list with the array elements.
#include <conio.h>
#include <malloc.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
struct Node{
int data;
struct Node *next;
};
int main()
{
struct Node *p=NULL;
struct Node *q=NULL;
int j,i,aux,n,v[25];
for (i=0;i<25;i++)
{
v[i]=rand()%100;
}
for (i=0;i<25;i++)
{
for (j=1;j<25;j++)
{
if (v[i]>v[j])
{
aux=v[i];
v[i]=v[j];
v[j]=v[i];
}
}
}
q=(Node *)malloc(sizeof(struct Node));
q->data=v[0];
q->next=NULL;
for (i=1;i<25;i++)
{
p=(Node *)malloc(sizeof(struct Node));
q->next=p;
p->data=v[i];
p->next=NULL;
q=p;
}
while (p)
{
printf("%d ",p->data);
p=p->next;
}
}
Output: 0.
Can you guys figure out what I did wrong ?

There's a number of things wrong... but the primary one (that's causing all 0's) is here:
if (v[i]>v[j])
{
aux=v[i];
v[i]=v[j];
v[j]=v[i];
}
Your swap is incorrect, you store v[i]'s data in aux, but you never set it to v[j], so you're just overwriting everything with the smallest value (0)
You wanted:
v[j] = aux;
The other major issue is you're not keeping track of the "head" of your list:
p=(struct Node *)malloc(sizeof(struct Node));
q->next=p;
p->data=v[i];
p->next=NULL;
q=p;
You keep assigning a new value to p, then overwritting q with p... so there's no way to find your way back. You'll only have the last value in your linked list
Something like:
struct Node* head = NULL;
...
head = q=(Node *)malloc(sizeof(struct Node)); // head points to the first node now
Then later:
p = head; // reset p to the start of the list.
while (p)
{
...

You don't need to set up all this array stuff; the fragment below returns a linked list of N=cnt Nodes with random payload:
struct Node *getnrandom(unsigned cnt) {
struct Node *p=NULL, **pp;
for (pp=&p; cnt--; pp = &(*pp)->next) {
*pp = malloc (sizeof **pp);
if (!*pp) break;
(*pp)->data = rand();
}
if (*pp) (*pp)->next = NULL;
return p;
}
UPDATE: since the OP appears to need the values to be ordered, he could either perform insertion (at the right position) into the llist (N*N) , or sort it post hoc. (NlogN)

Related

Linked List insertion in Beginning

I am trying basic creation of linked list using C. I have written the following code which is working up until first node but fails eventually on second one. I think the issue is where I am trying to display the node values in list separated by arrow(->). I think my logic is right but please correct me. Thanks in advance
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
struct node
{
int number;
struct node *next;
};
typedef struct node NODE;
NODE *node1, *node2, *start, *save;
int main()
{
node1 = (NODE *)malloc(sizeof(NODE));
int i = 0;
start = NULL;
for(i = 0; i < 3; i++)
{
int inf;
printf("Enter node value:");
scanf("%d", &inf);
node1->number = inf;
node1->next = NULL;
if(start == NULL)
{
start = node1;
save = node1;
}
else
{
// save=start;
// start=node1;
// node1->next=save;
node1->next = start;
start = node1;
}
while(node1 != NULL)
{
printf("%d ->",node1->number);
node1 = node1->next;
}
}
return 0;
}
The issues are
How you're allocating your nodes for insertion (i.e. save for one, you're not).
How they're placed in the list once you fix the above.
Don't cast malloc in C programs (read here for why).
Fail to check the success of your scanf invoke.
Fail to check the success of your malloc invoke
Before you get discouraged, things you did correctly:
Did not mask a node pointer in a typedef
Properly included a MCVE for review
Prospected the things you may be doing wrong.
A very simple example of iterating three values into a linked list would look something like this:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int number;
struct node *next;
};
typedef struct node NODE;
int main()
{
NODE *head = NULL, *p;
int i = 0;
for(i = 0; i < 3; i++)
{
int inf;
printf("Enter node value:");
if (scanf("%d", &inf) == 1)
{
p = malloc(sizeof *p);
if (p != NULL)
{
p->number = inf;
p->next = head;
head = p;
}
else
{
perror("Failed to allocate new node");
return EXIT_FAILURE;
}
}
else
{
// failed to read data. break
break;
}
// report current linked list
printf("%d", p->number);
for (p=p->next; p; p = p->next)
printf(" -> %d", p->number);
fputc('\n', stdout);
}
// cleanup the linked list
while (head)
{
p = head;
head = head->next;
free(p);
}
head = NULL;
return 0;
}
Input
The values 1 2 3 are input upon being prompted:
Output
Enter node value:1
1
Enter node value:2
2 -> 1
Enter node value:3
3 -> 2 -> 1
Best of luck.
You should use malloc() inside for loop.
Since it is outside, same memory is being used.
As said by Vamsi, you should use malloc to put the nodes on the heap. You also generally shouldn't cast the output of malloc, it isn't needed. And then you could play around with making a doubly-linked list, where you also have a prev pointer inside your struct.

Making of linked list by head and node

here's my code in C for making of linked list. Its giving runtime error after the while loop gets executed for one time. Plz help me in correcting my code. (totally confused that where's the error.) I am making a head node first and then adding child nodes to it.
#include <stdio.h>
#include <stdlib.h>
typedef struct node nd;
typedef nd *link;
struct node{
int data;
link next;
};
typedef struct {
int size;
link head;
}list;
void create(link temp)
{
link new;
new=(link)malloc(sizeof(nd));
printf("enter data: ");
scanf("%d",new->data);
temp->next=new;
temp=temp->next;
}
list createlist()
{
list sl;
sl.size=0;
sl.head=0;
return sl;
}
int main()
{
list sl;
sl=createlist();
link temp;
temp=sl.head;
char c;
while (1)
{
printf("Add node?: ");
scanf(" %c",&c);
if (c=='y')
{
create(temp);
sl.size++;
}
else
break;
}
return 0;
}
your createlist() function is returning a reference to a local variable that goes out of scope after it returns. You should instead return a heap based value:
list* createlist() {
list* sl = (list*)malloc(sizeof(list));
sl->size=0;
sl->head=0;
return sl;
}
Initially temp points to NULL. temp = sl.head;
In create(temp) temp->next = new;
You are dereferencing a NULL, address 0x0. I get a segmentation fault when I do that.
Need to change the algorithm.
A debugger shows this problem immediately.
You could use a pointer to pointer for temp. It would be easier to read if you didn't use a typedef for a pointer to node. I haven't tested this, but it should be close:
nd ** create(nd **temp)
{
nd *new;
new=(nd *)malloc(sizeof(nd)); /* this cast shouldn't be needed */
printf("enter data: ");
scanf("%d",&(new->data));
new->next = NULL;
*temp = new;
return &(new->next);
}
/* ... */
int main()
{
nd **temp;
temp = &(sl.head);
/* ... */
temp = create(temp);
/* ... */
}

Struct and Pointers

So in my code I have two structures. The first is a node which contains an int value and a pointer to another node. The second structure is used to create an array of 10 pointers each point to a another node. And it also contains link2 which will be used to traverse the array and all the nodes that it points to. I'm trying to add 3 nodes each holds the value 3 into the third index of the array. The pointer in the third index should point to the first 3 then that should point to the second three and so on. When I put add(a,3) three times and then print i get segmentation fault. I tried tracing the code but that still didn't make any sense to me because I always end up with three nodes. Can someone point me in some direction? Thanks!:)/>
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
struct node
{
int x;
struct node *link;
};
struct listofnodes
{
struct node *alist[10];
struct node *link2;
};
addFirst(struct listofnodes *a, int num)
{
struct node *nodeone = (struct node *)malloc(sizeof(struct node));
nodeone->x = num;
a->alist[num] = nodeone;
// printf("IT WENT THROUGH\n");
}
add(struct listofnodes *a, int num)
{
struct node *current;
current = a->alist[3];
struct node *nodeone = (struct node *)malloc(sizeof(struct node));
nodeone->x = num;
current->x = 5;
{
while (a->alist[3] != NULL)
{
if (a->alist[3]->link == NULL)
{
a->alist[3]->link = nodeone;
printf("IT WENT THROUGH\n");
break;
}
a->alist[3] = a->alist[3]->link;
}
}
}
main(void)
{
struct listofnodes *a =
(struct listofnodes *)malloc(sizeof(struct listofnodes));
// a->alist[3]=NULL;
addFirst(a, 3);
add(a, 3);
add(a, 3);
add(a, 5);
}
In your main() function you have:
struct listofnodes *a =
(struct listofnodes *)malloc(sizeof(struct listofnodes));
"a" is now a pointer to a listofnodes-sized block of memory containing random locations. You probably want to do something like
a->link2 = NULL;
Also, in your add() function, you have...
add(struct listofnodes *a, int num)
{
struct node *current;
current = a->alist[3];
struct node *nodeone = (struct node *)malloc(sizeof(struct node));
nodeone->x = num;
You have malloc()d random memory and put "num" into x, but you need to put a null into where 'link' goes, i.e.
nodeone->link = NULL;
When you create the memory block using malloc(), you have to manually make sure the 'link' member is set to NULL - otherwise the number left there from last use will point who knows where...

Linked list in C - first node data incorrect and can't figure it out

I have a multithreaded C program, where one thread creates random times and numbers, and stores them in a sorted linked list, and the second thread compares the the time in the first node to the current system time and deletes the node whenever the times are equal. However, 0 0 gets added to the linked list first, and I can't find where. It's not being added in the insert function as far as I can tell. Any help would be greatly appreciated. Here is the relevant code:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <signal.h>
pthread_mutex_t count_mutex;
/* Link list node */
struct node
{
int roomNo;
time_t time;
struct node* next;
};
void printList(struct node *node)
{
while(node!=NULL)
{
printf("%d ", node->roomNo);
printf("%d\n ", node->time);
node = node->next;
}
}
/* Function to insert a node at the beginging of the linked list */
void insert(struct node** head_ref, int new_room, time_t new_time)
{
/* allocate node */
struct node* new_node =
(struct node*) malloc(sizeof(struct node));
/* put in the data */
new_node->roomNo = new_room;
new_node->time = new_time;
/* link the old list off the new node */
new_node->next = (*head_ref);
/* move the head to point to the new node */
(*head_ref) = new_node;
MergeSort(&(*head_ref));
}
/* sorts the linked list by changing next pointers (not data) */
void MergeSort(struct node** headRef)
{
struct node* head = *headRef;
struct node* a;
struct node* b;
/* Base case -- length 0 or 1 */
if ((head == NULL) || (head->next == NULL))
{
return;
}
/* Split head into 'a' and 'b' sublists */
FrontBackSplit(head, &a, &b);
/* Recursively sort the sublists */
MergeSort(&a);
MergeSort(&b);
/* answer = merge the two sorted lists together */
*headRef = SortedMerge(a, b);
}
struct node* SortedMerge(struct node* a, struct node* b)
{
struct node* result = NULL;
/* Base cases */
if (a == NULL)
return(b);
else if (b==NULL)
return(a);
/* Pick either a or b, and recur */
if (a->time <= b->time)
{
result = a;
result->next = SortedMerge(a->next, b);
}
else
{
result = b;
result->next = SortedMerge(a, b->next);
}
return(result);
}
void FrontBackSplit(struct node* source,
struct node** frontRef, struct node** backRef)
{
struct node* fast;
struct node* slow;
if (source==NULL || source->next==NULL)
{
/* length < 2 cases */
*frontRef = source;
*backRef = NULL;
}
else
{
slow = source;
fast = source->next;
/* Advance 'fast' two nodes, and advance 'slow' one node */
while (fast != NULL)
{
fast = fast->next;
if (fast != NULL)
{
slow = slow->next;
fast = fast->next;
}
}
/* 'slow' is before the midpoint in the list, so split it in two
at that point. */
*frontRef = source;
*backRef = slow->next;
slow->next = NULL;
}
}
void * addThread(void *n)
{
struct node *llnode = n;
int i;
for(i = 0; i <4; i++)
{
pthread_mutex_lock(&count_mutex);
printf("Adding node.\n");
insert(&llnode, getRandRoom(), getRandTime());
sleep(1);
printf("the list is...\n");
printList(llnode);
pthread_mutex_unlock(&count_mutex);
}
}
struct node* head;
int main()
{
signal(SIGINT, ctrlc_catch);
pthread_t addWakeup, makeWakeup;
pthread_create(&addWakeup, NULL, addThread, (void*)&head);
pthread_create(&makeWakeup, NULL, wakeThread, (void*)&head);
pthread_join(addWakeup, NULL);
pthread_join(makeWakeup, NULL);
return 0;
}
Example output is:
Adding node.
the list is...
0 0
4000 1323882918
Adding node.
the list is...
0 0
809 1323882890
4000 1323882918
Adding node.
the list is...
0 0
809 1323882890
7617 1323882908
4000 1323882918
Adding node.
the list is...
0 0
809 1323882890
7617 1323882908
4000 1323882918
4426 1323882926
You problem is most likely due to passing address of head (i.e. ~struct node**) instead of head(i.e. struct node*) to the thread function where void * is typecast to struct node*. Change this call pthread_create(&addWakeup, NULL, addThread, (void*)&head); to pthread_create(&addWakeup, NULL, addThread, (void*)head); & next call also on similar lines. Unfortunately you were not seeing a crash in the current case. On my system I observed that initializing head to NULL was crashing the program. Similar suggestion has already been provided by #wildplasser. Try this change out and check the list printed.
Hope this helps!
Your function addthread creates a local copy llnode of its argument n, and uses a pointer to llnode to call insert(). Insert can alter llnode, but that change will only affect the local copy.
You should change addThread to take an argument of type struct node**, instead of struct node*.
While it may exist in code not shown, the code may need a call to pthread_mutex_init to initialize the mutex. It is possible that the contents of the variable count_mutex are initialized "by chance" to values that will actually work, but it would not be good to rely on that.

How to implement a linked list in C?

I am creating a linked list as in the previous question I asked. I have found that the best way to develop the linked list is to have the head and tail in another structure. My products struct will be nested inside this structure. And I should be passing the list to the function for adding and deleting. I find this concept confusing.
I have implemented the initialize, add, and clean_up. However, I am not sure that I have done that correctly.
When I add a product to the list I declare some memory using calloc. But I am thinking shouldn't I be declaring the memory for the product instead. I am really confused about this adding.
Many thanks for any suggestions,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PRODUCT_NAME_LEN 128
typedef struct product_data
{
int product_code;
char product_name[PRODUCT_NAME_LEN];
int product_cost;
struct product_data_t *next;
}product_data_t;
typedef struct list
{
product_data_t *head;
product_data_t *tail;
}list_t;
void add(list_t *list, int code, char name[], int cost);
void initialize(list_t *list);
void clean_up(list_t *list);
int main(void)
{
list_t *list = NULL;
initialize(list);
add(list, 10, "Dell Inspiron", 1500);
clean_up(list);
getchar();
return 0;
}
void add(list_t *list, int code, char name[], int cost)
{
// Allocate memory for the new product
list = calloc(1, sizeof(list_t));
if(!list)
{
fprintf(stderr, "Cannot allocated memory");
exit(1);
}
if(list)
{
// First item to add to the list
list->head->product_code = code;
list->head->product_cost = cost;
strncpy(list->head->product_name, name, sizeof(list->head->product_name));
// Terminate the string
list->head->product_name[127] = '/0';
}
}
// Initialize linked list
void initialize(list_t *list)
{
// Set list node to null
list = NULL;
list = NULL;
}
// Release all resources
void clean_up(list_t *list)
{
list_t *temp = NULL;
while(list)
{
temp = list->head;
list->head = list->head->next;
free(temp);
}
list = NULL;
list = NULL;
temp = NULL;
}
============================== Edited ============================
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PRODUCT_NAME_LEN 64
// typedef struct product_data product_data_t;
typedef struct product_data
{
int product_code;
char product_name[PRODUCT_NAME_LEN];
int product_cost;
}product_data_t;
typedef struct list
{
struct list *head;
struct list *tail;
struct list *next;
struct list *current_node;
product_data_t *data;
}list_t;
void add(list_t *list, int code, char name[], int cost);
int main(void)
{
list_t *list = NULL;
list = initialize(list);
add(list, 1001, "Dell Inspiron 2.66", 1299);
add(list, 1002, "Macbook Pro 2.66", 1499);
clean_up(list);
getchar();
return 0;
}
void add(list_t *list, int code, char name[], int cost)
{
/* Allocate memory for the new product */
product_data_t *product = (product_data_t*) calloc(1, sizeof(*product));
if(!product)
{
fprintf(stderr, "Cannot allocate memory.");
exit(1);
}
/* This is the first item in the list */
product->product_code = code;
product->product_cost = cost;
strncpy(product->product_name, name, sizeof(product->product_name));
product->product_name[PRODUCT_NAME_LEN - 1] = '\0';
if(!list->head)
{
/* Assign the address of the product. */
list = (list_t*) product;
/* Set the head and tail to this product */
list->head = (list_t*) product;
list->tail = (list_t*) product;
}
else
{
/* Append to the tail of the list. */
list->tail->next = (list_t*) product;
list->tail = (list_t*) product;
}
/* Assign the address of the product to the data on the list. */
list->data = (list_t*) product;
}
If you are looking to better understand the basics of linked lists, take a look at the following document:
http://cslibrary.stanford.edu/103/LinkedListBasics.pdf
Arguably you want your list data structure to be external to the data that it stores.
Say you have:
struct Whatever
{
int x_;
}
Then your list structure would look like this:
struct Whatever_Node
{
Whatever_Node* next_
Whatever* data_
}
Ryan Oberoi commented similarly, but w/o example.
In your case the head and tail could simply point to the beginning and end of a linked-list. With a singly linked-list, only the head is really needed. At it's most basic, a linked-list can be made by using just a struct like:
typedef struct listnode
{
//some data
struct listnode *next;
}listnodeT;
listnodeT *list;
listnodeT *current_node;
list = (listnodeT*)malloc(sizeof(listnodeT));
current_node = list;
and as long as list is always pointing to the beginning of the list and the last item has next set to NULL, you're fine and can use current_node to traverse the list. But sometimes to make traversing the list easier and to store any other data about the list, a head and tail token are used, and wrapped into their own structure, like you have done. So then your add and initialize functions would be something like (minus error detection)
// Initialize linked list
void initialize(list_t *list)
{
list->head = NULL;
list->tail = NULL;
}
void add(list_t *list, int code, char name[], int cost)
{
// set up the new node
product_data_t *node = (product_data_t*)malloc(sizeof(product_data_t));
node->code = code;
node->cost = cost;
strncpy(node->product_name, name, sizeof(node->product_name));
node->next = NULL;
if(list->head == NULL){ // if this is the first node, gotta point head to it
list->head = node;
list->tail = node; // for the first node, head and tail point to the same node
}else{
tail->next = node; // append the node
tail = node; // point the tail at the end
}
}
In this case, since it's a singly linked-list, the tail is only really useful for appending items to the list. To insert an item, you'll have to traverse the list starting at the head. Where the tail really comes in handy is with a doubly-linked list, it allows you to traverse the list starting at either end. You can traverse this list like
// return a pointer to element with product code
product_data_t* seek(list_t *list, int code){
product_data_t* iter = list->head;
while(iter != NULL)
if(iter->code == code)
return iter;
iter = iter->next;
}
return NULL; // element with code doesn't exist
}
Often times, the head and tail are fully constructed nodes themselves used as a sentinel to denote the beginning and end of a list. They don't store data themselves (well rather, their data represent a sentinel token), they are just place holders for the front and back. This can make it easier to code some algorithms dealing with linked lists at the expense of having to have two extra elements. Overall, linked lists are flexible data structures with several ways to implement them.
oh yeah, and nik is right, playing with linked-lists are a great way to get good with pointers and indirection. And they are also a great way to practice recursion too! After you have gotten good with linked-list, try building a tree next and use recursion to walk the tree.
I am not writing the code here but you need to do the following:
Create and object of list, this will remain global for the length of program.
Malloc the size of product _ data _ t.
For first element (head is NULL), point head to the malloced' address.
To add next element, move to the end of list and then add the pointer of malloced address to next of last element. (The next of the last element will always be NULL, so thats how you traverse to end.)
Forget tail for a while.
If you are learning C pointer theory this is a good exercise.
Otherwise, it feels like too much indirection for code that is not generic (as in a library).
Instead of allocating a static 128 byte character string, you might want to do some more pointer practice and use an allocated exact length string that you clean up at exit.
Academically, kungfucraigs' structure looks more generic then the one you have defined.
You're calloc'ing space for your list_t struct, just pointers to list head and tail, which isn't what you want to do.
When you add to a linked list, allocate space for an actual node in the list, which is your product_data_t struct.
You're allocating the wrong chunk of memory. Instead of allocating memory for each list element, you're allocating for the list head and tail.
For simplicity, get rid of the separate structure for the head and tail. Make them global variables (the same scope they're in now) and change them to be listhead and listtail. This will make the code much more readable (you won't be needlessly going through a separate structure) and you won't make the mistake of allocating for the wrong struct.
You don't need a tail pointer unless you're going to make a doubly linked list. Its not a major element to add once you create a linked list, but not necessary either.
In memory your items are linked by pointers in the list structure
item1 -> item2
Why not make the list structure part of your item?
Then you allocate a product item, and the list structure is within it.
typedef struct product_data
{
int product_code;
char product_name[PRODUCT_NAME_LEN];
int product_cost;
struct list_t list; // contains the pointers to other product data in the list
}product_data_t;
I think u first need to Imagin back-end. Code are nothing to important. Go here and visualize back-end basic c code of all insertion.
1) Insertion at beginning Visit and scroll to get every instruction execution on back- end
And u need front and imagin Go here
Back end imagin
And All other possible insertion here.
And important thing u can use this way.
struct Node{
int data;//data field
struct Node*next;//pointer field
};
struct Node*head,*tail; // try this way
or short cut
struct Node{
int data;//data field
struct Node*next;//pointer field
}*head,*tail; //global root pointer
And << Click >> To visualize other linked list problem.
Thanks.
A demo for Singly Linked List. If you prefer, try to check Circular Linked List and Doubly Linked List.
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int val;
struct node * next;
} node_t;
// Iterating over a list
void
print_list(node_t *head)
{
node_t *current = head;
while(current != NULL)
{
printf("%d\n", current->val);
current = current->next;
}
}
// Adding an item to the end of the list
void
push_end(node_t *head, int val)
{
node_t *current = head;
while (current->next != NULL)
{
current = current->next;
}
current->next = malloc(sizeof(node_t));
current->next->val = val;
current->next->next = NULL;
}
// Adding an item to the head of the list
void
push_head(node_t **head, int val)
{
node_t *new_node = NULL;
new_node = malloc(sizeof(node_t));
new_node->val = val;
new_node->next = *head;
*head = new_node;
}
// Removing the head item of the list
int
pop_head(node_t **head)
{
int retval = -1;
node_t *next_node = NULL;
if (*head == NULL) {
return -1;
}
next_node = (*head)->next;
retval = (*head)->val;
free(*head);
*head = next_node;
return retval;
}
// Removing the last item of the list
int
pop_last(node_t *head)
{
int retval = 0;
node_t *current = NULL;
if (head->next == NULL) {
retval = head->val;
free(head);
return retval;
}
/* get to the second to last node in the list */
current = head;
while (current->next->next != NULL) {
current = current->next;
}
/* now current points to the second to last item of the list.
so let's remove current->next */
retval = current->next->val;
free(current->next);
current->next = NULL;
return retval;
}
// Removing a specific item
int
remove_by_index(node_t **head, int n)
{
int i = 0;
int retval = -1;
node_t *current = *head;
node_t *temp_node = NULL;
if (n == 0) {
return pop_head(head);
}
for (i = 0; i < n - 1; i++) {
if (current->next == NULL) {
return -1;
}
current = current->next;
}
temp_node = current->next;
retval = temp_node->val;
current->next = temp_node->next;
free(temp_node);
return retval;
}
int
main(int argc, const char *argv[])
{
int i;
node_t * testnode;
for (i = 0; i < argc; i++)
{
push_head(&testnode, atoi(argv[i]));
}
print_list(testnode);
return 0;
}
// http://www.learn-c.org/en/Linked_lists
// https://www.geeksforgeeks.org/data-structures/linked-list/
The linked list implementation inspired by the implementation used in the Linux kernel:
// for 'offsetof', see: https://stackoverflow.com/q/6433339/5447906.
#include <stddef.h>
// See: https://stackoverflow.com/q/10269685/5447906.
#define CONTAINER_OF(ptr, type, member) \
( (type *) ((char *)(ptr) - offsetof(type, member)) )
// The macro can't be used for list head.
#define LIST_DATA(ptr, type, member) \
CONTAINER_OF(ptr, type, member);
// The struct is used for both: list head and list nodes.
typedef struct list_node
{
struct list_node *prev, *next;
}
list_node;
// List heads must be initialized by this function.
// Using the function for list nodes is not required.
static inline void list_head_init(list_node *node)
{
node->prev = node->next = node;
}
// The helper function, mustn't be used directly.
static inline void list_add_helper(list_node *prev, list_node *next, list_node *nnew)
{
next->prev = nnew;
nnew->next = next;
nnew->prev = prev;
prev->next = nnew;
}
// 'node' must be a list head or a part of a list.
// 'nnew' must not be a list head or a part of a list. It may
// be uninitialized or contain any data (even garbage).
static inline void list_add_after(list_node *node, list_node *nnew)
{
list_add_helper(node, node->next, nnew);
}
// 'node' must be a list head or a part of a list.
// 'nnew' must not be a list head or a part of a list. It may
// be uninitialized or contain any data (even garbage).
static inline void list_add_before(list_node *node, list_node *nnew)
{
list_add_helper(node->prev, node, nnew);
}
// 'node' must be part of a list.
static inline list_node *list_del(list_node *node)
{
node->prev->next = node->next;
node->next->prev = node->prev;
return node->prev;
}
Example of usage:
#include <stdio.h>
// The struct must contain 'list_node' to be able to be inserted to a list
typedef struct
{
int data;
list_node node;
}
my_struct;
// Convert 'list_node *' to 'my_struct*' that contains this 'list_node'
static inline my_struct* get_my_struct(list_node *node_ptr)
{
return LIST_DATA(node_ptr, my_struct, node);
}
void print_my_list(list_node *head)
{
printf("list: {");
for (list_node *cur = head->next; cur != head; cur = cur->next)
{
my_struct *my = get_my_struct(cur);
printf(" %d", my->data);
}
printf(" }\n");
}
// Print 'cmd' and run it. Note: newline is not printed.
#define TRACE(cmd) \
(printf("%s -> ", #cmd), (cmd))
int main()
{
// The head of the list and the list itself. It doesn't contain any data.
list_node head;
list_head_init(&head);
// The list's nodes, contain 'int' data in 'data' member of 'my_struct'
my_struct el1 = {1};
my_struct el2 = {2};
my_struct el3 = {3};
print_my_list(&head); // print initial state of the list (that is an empty list)
// Run commands and print their result.
TRACE( list_add_after (&head , &el1.node) ); print_my_list(&head);
TRACE( list_add_after (&head , &el2.node) ); print_my_list(&head);
TRACE( list_add_before(&el1.node, &el3.node) ); print_my_list(&head);
TRACE( list_del (head.prev) ); print_my_list(&head);
TRACE( list_add_before(&head , &el1.node) ); print_my_list(&head);
TRACE( list_del (&el3.node) ); print_my_list(&head);
return 0;
}
The result of execution of the code above:
list: { }
list_add_after (&head , &el1.node) -> list: { 1 }
list_add_after (&head , &el2.node) -> list: { 2 1 }
list_add_before(&el1.node, &el3.node) -> list: { 2 3 1 }
list_del (head.prev) -> list: { 2 3 }
list_add_before(&head , &el1.node) -> list: { 2 3 1 }
list_del (&el3.node) -> list: { 2 1 }
http://coliru.stacked-crooked.com/a/6e852a996fb42dc2
Of course in real life you will most probably use malloc for list elements.
In C language, we need to define a Node to store an integer data and a pointer to the next value.
struct Node{
int data;
struct Node *next;
};
To add a new node, we have a function add which has data as an int parameter. At first we create a new Node n. If the program does not create n then we print an error message and return with value -1. If we create the n then we set the data of n to have the data of the parameter and the next will contain the root as it has the top of the stack. After that, we set the root to reference the new node n.
#include <stdio.h>
struct node
{
int data;
struct node* next;
};
int main()
{
//create pointer node for every new element
struct node* head = NULL;
struct node* second = NULL;
struct node* third = NULL;
//initialize every new pointer with same structure memory
head = malloc(sizeof(struct node));
second = malloc(sizeof(struct node));
third = malloc(sizeof(struct node));
head->data = 18;
head->next = second;
second->data = 20;
second->next = third;
third->data = 31;
third->next = NULL;
//print the linked list just increment by address
for (int i = 0; i < 3; ++i)
{
printf("%d\n",head->data++);
return 0;
}
}
This is a simple way to understand how does pointer work with the pointer. Here you need to just create pointer increment with new node so we can make it as an automatic.
Go STL route. Declaring linked lists should be agnostic of the data. If you really have to write it yourself, take a look at how it is implemented in STL or Boost.
You shouldn't even keep the *next pointer with your data structure. This allows you to use your product data structure in a various number of data structures - trees, arrays and queues.
Hope this info helps in your design decision.
Edit:
Since the post is tagged C, you have equivalent implementations using void* pointers that follow the basic design principle. For an example, check out:
Documentation | list.c | list.h

Resources