Singly Linked List creation problem without using a function - c

//linked_list_1
#include<stdio.h>
#include<stdlib.h>
struct list
{
int data;
struct list *link;
};
int main()
{
struct list *ll=NULL, *tp=NULL;
int n=3, i;
ll=(struct list *)malloc(sizeof(struct list));
scanf("%d",&ll->data);
for(i=1; i<n; i++)
{
tp=(struct list *)malloc(sizeof(struct list));
scanf("%d",&tp->data);
ll->link=tp;
ll=ll->link;
}
ll->link=NULL;
while(ll)
{
printf("\n%d",ll->data);
ll=ll->link;
}
}
//linked_list_2
#include<stdio.h>
#include<stdlib.h>
struct list
{
int data;
struct list *link;
};
void linked_list(struct list *,int);
int main()
{
struct list *ll=NULL;
int n=3;
ll=(struct list *)malloc(sizeof(struct list));
linked_list(ll,n);
while(ll)
{
printf("\n%d",ll->data);
ll=ll->link;
}
}
void linked_list(struct list *kk, int n)
{
struct list *tp=NULL;
int i;
scanf("%d",&kk->data);
for(i=1; i<n; i++)
{
tp=(struct list *)malloc(sizeof(struct list));
scanf("%d",&tp->data);
kk->link=tp;
kk=kk->link;
}
kk->link=NULL;
}
Both the programs are same, the second program is linked list creation using a function: void linked_list(struct list *kk, int n) The first program is also linked list creation but without any function. Second program is working properly but the first program is not working in the right way.
If the inputs are 2 5 4 for both the programs, second program output is 2 5 4 but the first program output is only 4.
Why the first program is not working in the right way? What is the reason?

The problem with the first program is that you are moving the head of the linked list while you are taking the input. So when you are done taking the inputs basically the head of the linked list is now at the last node of it. Then when you are trying to print out the linked list you are just getting the last node of it since the head got moved to there when you took the last input.
Ideally you should use the temporary pointer, align it with the head pointer of the linked list and then take the input, assign it and move it and keep on building the linked list using it only. The head pointer (here ll) of the linked list once initialized should not be move like this:
ll=ll->link; //Wrong!
Until it is absolutely required to do so. This will result in a truncated linked list and you will lose your nodes.
Ideally your code should be something like this:
ll=(struct list *)malloc(sizeof(struct list));
tp = ll; //Align the temporary pointer with the head of the linked list.
scanf("%d",&tp->data);
for(i=1; i<n; i++)
{
//Allocate memory to the link of the temporary pointer since it is also a type of struct list.
tp->link=(struct list *)malloc(sizeof(struct list));
scanf("%d",&tp->link->data);
tp = tp->link; //Move only the temporary pointer.
}
tp->link=NULL; //Finally assign NULL when done taking inputs.
Notice carefully I am only using the temporary pointer to do everything.
The reason why the second program works is because you are passing the address of the head pointer to the function that you are using to build the linked list. Now this function gets a copy of the address in kk that is the starting address of the linked list and builds the linked list there using it. But back in the main() the ll pointer is still holding the original address where you initially allocated the memory. Hence after constructing the linked list when you are back in the main() to print it, you start with the actual head of the linked list still hold by ll and you are able to print out the entire linked list.
But this still has the same flaw that I mentioned earlier. You are moving the head of the linked list while printing it (i.e. ll).
while(ll)
{
printf("\n%d",ll->data);
ll=ll->link; //This is wrong!
}
So after you are done printing the linked list your head of the linked list is now NULL. So if you want to do something with the actual linked list after printing it, it is now not possible since you have made the head NULL. So again the solution is use a temporary pointer align it with the head of the linked list and then use it to print out the linked list. Something like this:
struct list *tp = ll;
while(tp)
{
printf("\n%d",tp->data);
tp=tp->link;
}

Related

Not able to create a second doubly linked list

