C Linked List with Sentinel - Getting Access to nodes - c

I'm struggeling to get this task (Implementing a linked list) done. I tried to build a so called sentinel, which sould make it easier. My question is, how do I get access to the actual elements? I tried to print the roots value (44) but I only get weired values. I assume, that these are adresses of memory (e.g. 6893440).
#include<stdio.h>
struct node {
int val;
struct node* next;
};
struct node** init() {
struct node **l;
l = malloc(sizeof(struct node**));
*l = NULL;
return l;
}
void insert(struct node** l, int val) {
struct node* p;
if(*l == NULL) {
p = malloc(sizeof(struct node));
p->val = val;
p->next = *l;
*l = p;
}
}
void main() {
struct node* list;
list = init();
insert(list, 44); // create a (root)node with value 44
printf("%d", list->val); // e.g. 6893440
}
Thank you very much for your help.

You should declare the list as a double pointer to node.
struct node** list;
Then you can access the value of the first node with
(*list)->val
More info:
In the implementation in data types such as lists in C we often use 2 typedefs to help with the readability of the code and eliminate lots of asterisks and ampersands. These are:
typedef struct node* ListNode;
typedef ListNode* List;
By doing this, you can declare a list simply by:
List list;
Note that the implementation of the list functions also becomes more readable by replacing struct node* and struct node** appropriately.

Related

Typedef vs tructure tag

I'm learning link list. I create structure called Node to store the data and link to the next node. I have two doubts.
I dont understand why we are using the structure we are creating inside the same strucutre as element to store link. Is looks like a nested structure, will the element likn will have link.data and link.link in it? It is confusing
struct Node{
int data;
struct Node* link;
}node;
I created a typedef for the structure Node as node, so that I can declare variables and use as datatype inside the code. But it gives me error. I'm missing some understanding here.
If I use struct Node representation throught my code, it works fine. If I change it to node, i see lot of error. (except when I use it inside sizeof function)
My working code:
#include <stdio.h>
#include <stdlib.h>
struct Node{
int data;
struct Node* link;
}node;
struct Node head;
void Insert(int X);
void Print();
int main(){
head = NULL;
printf("How laby elements you need?\n");
int n,i,x;
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("Enter the elements:\n");
scanf("%d",&x);
Insert(x);
Print();
}
}
void Insert(int x)
{
struct Node* temp = (struct Node*)malloc(sizeof(node));
temp->data = x;
temp->link = head;
head = temp;
}
void Print(){
struct Node* temp = head;
while(temp != NULL)
{
printf("The list is: %d\n",temp->data);
temp = temp->link;
}
}
My not working code:
#include <stdio.h>
#include <stdlib.h>
struct Node{
int data;
struct Node* link;
}node;
node* head; // Error
void Insert(int X);
void Print();
int main(){
head = NULL;
printf("How laby elements you need?\n");
int n,i,x;
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("Enter the elements:\n");
scanf("%d",&x);
Insert(x);
Print();
}
}
void Insert(int x)
{
node* temp = (node*)malloc(sizeof(node)); // Error
temp->data = x;
temp->link = head;
head = temp;
}
void Print(){
node* temp = head; // Error
while(temp != NULL)
{
printf("The list is: %d\n",temp->data);
temp = temp->link;
}
}
I dont understand why we are using the structure we are creating inside the same strucutre as element to store link. Is looks like a nested structure
The struct Node structure doesn't contain itself. That would be impossible, as it would have infinite size.
Rather, it contains a struct Node * pointer. Specifically, this pointer will be used to locate the next node in the list. But that doesn't make the next node part of the current node.
I created a typedef for the structure Node as node
No, you didn't. There's no typedef in the code you posted.
struct Node {
int data;
struct Node* link;
} node;
is short for
struct Node {
int data;
struct Node* link;
}
struct Node node;
This creates a variable of type struct Node called node.
typedef struct Node {
int data;
struct Node* link;
} node;
is short for
struct Node {
int data;
struct Node* link;
};
typedef struct Node node;
This creates a type called node.
Note that I prefer to use lowercase for variables, and CamelCase for types, so I wouldn't use node for a type; I'd use Node instead.
typedef struct Node {
int data;
struct Node* link;
} Node;
I dont understand why we are using the structure we are creating
inside the same strucutre as element to store link. Is looks like a
nested structure, will the element likn will have link.data and
link.link in it? It is confusing
In this declaration
struct Node{
int data;
struct Node* link;
};
the data member link does not have the type struct Node. It has the pointer type struct Node *. So there is no nested structures. Each node of the list stores a pointer to the next node.
You forgot to place the typedef specifier in this declaration
struct Node{
int data;
struct Node* link;
}node;
As a result the name node in the above declaration means an object of the type struct Node. So the compiler issues an error for the following declaration
node* head;
and other usages of the name node in the program because node in this case is an identifier of an object instead of a type specifier.
You have to write
typedef struct Node{
int data;
struct Node* link;
}node;
node* head;
In this case the name node denotes a type specifier that is a typedef name for the type specifier struct Node..
This statement in main
head = NULL;
is redundant. The pointer head was already initialized as a null pointer in its declaration in the file scope because this declaration
node* head;
is equivalent to
node* head = NULL;
Pay attention to that it is not a good idea when functions depend on global variables as in your program on the pointer head declared in the file scope.
Do not forget at least to write a function that will free all the allocated memory for the list.

