Linked List Definition - c

This snippet of code is from an assignment I'm working on at school for a data structures module. This bit of code is provided in the question, and I can't understand this.
typedef struct _listnode {
int item;
struct _listnode *next;
} ListNode; // You should not change the definition of ListNode
typedef struct _linkedlist {
int size;
ListNode *head;
} LinkedList; // You should not change the definition of LinkedList
I am confused because my lecture slides and sites I've been to check this out have just defined the node, and not the second one.
Can anyone help me with this please?

LinkedList is a struct denoting a linked list by holding its head and its size, while each node in the list is denoted by struct ListNode. This is a common paradigm if you want to maintain the size of the linked list, in the case you can easily get the number of nodes in the list without have to iterate through it. On the other hand, if size is not concern, you can just use a pointer to node for the head without have to define the LinkedList struct.
So for an empty list, you would have:
LinkedList list = (struct LinkedList){0, NULL};
For a list with one node:
ListNode node;
node.item = 0;
node.next = NULL;
list.head = &node;
list.size = 1;

A linked list is held using a local pointer variable which points to the first item of the list. If that pointer is also NULL, then the list is considered to be empty.
include <stdio.h>
int main() {
typedef struct node {
int val;
struct node * next;
} node_t;
return 0;
}

Related

I need help returning the next node of a doubly linked list in C

I created a doubly linked list and in the function that adds values to the list, it calls the function list_next which is supposed to return the next node in the list but I'm unable to figure out just how to do that. I feel like ListPos Pos is a double pointer hence why I wrote my code like that, but it's apparently wrong. How should I go about writing it and how would I avoid that mistake in the future?
struct node
{
struct node *next;
struct node *prev;
char *value;
};
typedef struct list_pos
{
struct node *node;
} ListPos;
ListPos list_next(ListPos pos)
{
return &(*pos.node)->next;
}
Here's your code with some changes, explained in comments, which hopefully will help you:
struct node
{
struct node *next;
struct node *prev;
char *value;
};
// typedefs are more confusing than they are useful
struct list_pos
{
struct node *node;
};
struct list_pos list_next(struct list_pos pos)
{
// don't be afraid to use temp variables to make your code clearer
struct node *current = pos.node;
assert(current != NULL); // one way to indicate assumption
// you could also check if current is NULL and return NULL in that case
struct node *next = current->next;
return (struct list_pos){next}; // compound literal to avoid temp variable
}
&(*pos.node)->next doesn't make any sense.
You probably want this:
ListPos list_next(ListPos pos)
{
ListPos next;
next.node = pos.node->next;
return next;
}
What Jabberwocky suggested is the right answer. I just wanted to add that you could replace
typedef struct list_pos
{
struct node *node;
} ListPos;
with
typedef struct node* ListPos;
because you looked like you were thinking that ListPos is a pointer rather than separate struct.

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 */
/* ... */
}

Pointer to struct, trying to refer to its data members - C

