Linked list and pointers - c

I'm trying to pass to a pointer my address of the linked list in main,pass it in a function to allocate memory to it and traverse to the next node while keeping the position of the next node without breaking head node.
typedef struct {
int data;
struct node_list *next;
}node_list;
typedef struct {
struct node_list *head;
}list;
void insert_list(node_list **c, int num);
void main()
{
int num;
list *list_odd = (list*)calloc(1, sizeof(list));
node_list *c = &list_odd->head;
while (num != -1)
{
if (num % 2)
insert_list(c, num);
}
}
void insert_list(node_list **c, int num)
{
if (*c == NULL)
{
*c = (node_list*)malloc(sizeof(node_list)); // it allocates the memory in the right place.
(*c)->data = num;
(*c) = (*c)->next; // but this step breaks the starting list pointer
}
else
{
(*c)->next = (node_list*)malloc(sizeof(node_list));
(*c)->data = num;
(*c) = (*c)->next;
}
}
Edit: I may not explained myself, To clarify: If my list points to the start of the linked-list, while I allocate memory to it and then do (*c) = (*c)->next, my head no longer points to the begging. What I'm trying to achieve is having the start of the list and saving the position of the next node.

I'd like to suggest a two-sided singly linked list.
Here is a demonstrative program.
#include <stdlib.h>
#include <stdio.h>
typedef struct node
{
int data;
struct node *next;
} node;
typedef struct list
{
node *head;
node *tail;
} list;
int push_back( list *lst, int data )
{
node *new_node = malloc( sizeof( node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = data;
new_node->next = NULL;
if ( lst->tail == NULL )
{
lst->tail = lst->head = new_node;
}
else
{
lst->tail = lst->tail->next = new_node;
}
}
return success;
}
void display( list *lst )
{
for ( node *current = lst->head; current != NULL; current = current->next )
{
printf( "%d ", current->data );
}
printf( "\n" );
}
int main( void )
{
list lst = { NULL, NULL };
int data;
while ( scanf( "%d", &data ) == 1 && data != -1 )
{
if ( data % 2 != 0 ) push_back( &lst, data );
}
display( &lst );
return 0;
}
If to enter this sequence of numbers
0 1 2 3 4 5 6 7 8 9 -1
then the output will be
1 3 5 7 9
The complexity of adding a new node to the end of the list is O(1).

What I'm trying to achieve is having the start of the list and saving the position of the next node.
I'm not entirely sure what you're trying to do, so I've made an equivalent program. If you find this way of adding to the list to be too slow, then the program needs to be changed to either keep a {head, tail} pair or add items to the front of the list. From your text it sounds like you're trying to keep the head the same -- so a {head,tail} pair is probably best.
#include <stdlib.h> //added
#include <stdio.h> //added
#include <assert.h>
typedef struct node_list_t { //changed
int data;
struct node_list_t *next; //changed
} node_list;
typedef struct list_t { //gave the struct a tag
node_list *head; //use the typedef name, not the struct name
}list;
void insert_list(list *my_list, int num);
void main()
{
int num = 0; // initialised
list my_list = {0}; // changed to be on stack. Could be calloc'd if you like
node_list* printer;
while (num != 50) //changed limit
{
if (num % 2)
{
// we're just passing in the list
insert_list(&my_list, num);
}
num += 1; //actually incrementing number. :)
}
for (printer = my_list.head;
printer;
printer = printer->next)
{
printf("%d\n", printer->data);
}
}
void insert_list(list *my_list, int num)
{
node_list *c = (node_list*) calloc(1, sizeof(node_list));
c->data = num;
assert(!c->next);
if (!my_list->head)
{
// if the head is not initialised, then make C the head
my_list->head = c;
}
else
{
// otherwise stick it on the end of the list.
node_list *p;
for (p = my_list->head;
p->next;
p = p->next)
{
//do nothing
}
p->next = c;
}
}

Related

Circular Link List program using c

I am just implementing circular linked list program but in this program i am having to face trouble, as you can see I am going to past code below, when I call insertAtLast and isertAtFirst function it's work fine but as soon as I call viewList function to view list item but it shows "there is no items" which I wrote inside if block for run when last is null but in this program I have already inserted two items before viewList call so I think last should not be null because I have already inserted item, I want to print all items of list by viewList function
#include <stdio.h>
#include <stdlib.h>`
#include <conio.h>
struct node {
int item;
struct node *next;
};
void insertAtFirst(struct node **last, int data) {
struct node *n, *t;
n = malloc(sizeof(struct node));
n->item = data;
t = *last;
if(*last == NULL) {
n->next = n;
t = n;
}
else {
n->next = t->next;
t->next = n;
}
}
void insertAtLast(struct node **last, int data) {
struct node *n, *t;
n = malloc(sizeof(struct node));
n->item = data;
t = *last;
if(*last == NULL) {
n->next = n;
t = n;
}
else {
n->next = t->next;
t->next = n;
t = n;
}
}
void viewList(struct node *last) {
struct node *start;
if(last == NULL)
printf("\n there is no items......");
else {
start = last->next;
while(start->next != last->next) {
printf("%d ", start->item);
start = start->next;
}
}
}
int main(){
struct node *last = NULL;
insertAtLast(&last, 3);
insertAtFirst(&last, 5);
viewList(last);
return 0;
}
You should use *last = n instead of t = n.
And that's because the latter just causes the variable t to point to n and that's it. But by doing *last = n you will at least insert a value in the list even if last == NULL I guess that would give the desired output.

Copy a pointer to a struct in a function (linked list)

I want to craete a single linked list without gloabal variables. I initialized the first element with NULL and then wanted to copy the first element node to list_. It is copied in the function but the side effect isnĀ“t working. In my main-function the value is still NULL.
If I return the struct in the add_element()function all works fine but, is it possible that l gets the value of node without changing the functions structure and the struct itself?
#include <stdio.h>
#include <stdlib.h>
struct list {
int value;
struct list *next;
};
struct list *initialize(void)
{
struct list * l = NULL;
return l;
}
int add_element(struct list *list_, void *v)
{
struct list *node = malloc(sizeof(struct list));
node->value = *((int*)v);
node->next = NULL;
if(list_ == NULL)
{
list_ = node;
printf("list_->value = %d\n", list_->value); // correct copy
return 0;
}
//TODO if not first then add at end..
return 0;
}
int main()
{
struct list *l = initialize(); // l = NULL
int i = 10;
add_element(l,&i);
if(l == NULL) printf("l == NULL!\n");
printf("l->value = %d\n", l->value); // does not work, l is NULL
return 0;
}
kaylum's comment points you in the right direction.
When you pass a pointer in C, the pointer's value is copied to the stack, and this copy is the value that the add_element() function is referring to. When you alter the pointer's value, you are modifying the copy placed on the stack, not the original pointer.
If you want to alter the original pointer (as if it was passed by reference and not by value) you need to use a double pointer.
Try this variant:
int add_element(struct list **list_, void *v)
{
struct list *node = malloc(sizeof(struct list));
node->value = *((int*)v);
node->next = NULL;
if(*list_ == NULL) // dereferencing the double pointer will access the original pointer
{
*list_ = node; // this will change the original pointer
printf("(*list_)->value = %d\n", (*list_)->value); // correct copy
return 0;
}
//TODO if not first then add at end..
return 0;
}
int main()
{
struct list *l = initialize(); // l = NULL
int i = 10;
add_element(&l,&i); // notice you are now passing the address of l instead of its value
if(l == NULL) printf("l == NULL!\n");
printf("l->value = %d\n", l->value); //should work now
return 0;
}
For starters the function initialize
struct list *initialize(void)
{
struct list * l = NULL;
return l;
}
does not make great sense. You can just write in main
struct list *l = NULL;
Or the function initialize can look like
inline struct list *initialize(void)
{
return NULL;
}
The function add_element deals with a copy of the passed list.
int add_element(struct list *list_, void *v);
So any changes of the copy do not influence on the original list. Also it is unclear why the second parameter has the type void * instead of the type int.
You have to pass the list by reference to the function.
The function can look the following way
int add_element( struct list **head, int value )
{
struct list *node = malloc( sizeof( struct list ) );
int success = node != NULL;
if ( success )
{
node->value = value;
node->next = NULL;
while ( *head != NULL ) head = &( *head )->next;
*head = node;
}
return success;
}
and called for example like
int i = 10;
if ( !add_element( &l, i ) )
{
puts( "Error: not enough memory." );
}
Here is a demonstrative program
#include <stdio.h>
#include <stdlib.h>
struct list
{
int value;
struct list *next;
};
static inline struct list * initialize( void )
{
return NULL;
}
int add_element( struct list **head, int value )
{
struct list *node = malloc( sizeof( struct list ) );
int success = node != NULL;
if ( success )
{
node->value = value;
node->next = NULL;
while ( *head != NULL ) head = &( *head )->next;
*head = node;
}
return success;
}
void output( struct list *head )
{
for ( ; head != NULL; head = head->next )
{
printf( "%d -> ", head->value );
}
puts( "NULL" );
}
int main(void)
{
struct list *head = initialize();
const int N = 10;
for ( int i = 0; i < N; i++ )
{
add_element( &head, i );
}
output( head );
return 0;
}
Its output is
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> NULL
Pay attention to that if a new node is appended to the tail of the list then it is better to define the list as a two-sided singly-linked list.

why does my LinkListCreate function stop running?

I want to creat a link list by CreateLinkList(LinkList *L, int n), but the output of printf is 0 1 only.
It seems to stop at line 3 in CreateLinkList.
How can I fix it?
void CreateLinkList(LinkList *L, int n)
{
srand(time(0));
printf("1\n");
*L = (Node*)malloc(sizeof(Node)); \\ it seems to stop here
printf("2\n");
Node *flag = *L;
printf("3\n");
for (int i=0; i<n; i++)
{
Node *newNode = (Node*)malloc(sizeof(Node));
newNode->data = rand() %100+1;
flag->next = newNode;
flag = newNode;
}
printf("4\n");
flag->next = NULL;
printf("5\n");
}
int main()
{
LinkList *p;
printf("0");
CreateLinkList(p, 10);
return 0;
}
The LinkList and Node were defined as:
typedef struct
{
int data;
struct Node *next;
} Node;
typedef Node *LinkList;
For starters this structure definition
typedef struct
{
int data;
struct Node *next;
} Node;
is invalid. Within the structure the type struct Node * is not the same as the typedef name Node.
Write instead
typedef struct Node
{
int data;
struct Node *next;
} Node;
Neither the node L nor the node flag are initialized.
*L = (Node*)malloc(sizeof(Node)); \\ it seems to stop here
printf("2\n");
Node *flag = *L;
So this statement
flag->next = newNode;
invokes undefined behavior.
Moreover the pointer p is not also initialized in main
LinkList *p;
So even this call
*L = (Node*)malloc(sizeof(Node));
also invokes undefined behavior.
In any case it is a bad idea to use such a typedef like
typedef Node *LinkList;
because it only confuses readers of the code.
The function can be defined as it is shown in the demonstrative program.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct Node
{
int data;
struct Node *next;
} Node;
typedef Node *LinkList;
void CreateLinkList( LinkList *head, unsigned int n )
{
const int MAX_VALUE = 100;
srand( ( unsigned int )time( NULL ) );
for ( unsigned int i = 0; i < n; i++ )
{
*head = malloc( sizeof( Node ) );
( *head )->data = rand() % MAX_VALUE + 1;
( *head )->next = NULL;
head = &( *head )->next;
}
}
void print( LinkList head )
{
for ( ; head != NULL; head = head->next )
{
printf( "%d -> ", head->data );
}
puts( "NULL" );
}
int main(void)
{
LinkList head = NULL;
CreateLinkList( &head, 10 );
print( head );
return 0;
}
The program output might look like
14 -> 40 -> 17 -> 54 -> 8 -> 48 -> 40 -> 25 -> 99 -> 41 -> NULL

Structure pointer assignment not assigning expected value - Linked Lists

I'm writing a program to reverse a linked list in C. While debugging code in gdb, after the second iteration of while loop, function,reverse, take exit.
#include <stdio.h>
#include <stdlib.h>
void insert (int number);
void print ();
struct Node {
int data;
struct Node *link;
} head, *last_node;
int count (struct Node *);
void reverse (struct Node *);
int main () {
int number, choice = 0;
while (choice != 4) {
printf ("\nChoose the action: ");
printf ("\n 1. Insert ");
printf ("\n 2. Print List ");
printf ("\n 3. Reverse");
printf ("\n 4. Exit \n");
scanf("%d", &choice);
switch (choice) {
case 1 : printf ("\nEnter number to be inserted: ");
scanf ("%d", &number);
insert (number);
break;
case 2 : printf ("\nHere is/are linked list element/s: ");
print();
break;
case 3 : printf ("\nLinked List Reversed ");
reverse(&head);
break;
case 4 :
default: exit(0);
}
}
}
void insert (int number) {
if (head.data == 0) {
head.data = number;
head.link = NULL;
last_node = &head;
} else {
struct Node *new_node;
new_node = (struct Node *) malloc (sizeof(struct Node));
new_node -> data = number;
new_node -> link = NULL;
last_node -> link = new_node;
last_node = new_node;
}
}
void print () {
struct Node *start;
start = &head;
do {
printf ("%d ", start->data);
start = start->link;
} while (start != NULL);
printf ("\n");
}
void reverse (struct Node *start) {
struct Node *temp1 = NULL, *temp2;
while (start->link != NULL) {
temp2 = start->link;
start->link = temp1;
temp1 = start;
start = temp2;
}
}
After running reverse function only first element of linked list shows.
There are several drawbacks of your approach.
The first one is that it is a bad idea to declare a global variable start.
struct Node {
int data;
struct Node *link;
} head, *last_node;
Also if it is a singly-linked list then nodes should be inserted to the beginning of the list. So the global pointer last_node is not required.
The function reverse deals with the local variable start because function parameters are local variables of functions
void reverse (struct Node *start)
The original pointer to the start node is not changed in the function because the function deals with its copy.
And the function has to check whether the passed argument is already equal to NULL.
There is a simple logic behind the reverse algorithm.
You should just insert already existent nodes as if you would do this within the function that pushes new nodes into list.
And the pointer to the start node (head) must be passed by reference using a pointer to it.
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *link;
};
int push_front( struct Node **head, int data )
{
struct Node *current = malloc( sizeof( struct Node ) );
int success = current != NULL;
if ( success )
{
current->data = data;
current->link = *head;
*head = current;
}
return success;
}
void output( struct Node *head )
{
for ( ; head != NULL; head = head->link )
{
printf( "%d -> ", head->data );
}
puts( "NULL" );
}
void reverse( struct Node **head )
{
struct Node *current = *head;
*head = NULL;
while ( current != NULL )
{
struct Node *tmp = current;
current = current->link;
tmp->link = *head;
*head = tmp;
}
}
int main(void)
{
struct Node *head = NULL;
const int N = 10;
for ( int i = 0; i < N; i++ ) push_front( &head, i );
output( head );
reverse( &head );
output( head );
return 0;
}
Its output is
9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0 -> NULL
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> NULL
Of course you need to append the list implementation with a function that deletes all nodes of the list when it is not anymore required.