Deleting head node of a linked list in C where every node knows its headlist

typedef struct node {
int x;
struct node *next;
struct node **head;
} node;
Considering this struct, I've implemented a push function:
node *push(node *nodo, node *top) {
nodo->next = top;
top = nodo;
nodo->head = &top;
return top;
}
so that every node is aware of who is the current head list.
But I have some problems when I have to delete the head of the list:
node *delete(node *top, int x) {
if (top->x == x)
return pop(top);
else
return *other function*;
}
node *pop(node *top) {
node *tmp = top;
top = tmp->next;
free(tmp);
return top;
}
When printing head content, this will give me segmentation fault:
void print(node *top) {
node *tmp = top;
printf("List:\n");
while (tmp != NULL) {
printf("%d\n", (*((tmp)->head))->x);
tmp = tmp->next;
}
printf("\nEnd\n");
}
But I have some problems when I have to delete the head of the list
You have much worse and more pervasive problems.
Here ...
node* push(node* nodo, node* top){
nodo->next=top;
top = nodo;
nodo->head = &top;
return top;
}
You set nodo->head to point to a parameter of the function. The lifetime of that parameter ends when the function returns, at which time the node's head pointer becomes invalid. Undefined behavior results from any subsequent attempt to use the node's head pointer in any way.
I suppose that you have defined node.head as a double pointer so as to be able to change the head node in one place for all nodes. In that case, you need to choose a "one place" that is in fact the same for every node and whose lifetime does not end before that of the overall list does. Having chosen such a location, you would pass it itself to push:
node* push(node* nodo, node** top){
nodo->next = *top;
nodo->head = top;
*top = nodo;
return *top;
}
Of course, all callers would need to be updated appropriately.
However, if you want to have this kind of association between nodes and the list to which they belong, then you should consider creating a separate data structure for the list itself, and giving the nodes a poiunter to that. That would solve several problems for you.
Example:
typedef struct node{
int x;
struct node* next;
struct list* list;
}node;
struct list {
node *head;
// maybe other whole-list information, too, such as the tail node
// or an element count
};
The struct list objects then provide the place for head node pointers to be recorded, and nodes can access their lists' head node via the list.

Question regarding multiple singly linked lists

