Double linked list prepend element by ref in C - c

I try to write double linked list in C.
This is my implementation:
typedef struct
{
void* value;
struct Dlist* prev;
struct Dlist* next;
} Dlist;
Dlist* createDlist()
{
Dlist* newList = (Dlist*)malloc (sizeof(Dlist));
newList->value = NULL;
newList->next = NULL;
newList->prev = NULL;
return newList;
}
/*
* Get last element from Dlist
*/
Dlist* getLast(Dlist* list)
{
if (list)
{
while(list->next)
list = (Dlist*)list->next;
}
return list;
}
/*
* add element to list at start
*/
Dlist* addItemAtStart(Dlist* list, Pair* value)
{
Dlist* newList = NULL;
Dlist* last = NULL;
newList = createDlist ();
newList->value = value;
if (list)
{
last = getLast(list);
last->next = newList;
newList->prev = last;
return list;
}
else
return newList;
}
Now, when i try to add element to my list, i need assign a new value every time:
list = addItemAtStart(list, "Hello");
But i want only
addItemAtStart(list, "Hello");
Without list = How can i make so that list will change without assign?
p.s. I get segfaut with Dlist* addItemAtStart(Dlist **list, void* value)
I try to insert so:
Dlist **list = NULL;
addItemAtStart(&list, "Hello");
Thank you.

If you handle the list by pointing to its first element, maybe you should use double indirection:
void addItemAtStart(Dlist** plist, Pair* value)
{
// replace all list with *plist
}
addItemAtStart(&list, "Hello");

You can write your function to accept a pointer to a pointer to a List:
Dlist* addItemAtStart(Dlist** list, Pair* value)
Just make sure you add another level of indirection inside of addItemAtStart when using list.
The function can be called using
addItemAtStart(&list, "Hello");