So I have created two structures LIST (consists of head and last pointer) and NODE (consists of next and previous pointer). I have a function create_list (LIST *p) that does the following:
Sets the head and last pointer to NULL
Asks the user to enter the no of nodes for the list and also lets user enter the value and it inserts a node in an orderly manner (increasing order)
Once done, it displays the list
So I created two LIST pointer variables and tried making two doubly linked list, it works perfectly for the first list but the second list does not get initialized.
Here is the code:
void create_list(LIST *p){
int x;
printf("enter no of elements to enter\n");
scanf("%d", &x);
printf("creating a list of size %d\n", x);
p->head =NULL;
p->last=NULL;
printf("initialised list\n");
for(int i =0; i<x; i++){
ins(p);
}
display(p);
}
int main(){
LIST* list1, *list2;
create_list(list1);
create_list(list2);
return 0;
}
LIST* list1, *list2; isn't doing what you think its doing. These pointers are pointing at a random location in memory. They need to point at a LIST type somewhere. In other words, there is no LIST in existence in your code. This is undefined behavior, so the fact that the first one initialized correctly was only by chance.
For example, if I wanted them to exist in main's stack:
LIST list1, list2;
create_list(&list1);
create_list(&list2);
Now 2 LISTs exist, and we have passed their addresses to create_list.

How to print linked list node top to bottom

I am trying to make linked list. I can add node one by one but I could not print the linked list as i wanted. How to print linked list node from top to bottom
#include<stdio.h>
#include<stdlib.h>
struct node{
int N;
struct node *next;
};
struct node* newNode(int number, struct node *next) {
struct node *new = malloc(sizeof(*new));
new->N = number;
new->next = next;
return new;
}
void show(struct node *head){
struct node *c;
c = head;
while (c!=NULL){
printf("%d\n",c->N);
c = c->next;
}
}
int main (void ) {
struct node *head = NULL;
head = newNode(10, head);
head = newNode(20, head);
head = newNode(30, head);
head = newNode(40, head);
show(head);
return 0;
}
Output
40
30
20
10
I am trying to print node like below
10
20
30
40
How to get above output ?
Since I understand this is probably part of an excercise, I will attempt to answer it in the style of assistance, while still giving a comprehensive answer.
I let aside the fact that you insert your elements in the head - which I am not sure it is what you want to do, and I consider the question as "How to print it backwards, once I have entered the elements correctly?".
We have to examine possible solutions on this:
1) Create a method void addToTail(Node* head, int value); That traverses the list and adds elements to the tail of the list instead of the head. Side note: this operation is time costly, as it requires O(N) time complexity. About complexities, read more here. Se also this StackOverflow question.
2) You mention the term "linked list". By what you say, you do not specify if it is a singly linked, or a doubly linked. And since you have access to the node implementation, I suggest that you add a pointer to each node that points to the previous element, thus converting your singly-linked list to a doubly-linked one.
struct node{
int N;
struct node *next;
struct node *prev;
};
And, of course, you need to update this node respectively in the operations of your list - otherwise it will not work - I let this to you.
That way, you will be able to easily iterate the list backwards then in order to print the number in the order desired.
3) You could implement a function Node * reverseList(Node* head); that "reverses" a list via iteration, and then use it to print the list reversed.
And again, I let the implementation to you. Of, course, you need to consider the list state on each time, as also if you need to reverse the list in-place or return a pointer to a new, reversed list (as the function contract above indicates).
What you need to do now, is re-read your excercise brief, stop for a moment and think: "Do I really need these solutions? Is this what is requested from me?".
If you are just entering the data in the wrong order, probably not.
But if it is specifically required from you to print the list elements backwards, then you have some good hints on how to proceed.
Recursive approach works great here:
void show(struct node *c){
if (c == NULL)
return;
show(c->next);
printf("%d\n", c->N);
}

Reverse the pointers in a linked list