I'm trying to create multiple singly linked lists by using a list struct and a node struct. What I am thinking is each new list is told apart by a different head. But what makes me confused is how do I initialize a new head for each list and then add on nodes?
When I worked with just one list I was able to just allocate memory for the one head pointer and set it to NULL and then just add on new nodes.
My structs looks like this for reference:
typedef struct node
{
int value;
struct node *next;
}node_t;
typedef struct list
{
struct list *head;
int size;
}list_t;
If you feel like I've been unclear on something just ask and I will clarify!
Thanks
In your list structure head should actually be a node_t - first node in the list.
And then you will chain the nodes by assigning another node_t to next
typedef struct node
{
int value;
struct node *next;
}node_t;
typedef struct list
{
node_t *head;
int size;
}list_t;
Simple example for reference:
node_t node1;
node_t node2;
node1.value = 1;
node1.next = &node2;
node2.value = 1;
node2.next = NULL;
list_t list;
list.head = &node1;
list.size = 2;
After re-reading your question multiple times, I probably finally understand what you are trying to achieve. You want list_t to contain multiple "lists" of type node_t.Then you need to make head an array of node_t pointers like this:
typedef struct node
{
int value;
struct node *next;
}node_t;
typedef struct list
{
node_t *head[2];
int size;
}list_t;
(i've used array of static size of 2 for simplicity. If you want to make it dynamic, you will need to take care of memory allocations on your own)
And example code:
// list1
node_t node11;
node_t node12;
node11.value = 1;
node11.next = &node12;
node12.value = 1;
node12.next = NULL;
//list2
node_t node21;
node_t node22;
node11.value = 2;
node11.next = &node22;
node12.value = 2;
node12.next = NULL;
list_t list;
list.head[0] = &node11;
list.head[1] = &node21;
list.size = 2;

Trying To Typecast A Node Into A Linked List

I have a doubly linked list data structure, and each node within that linked list is another linked list.
I'm trying to typecast the node into a linked list later in the program, but receive the error:
error: conversion to non-scalar type requested
Which I know is because I'm trying to typecast into a structure which isn't allowed.
What would the work around be for something similar to this?
List toPass = (List)(iter->data);
I've already tried creating a new List and manually setting all of the values from the iter->data to the structure items but I receive the same error.
Edit:
Initialize List Function:
List initializeList(char* (*printFunction)(void* toBePrinted),void (*deleteFunction)(void* toBeDeleted),int (*compareFunction)(const void* first,const void* second)) {
List tmpList;
tmpList.head = NULL;
tmpList.tail = NULL;
tmpList.deleteData = deleteFunction;
tmpList.compare = compareFunction;
tmpList.printData = printFunction;
tmpList.length = 0;
return tmpList;
}
Node Function:
Node* initializeNode(void* data) {
Node* tmpNode;
tmpNode = (Node*)malloc(sizeof(Node));
if (tmpNode == NULL){
return NULL;
}
tmpNode->data = data;
tmpNode->previous = NULL;
tmpNode->next = NULL;
return tmpNode;
}
At this point if you want to test, just make a list of lists, then try to typecast the node into a list.
Edit:
Header structs
List:
typedef struct listHead{
Node* head;
Node* tail;
int length;
void (*deleteData)(void* toBeDeleted);
int (*compare)(const void* first,const void* second);
char* (*printData)(void* toBePrinted);
} List;
Node:
typedef struct listNode{
void* data;
struct listNode* previous;
struct listNode* next;
} Node;
So if you know that list->data is a void* pointer pointing to a List
object, then you have to do:
List *toPass = list->data;
no cast is needed because C explicitly casts the void*-pointer to a List*
pointer.
If you don't want to have a pointer but a copy (bit by bit copy) of the object pointed to by list->data, then you would need to
do
List toPass = *((List*) list->data);
and toPass would be a copy of the contents of the object pointed to by
list->data.
I think you want to do like followings,
the typical double linked list implementation:
typedef struct list {
List *prev, *next;
} List;
typedef struct entry {
List *list;
List *another link; /* your another dlist here */
void *my_real_data; /* you store your data here */
/* ... */
}

Creating lists of lists (Structs)

I am doing a programming assignment at the moment and I dont really have a full grasp of linking as we havent covered it yet. However I feel I need it to do what I want as arrays are not sufficent
I have created a struct as follows
struct node
{
float coef;
int expo;
struct node *link;
};
from this I can create pointers to the struct each with different names, however the problem I encountered is that I want user input to determine the amount I structs. I also want the ability to add and create the different structs.
You need to create a head pointer to keep track of your list.
This might be helpful:
struct list
{
struct node *head;
int count;
};
And you need to allocate memory for each new node and move the head to the newly created one.
struct node *add_node(struct list *pList, float coef, int expo)
{
if (pList == NULL)
{
return NULL;
}
struct *node pNode = (struct node*)malloc(sizeof(struct node));
if (node == NULL)
{
return NULL;
}
pNode->coef = coef;
pNode->expo = expo;
pNode->link = pList->head;
pList->head = pNode;
pList->count++;
return pNode;
}
To delete an element you need to move the head forward and then free it previous memory.
void *delete_node(struct list *pList, float coef, int expo)
{
if (pList == NULL)
{
return NULL;
}
struct node *tmp = pList->head;
pList->head = pList->head->link;
free(tmp);
pList->count--;
}
Note:
This is not the ultimate version. I'm just pointing my fingers to what should be done.
I would try something like this as your data structure
struct node
{
float coef;
int expo;
struct node *link;
};
struct poly
{
node *value;
struct poly *link
}
Maintain a linked list of polys, each of which contains a linked list of nodes.

Resources