A linked list to alphabetize strings

In the lab work I am doing, it is supposed to allow a user to input strings into a linked list one by one until the user doesn't input a string. At this point the program will then compare each string by the first letter, alphabetize them, and then display them.
I know I have to use strcmp to compare two strings at a time, I've tried to understand this but it is just so complicated.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define StringLengthMAX 80
struct node_link
{
//char node_string[StringLengthMAX];
int num;
struct node_link *next;
};
int compare_node(struct node_link *b1, struct node_link *b2)
{
//strcmp(*b1, *b2);
if (b1 -> num < b2 -> num)
{
return -1;
}
if (b1 -> num == b2 -> num)
{
return 0;
}
if (b1 -> num > b2 -> num)
{
return 1;
}
}
struct node_link *add_node(struct node_link *list, struct node_link *node)
{
struct node_link *cur_node=list;
//case 1 : When list->num > node->num
if (compare_node(list, node) == 1)
{
node -> next = list;
list = node;
return list;
}
// case 2
while(cur_node->next != NULL)
{
if (compare_node(cur_node->next,node) == 1)
{
node -> next = cur_node -> next;
cur_node->next = node;
break;
}
else
{
cur_node = cur_node -> next;
}
}
// case 3 : node->next is the greatest
if (cur_node -> next == NULL)
{
cur_node->next = node;
}
return list;
}
void display_newlist(struct node_link *head)
{
struct node_link *node=head;
while(node != NULL)
{
printf("%d", node->num);
node = node->next;
printf(" ");
}
}
int main()
{
int a;
struct node_link *head;
struct node_link *node;
node = (struct node_link*)malloc(sizeof(struct node_link));
node->num = a;
node->next = NULL;
head = node;
do
{
puts("Please enter any number of integers, end inputs with a ZERO (0): ");
scanf("%d", &a);
node = (struct node_link*)malloc(sizeof(struct node_link));
node->num = a;
node->next = NULL;
head = add_node(head,node);
}while(a != 0);
display_newlist(head);
return 0;
}
You can do that by this way
1- Replace that int num with any array of character
2- in compare function try to compare elements of the char array using strcmp function then return values according to that from compare() function.
3- Replace evry num by array of character variable

Resources