Hello guys could you please help me in writing a procedure to reverse the pointers in a linked list . for example A->B->C->D would become A<-B<-C<-D without using extra linked list .
Edit:
------ okay guys so i have been looking for solution for this problem here is the code in case u want it :
void reverse_list(){
struct node *next, *current,*previous;
previous = NULL;
current =head;
while(current != NULL){
next = current->next;
current->next = previous;
previous=current;
current = next;
}
head = previous;
}
You could think of the list as a stack. Then you could easily reverse such a list by "popping" the nodes and "pushing" them into a new list.
The above could be done both destructively (destroying the old list) and non-destructively (creating the new list as a reversed copy of the original list).
As you didn't mention if you are implementing the linked list yourself or not.
So firstly I am assuming that you are doing it by yourself. So following is an implementation of linked list and again its pointers are reversed to make the link list reverse. You can take an idea from it.
#include<stdio.h>
#include<stdlib.h>//for using malloc
struct Node//Defining a structure for linked list's node
{
int info;//assuming it is an integer linked list
struct Node *link;//this pointer links a node to it's immediate neighbor node
};
struct Node *head=NULL,*temp;//some initializations and declarations
void insertion(int data)//To insert elements to linked list
{
struct Node *ptr;
ptr=malloc(sizeof(*ptr));//creating a new node for the newcomer
ptr->info=data;//taking the given integer value for the node to hold
//initializing with null as the current node may be the last node and
//if it is then it will point nobody
//...but if it is not when a new node comes in the future it will eventually be
//replaced to point the newcomer
ptr->link=NULL;
if(head==NULL)//head still null means we are creating the first node
{ //handling the head separately as it has no parent node
head=ptr;
temp=ptr;//copying the current node's pointer to temp such that we can
//find it as a parent of next node
}
else//for the rest of the nodes' creation
{
//as temp is the pointer to the previous node, so previous node is linking
//to its next node, i.e, the current node
temp->link=ptr;
//updating the temp to point the current node such that it can act as a parent node
//when the next node comes
temp=ptr;
}
}
void reversePointers()
{
struct Node *trav,*from=NULL,*temp;
for(trav=head;;)
{
if(trav->link==NULL)//if we have reached to the end
{
head=trav;//then the reverse linked list's head should point to the last element
trav->link=from;//and making the second last node as it's next node
break;
}
temp=trav;//saving current node pointer to update the "from" pointer
trav=trav->link;//advancing current node pointer to forward
temp->link=from;//making the current node to point to it's previous node
from=temp;//saving current node's pointer which will be used in next iteration
}
}
void traverse()//to traverse the nodes
{
struct Node *ptr=head;
while(ptr!=NULL)
{
printf("%d ",ptr->info);
ptr=ptr->link;
}
printf("\n");
}
int main(void)
{
int i,n,t;
printf("Enter Number of elements: ");
scanf("%d",&n);
printf("Enter Elements: ");
for(i=0;i<n;i++)
{
scanf("%d",&t);
insertion(t);
}
printf("Before reversing the pointers the elements are: ");
traverse();
//let's reverse the pointers to make the list to go backward
reversePointers();
printf("After reversing the pointers the elements are: ");
traverse();
}
Secondly if you are using STL list then the approach is quite straightforward. Just use,
your_list_name.reverse()
Again if you want to reverse the STL list just for iteration purpose then there is no need to actually reverse it. Instead you can use reverse iterator as following (say for an integer list):
for(list<int>::reverse_iterator it=your_list_name.rbegin();it!=your_list_name.rend();it++)
{
//do whatever you want
}

Allocating memory for a array of linked lists