Give reference of the head node to insert node at start.
Dlist* addItemAtStart(Dlist** list, Pair* value)
{
Dlist* newList = NULL;
Dlist* last = NULL;
newList = createDlist();
newList->value = value;
if (list)
{
last = getLast(*list);
last->next = newList;
newList->prev = last;
}
else
*list = newList

for achieving that, you need to create a static linked list node pointer.
make sure that the atitematstart method updates that node.

Using a global list will solve your problem. In the function, assign the value to the list object. I have tried it.

Your code with some corrections and inclusions:
#include <stdio.h>
#include <stdlib.h>
struct node{
void* value;
struct node *prev, *next;
};
/*This Function is Unnecessary
struct node * createList(){
struct node *newNode=malloc(sizeof(struct node));
if (newNode==NULL) return NULL;
newNode->value = NULL;
newNode->next = NULL;
newNode->prev = NULL;
return newNode;
}
*/
/*
*This Function is also Unnecessary
*Get last element from Dlist
struct node* getLast(struct node* node){
if (node==NULL) return NULL;
while (node->next!=NULL) node=node->next;
return node;
}
*/
/*
*Description: add element to list at start
*
*Return Values:
*0:Failed
*1:Succeeded
*/
int addItemAtStart(struct node **head, void *value){
struct node *newNode=malloc(sizeof(struct node));
/*Sometimes malloc can't allocate memory and returns NULL so you have to check it and if malloc couldn't allocate memory you have to exit the function*/
if (newNode==NULL) return 0;
newNode->value=value;
newNode->prev=NULL;
newNode->next=*head;
if (*head!=NULL) (*head)->prev=newNode;
*head=newNode;
return 1;
}
int main(){
struct node *list=NULL;
addItemAtStart(&list, "apple");
addItemAtStart(&list, "lemon");
addItemAtStart(&list, "orange");
addItemAtStart(&list, "peach");
return 0;
}

Related

How to init a LinkedList?

I want to init my LinkedList, but failed.
typedef int ElemType;
typedef struct LNode
{
ElemType data;
struct LNode* next;
}LNode, *LinkedList;
void Init(LinkedList L)
{
L = (LNode *)malloc(sizeof(LNode));
L->next = NULL;
}
int main()
{
LinkedList head;
Init(head);
return 0;
}
If I Init my LinkedList like this it works.
LNode node = (LNode *)malloc(sizeof(int));
node->data = 5;
node->next = NULL;
LinkedList head = node;
but this will make my head with a value.
void Init(LNode **L, ElemType data)
{
*L = malloc(sizeof(LNode));
(*L)->data = data;
(*L)->next = NULL;
}
int main()
{
LinkedList head;
Init(&head, 0);
// ...
free(head);
return 0;
}
Initializing your head to not contain a value doesn't really make sense, unless you actually want head = NULL which I assume is not the case.
You've chosen to define a linked list as a pointer to an element - the head element.
It's customary to initialize containers (like lists, queues, stacks etc.) to be empty. An empty list has no head element, so the pointer to the head element would be NULL. In other words, you would either write
LinkedList create_list()
{
return NULL;
}
// ...
LinkedList mylist = create_list();
or
void initialize_list(LinkedList* list)
{
*list = NULL;
}
// ...
LinkedList my_list;
initialize_list(&my_list);
The use of malloc() will be in functions which append or prepend a new node to the list.

How to avoid the condition that a variable is auto-allocated to the memory unit that my pointer points to?

I want to insert several nodes into an empty singly-linked list. It's OK when I insert the first node. However, the fist node is replaced by the second node when I call the function
the first time using function ListInsert(), the variable newNode is at the memory unit 0x7fffffffdf50. And the second time calling function ListInsert(), *L = 0x7fffffffdf50, **L = {m_Data = first node data, m_nextNode = NULL}. but when I create the newNode, it is still at the memory unit 0x7fffffffdf50. If I set newNode = second node data, it actually replace the first node but not insert into the linked list
struct t_Node
{
struct t_Data m_Data;
struct t_Node *m_nextNode;
}
typedef struct Node* t_LinkedList;
void ListInsert(t_LinkedList* L, int position, struct t_Data newData)
{
if (!*L)
{
struct t_Node newNode;
newNode.m_Data = newData;
newNode.m_nextNode = NULL;
(*L) = &newNode;
}
/* first Node is not NULL */
else
{
t_LinkedList anIterator;
anIterator = (*L);
if (!(*anIterator).m_nextNode)
{
struct t_Node newNode;
newNode.m_Data = newData;
newNode.m_nextNode = NULL;
(*anIterator).m_nextNode = &newNode;
}
}
}
t_LinkedList aLinkedList;
aLinkedList = NULL;
ListInsert(&aLinkedList,1,data1);
ListInsert(&aLinkedList,2,data2);
I expect to insert the second node based on the singly linked list with one node but not to replace the first node, and to maintain the structure of the program.
When you create new variable inside a function, the memory for that variable is allocated on the stack, that is why when the function returns the memory is no longer accessible. So we need to dynamically allocate memory in the heap. Read this to get a better idea about heap and stack. Here is the modified version of your code using dynamic allocation. Also note that when allocating memory dynamically, we need to free the memory when we are done using it, therefore I added a deleteList() function to delete the list.
#include<stdio.h>
#include<stdlib.h>
struct t_Node
{
int m_Data;
struct t_Node *m_nextNode;
};
typedef struct t_Node* t_LinkedList;
void ListInsert(t_LinkedList* L, int position, int newData)
{
struct t_Node * newNode = malloc(sizeof(struct t_Node));
newNode -> m_Data = newData;
newNode -> m_nextNode = NULL;
if (!*L)
{
(*L) = newNode;
}
/* first Node is not NULL */
else
{
t_LinkedList anIterator;
anIterator = (*L);
if (!(*anIterator).m_nextNode)
{
(*anIterator).m_nextNode = newNode;
}
}
}
void printList(t_LinkedList list)
{
while(list != NULL)
{
printf("%d\n", list->m_Data);
list = list -> m_nextNode;
}
}
void deleteList(t_LinkedList list)
{
t_LinkedList node = list -> m_nextNode;
while(node)
{
free(list);
list = node;
node = node -> m_nextNode;
}
}
int main()
{
t_LinkedList aLinkedList;
aLinkedList = NULL;
ListInsert(&aLinkedList,1,10);
ListInsert(&aLinkedList,2,20);
printList(aLinkedList);
deleteList(aLinkedList);
return 0;
}

Returning the first node in a list

I'm asked to return the first Node in a list, in a given generic struct, but I'm having trouble to figure out the most efficient way to do so.
Is doing a previous pointer (besides next) is the only way?
struct Map_t {
Map next;
MapDataElement currentData;
MapKeyElement currentKey;
};
You provide very little information.
I guess you need something like this:
struct List
{
struct Map_t *head;
struct Map_t *tail;
};
struct Map_t {
struct Map_t *next;
MapDataElement currentData;
MapKeyElement currentKey;
};
// Initialize list for first use
void InitializeList(struct List *l)
{
l->head = l->tail = NULL;
}
// add new data/key pair to list
void AddToList(struct List *l, MapDataElement data, MapKeyElement key)
{
struct Map_t *newnode = malloc(sizeof(*newnode));
newnode->currentData = data;
newnode->currentKey = key;
newnode->next = NULL;
if (l->head == NULL)
{
// special case when list is empty
l->head = l->tail = newnode;
}
else
{
// list is non empty
l->tail->next = newnode; // append new node to tail
l->tail = newnode; // tail becomes newnode
}
}
int main()
{
struct List mylist; // your list
// the head of the list is stored permanently
// in mylist.head
InitializeList(&mylist);
MapDataElement data = ...; // get data from somewhere
MapKeyElement key = ...; // get key from somewhere
AddToList(&mylist, data, key);
...
}
As already stated in a comment: the head of the list is stored permanently mylist.head.
Disclaimer: this is untested and incomplete code. No error checking is done for brevity.

How to modularize a Linked List?

I have the following Linked List:
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data; // Linked List type of data.
struct Node *next; // Pointer to the next Node.
};
void printfList(struct Node *head)
{
while(head != NULL)
{
printf(" %d\n", head -> data);
head = head -> next;
}
}
int main()
{
struct Node *head = NULL;
struct Node *second = NULL;
struct Node *third = NULL;
head = (struct Node*) malloc(sizeof(struct Node));
second = (struct Node*) malloc(sizeof(struct Node));
third = (struct Node*) malloc(sizeof(struct Node));
head -> data = 1;
head -> next = second;
second -> data = 2;
second -> next = third;
third -> data = 3;
third -> next = NULL;
printfList(head);
return 0;
}
How can I modularize this example to get something more professional? node type and separated from the others and function separately?
I think by "modularize" here you mean more kinda professional, clean looking code, I came up with following :
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data; // Linked List type of data.
struct Node *next; // Pointer to the next Node.
};
struct Node * makeNode(int data){
struct Node *temp = (struct Node*)malloc(sizeof(struct Node));
temp->data = data;
temp->next = NULL;
return temp;
}
void printfList(struct Node *head)
{
while(head != NULL)
{
printf(" %d\n", head -> data);
head = head -> next;
}
}
int main()
{
struct Node *head, *prev;
int i, n;
printf("How many values you want to insert ?");
scanf("%d", &n);
printf("\nNow enter values :\n");
for(i = 0; i < n; i++){
int val;
scanf("%d", &val);
if(i == 0){
head = makeNode(val);
prev = head;
}
else{
struct Node *temp = makeNode(val);
prev->next = temp;
prev = temp;
}
}
printfList(head);
return 0;
}
Hope it helps.
I'm not sure what you're looking to do, but I think you should start by reviewing the question: should a "node" be a property of an object (a struct data type) or should a "node" be an accessor to a data type...?
Both work and I've used both.
When I need to link existing objects together, than a node will contain a reference data type... but unlike your list, the data is always accessed using a pointer (not containing the actual data type, but only using a reference).
This allows one (object) to many (lists) relationships.
However, many times the data type itself will need to be "chained" (in a single list - one to one relationship), in which case the "node" is a property of the data type and can be re-used in many different types.
A list to link existing types
Here's an example code where I used a linked list to link existing objects using a void pointer.
I'm not sure this implementation adds anything to your initial concept, but it does show the "modularization" for a "one (objet) to many (lists)" approach.
/* *****************************************************************************
Simple List
***************************************************************************** */
typedef struct fio_ls_s {
struct fio_ls_s *prev;
struct fio_ls_s *next;
void *obj;
} fio_ls_s;
#define FIO_LS_INIT(name) \
{ .next = &(name), .prev = &(name) }
/** Adds an object to the list's head. */
static inline __attribute__((unused)) void fio_ls_push(fio_ls_s *pos,
void *obj) {
/* prepare item */
fio_ls_s *item = (fio_ls_s *)malloc(sizeof(*item));
if (!item)
perror("ERROR: fiobj list couldn't allocate memory"), exit(errno);
*item = (fio_ls_s){.prev = pos, .next = pos->next, .obj = obj};
/* inject item */
pos->next->prev = item;
pos->next = item;
}
/** Adds an object to the list's tail. */
static inline __attribute__((unused)) void fio_ls_unshift(fio_ls_s *pos,
void *obj) {
pos = pos->prev;
fio_ls_push(pos, obj);
}
/** Removes an object from the list's head. */
static inline __attribute__((unused)) void *fio_ls_pop(fio_ls_s *list) {
if (list->next == list)
return NULL;
fio_ls_s *item = list->next;
void *ret = item->obj;
list->next = item->next;
list->next->prev = list;
free(item);
return ret;
}
/** Removes an object from the list's tail. */
static inline __attribute__((unused)) void *fio_ls_shift(fio_ls_s *list) {
if (list->prev == list)
return NULL;
fio_ls_s *item = list->prev;
void *ret = item->obj;
list->prev = item->prev;
list->prev->next = list;
free(item);
return ret;
}
/** Removes an object from the containing node. */
static inline __attribute__((unused)) void *fio_ls_remove(fio_ls_s *node) {
void *ret = node->obj;
node->next->prev = node->prev->next;
node->prev->next = node->next->prev;
free(node);
return ret;
}
A list that is integrated in the data-type
Often I have objects that I know I will link together and that by nature will only belong to a single list ("one to one").
In these cases, placing the node struct data within the data-type allows better locality and improved performance through a single allocation for both the data and the node information.
A good enough example for such a situation can be examined is this SO answer.