I have this code:
typedef struct node
{
char* data;
struct node next;
} node;
typedef struct linkedList
{
node head;
int size;
} linkedList;
typedef struct _MyLinkedList *MyLinkedListP
{
struct linkedList* listp;
};
MyLinkedListP createList()
{
linkedList *list = (linkedList*)malloc(sizeof(linkedList));
(*list).head = NULL;
(*list).size = 0;
MyLinkedListP listP = list;
return listP;
}
I am trying to build a function:
MyLinkedListP cloneList(MyLinkedListP l)
l is a pointer to a linkedList, I am trying to get its members (size and first node), in order to complete the function. But I just do not understand how to do it under this build.
I also want to ask regarding my build of struct MyLinkedListP. My goal was to create a type that is a pointer to a linkedList, is the way I did it good practice?
First of all, this won't work:
typedef struct node
{
char* data;
struct node next;
} node;
A struct type may not contain a member that's an instance of itself1; this should be written as
typedef struct node
{
char* data;
struct node *next; // next is a *pointer* to struct node
} node;
Secondly, while the following isn't a problem like the above, this is not good practice:
typedef struct _MyLinkedList *MyLinkedListP
Identifiers with leading underscores are reserved for the implementation; you should not create any type or object names with leading underscores. Just use
typedef struct MyLinkedList *MyLinkedListP
instead2.
Third, lose the cast in
linkedList *list = (linkedList*)malloc(sizeof(linkedList));
It's not necessary (since C89), it clutters up the call, and it creates maintenance headaches. That can be made much simpler as follows:
linkedList *list = malloc( sizeof *list );
Fourth, note that you can write
(*list).head = NULL;
(*list).size = 0;
as
list->head = NULL;
list->size = 0;
a->b is shorthand for (*a).b, and makes things a little easier to read.
Finally,
MyLinkedListP listP = list;
is attempting to assing a value of type struct linkedList * to an object of type struct MyLinkedList *, and they aren't compatible. Based on the code you've shared, it looks like you meant to do something more like
struct MyLinkedList myList;
list.listp = list;
or
struct MyLinkedList myList = {list};
or even
MyLinkedListP listP = malloc( sizeof *listP ); // leaky abstraction from hiding
// pointer behind typedef
listP->listp = list;
I suggest you take a step back and try to simplify what you're doing - you've added a bit of unnecessary complexity with your types.
First of all, the struct node type isn't complete until the closing } of the struct definition, and you can't declare an instance of an incomplete type; you can, however, declare a pointer to an incomplete type. Secondly, the size to store an instance of struct node would have to be infinite, since the instance contains an instance of itself, which contains an instance of itself, which contains an instance of itself, etc.
A quick rant - as a rule, you should not hide pointers behind typedefs. If the programmer has to ever be aware that they are dealing with a pointer (for example, if they need to access members of the struct type), then make that explicit in the declaration of the pointer object (look at the FILE type in stdio.h as an example - even though you only ever deal with pointers to FILEs, that pointer is not part of the FILE typedef).
The definition of struct node won't compile, because it is trying to contain itself in its definition. Instead, use indirection via a pointer.
typedef struct node
{
char* data;
struct node *next;
} node;
The definition of struct _MyLinkedList is incorrect, since the body has to follow the tag. Mirror your syntax for struct node and place the alias after the struct declaration.
typedef struct _MyLinkedList
{
struct linkedList* listp;
} *MyLinkedListP;
Since the head member of struct linkedList is not a pointer variable, the assignment will not compile. If you meant for the assignment to succeed, then change the definition of struct linkedList accordingly.
typedef struct linkedList
{
node *head;
int size;
} linkedList;
Your are assigning a struct linkedList * to a struct _MyLinkedList *, but they are not compatible. Since your function wants to return a struct _MyLinkedList *, you should properly allocate one to be returned.
MyLinkedListP listP = malloc(sizeof(*listP));
listP->listp = list;
return listP;
With all the changes together, and fixing up some stylistic issues:
typedef struct node
{
char* data;
struct node *next;
} node;
typedef struct linkedList
{
node *head;
int size;
} linkedList;
typedef struct _MyLinkedList
{
struct linkedList* listp;
} *MyLinkedListP;
MyLinkedListP createList()
{
linkedList *list = malloc(sizeof(*list));
list->head = NULL;
list->size = 0;
MyLinkedListP listP = malloc(sizeof(*listP));
listP->listp = list;
return listP;
}

Wrong memory offset with polymorphic structs

I'm currently implementing a doubly-linked list in C. The purpose of the list is to be as generic as possible. Here's the node struct:
typedef struct list_node
{
struct list_node *prev;
struct list_node *next;
int nodeId;
} Node;
Now, I'm extending this into the following node:
typedef struct history_node
{
Node *node;
String *cmd;
} HistoryNode;
Where the string struct is defined as follows:
typedef struct c_string
{
char *array;
size_t size;
} String;
Now, the problem that I'm having is this: I create a new history node, and set it's string to a value, "hello" for example. I then call on my pushBack function, that is defined as follows:
void pushBack(Node *node, List *list)
{
node->next = list->tail;
node->prev = list->tail->prev;
list->tail->prev->next = node;
list->tail->prev = node;
list->size++;
}
The thing here is that when I assign node->next, instead of accessing the node part of the history node, I access the string, which results in disaster. I have no idea why this is happening. Looking at the addresses in memory, the pointer that is passed in has the correct address, but the address that is accessed in node->next corresponds to the address of cmd and not node. Any ideas?
Just in case, the code that calls this function is:
HistoryNode *node = createHistoryNode(buffer);
pushBack((Node*)node, historyList);
I have already verified that createHistoryNode works as expected, so that is not the source of the problem.
You don't want
typedef struct history_node {
Node *node;
String *cmd;
} HistoryNode;
you want
typedef struct history_node {
Node node;
String *cmd;
} HistoryNode;

Resources