Hi guys I'm new to linked lists, but I'm pretty sure that I know how they work, theoretically, I think I might having a syntax misunderstanding, or memory management error.
edit: My main purpose is to make a collection of lists which are indexed by the array, each array element is a head(or root) node. I'm having issues allocation dynamically this struct array.
What I'm doing is the following:
typedef struct item_list{
int item_name;
int item_supplier;
int item_price;
struct item_list *next
}node;
int i;
node ** shop_1 = (node **)malloc(shop_items_elements * sizeof(node));
for (i=0;i<=shop_items_elements;i++)
{
shop_1[i]->next=NULL;
}
I'm getting a segmentation fault while I try to give next at the element i the value of NULL.
The problem is that you are trying to allocate the memory for 20000 items as a contiguous block. Which implies that you actually haven't understood linked lists yet.
I think you are mixing up random access array functionality with pure linked lists which do not allow accessing individual items without traversing the list.
A linked list usually has a head and tail node which are initially NULL when there are no elements in the list:
node* head = NULL;
node* tail = NULL;
When adding a new node you first allocate it by using malloc with the size of a single node struct:
node* the_new_node = (node*)malloc(sizeof(node));
Initialize the struct members, specifically set next to NULL for each new node. Then use this append_node() function to append the node to the linked list:
void append_node(node** head, node** tail, node* the_new_node)
{
if(*tail == NULL)
{ // list was empty
*head = *tail = the_new_node;
}
else
{
(*tail)->next = the_new_node; // link previous tail node with new one
*tail = the_new_node; // set the tail pointer to the new node
}
Please note the pointer to pointers which are needed to update the head and tail pointers. Call the function like this for any given n you want to add:
append_node(&head, &tail, n);
Repeat this for every new node.
A much better way of encapsulating a linked list is putting the head and tail pointers into another struct
typedef struct linked_list
{
node* head;
node* tail;
} list;
and using an instance of that as first argument to append_node() (which I'll leave to you as an exercise ;)
When using such a linked list it is not possible to conveniently access the Nth node in less than O(n) since you have to follow all next pointers starting from the head node until you arrive at the Nth node.
EDIT: If you want to have the possibility to index the shop items and build a linked list from each of the elements I would suggest the following solution:
node** shop_1 = (node**)malloc(shop_items_elements * sizeof(node*));
int i;
for(i = 0; i < shop_items_elements; ++i)
{
node* n = (node*)malloc(sizeof(node));
n->next = NULL;
shop_1[i] = n;
}
You first allocate an array of pointers to node pointers which have to be allocated individually of course. Take a look at this diagram for reference:
The actual node instances may be larger than a pointer's size (unlike drawn in the diagram) which is the reason why you allocate N * sizeof(node*) in a block instead of N * sizeof(node).
Your code needs to look like this
int i;
node * shop_1 = (node *)malloc(shop_items_elements * sizeof(node));
for (i=0;i<shop_items_elements;++i)
{
shop_1[i].next=NULL;
}
Your malloc statement has allocated an array of nodes, not an array of pointers to nodes. (If that is what you wanted instead, then you would have had to initialize each pointer with a further malloc call before trying to assign a value to a field within the node pointed to.)

More than 1 linked list - Adding elements

I need to make a program that has (at most) 50 linked lists. Basically, my program generates some messages and based on a indicator that comes in the front of my string, I need to put the message in the right linked list.
I don't know if it is clear enough but I will try to show part of my code (the important part). The function I made to add a new element (on the top) of the linked list is the following:
void InsertLL (News p, char M[]) {
char * text = malloc(strlen(M)+1);
strcpy(text, M);
News s,t;
t = malloc(sizeof(struct List));
t-> Text = text;
s = p;
p = t;
p-> next = s;
}
My struct List (the type of the elements of my lists) contains a char pointer (called text) and a pointer to the next element of the list.
Simulating my program, suppose that I received a message that needs to be put in the linked list where the begin is pointed by the pointer p[0]. So I create a new element (forget the case that the list is empty, I already made this one) and add in the top of my list using the function I've shown.
Now, suppose that I received another message that needs to be put in the next pointer p[1]. If I print p[0] -> Text, I get the text of p[1]->Text.
I mean, if I add a new element in the list pointed by p[i], all the previous texts p[i] -> Texts gets the new text of this new element. I have no idea what am I doing wrong.
I don't know if it is enough to help me, if more information is needed, just tell me.
Problem with your code is you are not maintaining the list of nodes. you are overwriting the same node again and again.
Algo:
If no node then create one.
If nodes are present then navigate to end node.(You can use tail
pointer for quicker access).
Append the node at the end.
Creating Node:
Declare a node type pointer.
Allocate memory to it.
Update the content of the node.
Set the next pointer of the node to null.
Add this node to end of the list.
ex. inserting node 3 in the list of node 1 and node 2.
This is the general approach that you can use
typedef struct node{
int val; //you can use your text here
struct node* next;
}NODE;
struct node* head=0;
int addNode(int v){
if(head==0){ //checking for empty node.
struct node* n=malloc(sizeof(NODE));
n->val=v;
head=n;
}
else{
struct node* temp=head;
while(temp->next != 0) //Navigating till end
{
temp=temp->next;
}
struct node* n=malloc(sizeof(NODE)); //allocating memory
n->val=v; //you need to use strcpy for string here.
temp->next=n; //adjusting pointers
n->next=0;
}
}
You can check this demo created by me for Double linked List http://ideone.com/s6TtUX

Resources