Trying to access elements of linked-list structures in C and calling functions on struct elements

I am starting out on C and i was just wondering how I would declare these linked lists structures in the main function so that I could call the functions on them, and then how I would print the values from the elements of the linked list.
Thanks for the help
#include <stdio.h>
#include <stdlib.h>
void main() {
}
struct element {
struct element * next;
int data;
};
struct linked_list {
struct element * head;
};
void append_int(struct linked_list * list, int val) {
struct element * elem = malloc(sizeof(struct element));
elem->data = val;
elem->next = NULL; // Really important to explicitly set this to null. Malloc does not zero memory
if (list->head == NULL) {
// Empty list, we need to append to head
list->head = elem;
} else {
// List has some elements, find the end and append to that
struct element * tail = list->head;
while (tail->next != NULL) {
tail = tail->next;
}
tail->next = elem;
}
}
void deletehead(struct linked_list * list) {
while(list->head) {
struct element * temp_head = list->head->next;
free(list->head);
list->head = temp_head;
}
}
void inserthead(struct linked_list * list, int val) {
struct element * new_node = malloc(sizeof(struct element));
new_node->data = val;
struct element * temp_head2 = list->head;
list->head = new_node;
new_node->next = temp_head2;
}
you can create the struct linked_list, that will hold the pointer to the first "link", the first element that is your "object" like in Object Oriented programming.
also don't forget to forward declare your functions if needed!
to create a linked list:
struct linked_list* list = malloc(sizeof(linked_list));
to call functions on it:
inserthead(list, 5);
if you are coming from an oop background, all functions are static, you can think of passing the pointer to the function as calling it like "list.insert()".

Resources