How to init a LinkedList? - c

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.

Related

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.

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()".

Implementing a list C

I have the code with the structure of a list and the code that implements it.
Structure,entry_t is the type of data on the list:
#ifndef _list_private_h
#define _list_private_h
typedef struct list_t{
struct node_t *head;
int size;
};
typedef struct node_t{
struct entry_t *element;
struct node_t *next;
}node_t;
#endif
Code:
struct list_t *list_create(){
struct list_t *list = (struct list_t*) malloc(sizeof(struct list_t));
list->head=NULL;
list->size=0;
return list;
}
int list_destroy(struct list_t *list){
node_t *no = list->head;
while(no!=NULL){
node_t *aux=no;
entry_destroy(no->element);
no=no->next;
free(aux);
list->size=(list->size)-1;
}
free(list);
return 0;
}
int list_add(struct list_t *list, struct entry_t *entry){
node_t *no = list->head;
if(no==NULL){
list->head=(node_t*) malloc(sizeof(node_t));
list->head->element=entry_dup(entry);
list->size=list->size+1;
return 0;
}
else{
while(no!=NULL){
no=no->next;
}
no=(node_t*) malloc(sizeof(node_t));
no->element=entry_dup(entry);
list->size=list->size+1;
return 0;
}
return -1;
}
struct entry_t *list_get(struct list_t *list, char *key){
node_t *no = list->head;
while(no!=NULL){
if(strcmp(no->element->key,key)==0){
return no->element;
}
no=no->next;
}
return NULL;
}
When I run these tests it doesn't add the element to the list:
int testEmptyList() {
struct list_t *list = list_create();
int result = list != NULL && list_size(list) == 0;
list_destroy(list);
printf("Test empty list: %s\n",result?"pass":"not pass");
return result;
}
int testAddHead() {
int result;
struct list_t *list = list_create();
struct entry_t *entry = entry_create(strdup("abc"),data_create(5));
memcpy(entry->value->data,"abc1",5);
list_add(list,entry);
result = list_get(list,"abc") == entry &&
list_size(list) == 1;
list_destroy(list);
printf("Module list -> test add first: %s\n",result?"pass":"not pass");
return result;
}
So, what I want is put this code adding elements to the list. Thanks.
Several issues:
You are destroying the list via list_destroy which can call entry_destroy on the entry added to the list before calling list_get which returns a pointer to (not a copy of) an entry.
In list_add you call malloc to allocate space for a new node, however you don't set its next element to NULL. Since malloc does not guarantee that the memory allocated is wiped, the list may never end with a node that has its next element set to NULL resulting in spurious results.
Your else branch in list_add guarantees no will be NULL (or the program will have crashed from a segfault given earlier problems.) You probably want to terminate when no->next is NULL instead of when no is NULL. Also, this branch needs to assign the next element to NULL explicitly.
Try this:
int list_add(struct list_t *list, struct entry_t *entry){
node_t *no = list->head;
if(no==NULL){
list->head=(node_t*) malloc(sizeof(node_t));
list->head->element=entry_dup(entry);
list->size=list->size+1;
return 0;
}
else{
while(no->next!=NULL){
no=no->next;
}
no->next=(node_t*) malloc(sizeof(node_t));
no->next->element=entry_dup(entry);
no->next->next = NULL;
list->size=list->size+1;
return 0;
}
return -1;
}
The problem is that the previous node needs to know the address of the next one, via the pointer next. In your case, no->next will be equal to NULL (after the loop), so it's the last node. You never assign the next pointer of the last node to the new node, so it will be lost.

Double linked list prepend element by ref in 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;
}

Resources