Linked List - Implementation - c

I'm basically trying to implement LinkedList in C but I still can't get it I will leave my code below so you can see what I'm missing:
#include <stdio.h>
#include <stdlib.h>
struct Node {
int val;
struct Node *Next;
};
struct Node *head;
void insert(int x);
void print();
int main() {
head = NULL;
int d, i = 0, f;
printf("How many number you want to insert:\n");
scanf("%d", &d);
for (i; i < d; i++) {
printf("Enter your number:\n");
scanf("%d", &f);
insert(f);
print();
}
return 0;
}
void insert(int x) {
struct Node *A = (struct Node *)malloc(sizeof(struct Node));
if (head == NULL) {
A->val = x;
A->Next = head;
head = A;
return;
}
A->val = x;
A->Next = head->Next;
}
void print() {
printf("[");
struct Node *B = head;
while (B->Next != NULL) {
B = B->Next;
printf("%d", B->val);
}
printf("]\n");
}
I need some pointers to where I missed up.

Here are the two ways to insert, either at the front/head of the list or the back/tail of the list:
void
insert_front(int x)
{
struct Node *A = malloc(sizeof(*A));
A->val = x;
A->Next = head;
head = A;
}
void
insert_back(int x)
{
struct Node *A = malloc(sizeof(*A));
A->val = x;
A->Next = NULL;
struct Node *prev = NULL;
for (struct Node *cur = head; cur != NULL; cur = cur->Next)
prev = cur;
if (prev != NULL)
prev->Next = A;
else
head = A;
}

The print() function is incorrect: it misses the first node and would crash on an empty list:
void print() {
printf("[");
struct Node *B = head;
while (B != NULL) {
printf(" %d", B->val);
B = B->Next;
}
printf(" ]\n");
}
The insert() function also has problems: only the first node is correctly inserted. Here is a modified version:
// insert a node in front of the list.
void insert(int x) {
struct Node *A = (struct Node *)malloc(sizeof(struct Node));
if (A != NULL) {
A->val = x;
A->Next = head;
head = A;
}
}

Related

Garbage value for certain C functions

I'm learning C and I'm trying to make a program with multiple linked list operations all at once. They don't give me errors, but for the functions to delete a node at the end, and to insert at a certain position, I'm getting a garbage value at the beginning of the output.
Temporary program to implement just the insert function:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node* next;
};
void inp(struct node **start, int ele)
{
struct node *NEW = (struct node*)malloc(sizeof(struct node));
NEW->data = ele;
struct node *ptr = *start;
while(ptr != NULL)
{
if(ptr->next == NULL)
{
ptr->next = NEW;
NEW->next = NULL;
break;
}
ptr = ptr->next;
}
}
void insert_pos(struct node **start, int ele, int pos)
{
struct node *ptr = *start;
for(int i = 1; i < pos; i++)
{
ptr = ptr->next;
}
struct node *NEW = (struct node*)malloc(sizeof(struct node));
NEW->data = ele;
NEW->next = ptr->next;
ptr->next = NEW;
}
void display(struct node* start)
{
struct node* ptr = start;
while(ptr != NULL)
{
printf("%d\n", ptr->data);
ptr = ptr->next;
}
}
int main()
{
struct node *a;
int m;
for(int i = 0; i < 10; i++)
{
scanf("%d", &m);
inp(&a, m);
}
insert_pos(&a, 594, 3);
printf("\n\n");
display(a);
}
Temporary program to delete at the end:
//Temporary
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node* next;
};
void inp(struct node **start, int ele)
{
struct node *NEW = (struct node*)malloc(sizeof(struct node));
NEW->data = ele;
struct node *ptr = *start;
while(ptr != NULL)
{
if(ptr->next == NULL)
{
ptr->next = NEW;
NEW->next = NULL;
break;
}
ptr = ptr->next;
}
}
void del_end(struct node **start)
{
struct node *ptr = *start;
while(ptr != NULL)
{
if(ptr->next->next == NULL)
{
ptr->next = NULL;
free(ptr->next->next);
break;
}
ptr = ptr->next;
}
}
void display(struct node* start)
{
struct node* ptr = start;
while(ptr != NULL)
{
printf("%d\n", ptr->data);
ptr = ptr->next;
}
}
int main()
{
struct node *a;
int m;
for(int i = 0; i < 10; i++)
{
scanf("%d", &m);
inp(&a, m);
}
del_end(&a);
printf("\n\n");
display(a);
}
Any idea how to fix it?
you can see that in here:
The inp problem:
struct node *a;
puts a garbage value in a that you don't handle and uses it like a node,
add =NULL to solve.
also, your function that deletes from the end has the following error:
struct node *ptr = *start;
while(ptr != NULL)
{
if(ptr->next->next == NULL)
{
ptr->nexStack Overflow for Teams – Collaborate and share knowledge with a private group.t = NULL;
free(ptr->next->next);
break;
}
ptr = ptr->next;
}
you are changing ptr-> next and than accessing ptr->next->next...

Can you please help me resolve this ReverseRange Function?

I was trying to write a function ReverseRange(struct Node **head, int x, int y) which will reverse a linked list in given range of indices int x and int y. I used a previously defined function Reverse() in one of condition in ReverseRange() but it is not reversing the given list, only printing only one Node with data 'Q'. I don't know if the error is in Print() or Reverse() or ReverseRange() or elsewhere. Please help, Thank you.
#include <stdio.h>
#include <stdlib.h>
struct Node {
char data;
struct Node *next;
};
//insert data in the node
void Insert(struct Node **Head, char data) {
struct Node *temp = (struct Node *)malloc(sizeof(struct Node));
temp->data = data;
temp->next = *Head;
*Head = temp;
}
//find length of linked list
int LengthRec(struct Node *head) {
if (head == NULL)
return 0;
return 1 + LengthRec(head->next);
}
//Reverse a linked list when head is given;
void Reverse(struct Node **head) {
struct Node *prev = NULL;
struct Node *curr = *head;
struct Node *next = NULL;
while (curr != NULL) {
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
*head = prev;
}
//Reverse list in range x to y;
int ReverseRange(struct Node **H, int x, int y) {
struct Node *Head = *H;
if (Head == NULL)
return -1;
else if (Head->next == NULL)
return -1;
else if (x == y)
return -1;
else if (x > y)
return -1;
else if (LengthRec(Head) >= y) {
if (x == 1 && y == LengthRec(Head)) {
Reverse(&Head);
return 1;
}
/* NOTE::
Code is incomplete, because I found error before
the entire code is written,
*/
}
}
void Print(struct Node **H) {
struct Node *head = *H;
if (head == NULL) {
printf("Head=NULL");
return;
}
printf("\n %c", head->data);
while (head->next != NULL) {
head = head->next;
printf("\t%c", head->data);
}
}
int main() {
struct Node *Head = NULL;
Insert(&Head, 'Q');
Insert(&Head, 'W');
Insert(&Head, 'E');
Insert(&Head, 'R');
Insert(&Head, 'T');
Print(&Head);
Reverse(&Head);
Print(&Head);
ReverseRange(&Head, 1, 5);
Print(&Head);
}
Output:
T R E W Q
Q W E R T
Q
The Reverse function seems fine, but it should be called with H as an argument from ReverseRange(), not &Head which is a local variable.
Some of the explicit tests at the beginning of the function correspond to legitimate arguments, and should not return an error value.
Note also that you should document the precise semantics for x and y: it is not idiomatic in C to use 1 to designate the first element of a collection, 0 is mote common. y seems included, which is not idiomatic either but consistent with using 1 for the first element.
Your LengthRec function is very inefficient and may cause a stack overflow for very long lists. Use a loop instead of recursing as this recursion is not a tail recursion.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
struct Node {
char data;
struct Node *next;
};
//insert data in the node
void Insert(struct Node **Head, char data) {
struct Node *temp = (struct Node *)malloc(sizeof(struct Node));
temp->data = data;
temp->next = *Head;
*Head = temp;
}
//find length of linked list
int ListLength(const struct Node *head) {
int length = 0;
while (head != NULL) {
length++;
head = head->next;
}
return length;
}
//Reverse a linked list when head is given;
void Reverse(struct Node **head) {
struct Node *prev = NULL;
struct Node *curr = *head;
while (curr != NULL) {
struct Node *next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
*head = prev;
}
//Reverse list in range x to y;
int ReverseRange(struct Node **H, int x, int y) {
int length = ListLength(*H);
if (x < 1 || x > length || x > y || y > length)
return -1;
if (x == y)
return 1;
if (x == 1 && y == length) {
Reverse(H);
return 1;
} else {
struct Node **head = H;
struct Node *prev = NULL;
struct Node *curr = *head;
struct Node *last;
while (x > 1) {
head = &curr->next;
curr = *head;
x--;
y--;
}
last = curr;
while (x <= y) {
struct Node *next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
x++;
}
last->next = curr;
*head = prev;
return 1;
}
}
void Print(const char *msg, const struct Node *head) {
if (msg) {
printf("%s", msg);
}
if (head == NULL) {
printf("Head=NULL\n");
return;
}
printf("%c", head->data);
while (head->next != NULL) {
head = head->next;
printf("\t%c", head->data);
}
printf("\n");
}
int main() {
struct Node *Head = NULL;
Insert(&Head, 'E');
Insert(&Head, 'D');
Insert(&Head, 'C');
Insert(&Head, 'B');
Insert(&Head, 'A');
Print(" Initial list:\t", Head);
Reverse(&Head);
Print(" Reverse(&Head):\t", Head);
ReverseRange(&Head, 1, 5);
Print("ReverseRange(&Head,1,5):\t", Head);
ReverseRange(&Head, 1, 1);
Print("ReverseRange(&Head,1,1):\t", Head);
ReverseRange(&Head, 2, 4);
Print("ReverseRange(&Head,2,4):\t", Head);
return 0;
}
Output:
Initial list: A B C D E
Reverse(&Head): E D C B A ReverseRange(&Head,1,5): A B C D E
ReverseRange(&Head,1,1): A B C D E
ReverseRange(&Head,2,4): A D C B E

Sort a Linked list using C

I am trying to sort a Linked list, but not able to do it. Below is my code. Can anyone help me. I have seen some programs too, which sort linked list and their approach is also like this only.
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
int push(struct node **h, int x)
{
struct node *temp = (struct node*)malloc(sizeof(struct node));
temp->data = x;
temp->next = *h;
*h = temp;
return 0;
}
void print(struct node *head)
{
struct node *temp = head;
while(temp != NULL)
{
printf("%d ",temp->data);
temp = temp->next;
}
printf("\n");
}
void sort(struct node **h)
{
int i,j,a;
struct node *temp1;
struct node *temp2;
for(temp1=*h;temp1!=NULL;temp1=temp1->next)
{
for(temp2=temp1->next;temp2!=NULL;temp2=temp2->next)
{
a = temp1->data;
temp1->data = temp2->data;
temp2->data = a;
}
}
}
int main()
{
struct node * head = NULL;
push(&head,5);
push(&head,4);
push(&head,6);
push(&head,2);
push(&head,9);
printf("List is : ");
print(head);
sort(&head);
printf("after sorting list is : ");
print(head);
return 0;
}
Below is the output which i am getting :
List is : 9 2 6 4 5
after sorting list is : 5 4 6 2 9
You're switching the elements no matter what. Compare them first and then swap them if temp2 is less than temp1:
void sort(struct node **h)
{
int i,j,a;
struct node *temp1;
struct node *temp2;
for(temp1=*h;temp1!=NULL;temp1=temp1->next)
{
for(temp2=temp1->next;temp2!=NULL;temp2=temp2->next)
{
if(temp2->data < temp1->data)
{
a = temp1->data;
temp1->data = temp2->data;
temp2->data = a;
}
}
}
}
In your bubble sort, you forget the swap condition.
In my opinion, I suggest insertion sort
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
int push(struct node **h, int x)
{
struct node *temp = (struct node*)malloc(sizeof(struct node));
temp->data = x;
if (*h == NULL) {
temp->next = *h;
*h = temp;
} else {
struct node *tmp = *h;
struct node *prev = NULL;
while (1) {
if (tmp == NULL || tmp->data >= temp->data)
break;
prev = tmp;
tmp = tmp->next;
}
temp->next = tmp;
if (prev != NULL)
prev->next = temp;
else
*h = temp;
}
return 0;
}
void print(struct node *head)
{
struct node *temp = head;
while(temp != NULL)
{
printf("%d ",temp->data);
temp = temp->next;
}
printf("\n");
}
int main()
{
struct node * head = NULL;
push(&head,5);
push(&head,4);
push(&head,6);
push(&head,2);
push(&head,9);
printf("List is : ");
print(head);
//sort(&head);
printf("after sorting list is : ");
print(head);
return 0;
}

Exception thrown in linked list

I need to write a function that returns the size of a linked list. It seems simple enough, but I get an exception when I try to advance my pointer.
This is the code:
int List_size(List *list)
{
List_node *p;
int counter = 0;
p = list->head;
while (p != NULL)
{
p = p->next;
counter = counter + 1;
}
return counter;
}
This is the code that defines the linked list:
typedef struct List_node
{
int data;
struct List_node *next;
struct List_node *prev;
}List_node;
typedef struct List
{
List_node *head;
}List;
And this is the code that creates the list:
List *create_list(int n)
{
List *list = (List*) calloc(n,sizeof(List));
list->head = NULL;
return list;
}
Lastly, I have inserted data (numbers) into the list using these two functions: (so don't think the lists are empty).
void insert_first(List_node *x, List *list)
{
x->next = list->head;
list->head = x;
}
void insert(List_node *x, List_node *y)
{
x->next = y->next;
y->next = x;
}
List_node *mk_node(int data, int n)
{
List_node *node = (List_node *)calloc(n, sizeof(List_node));
node->data = data;
return node;
}
Using a breakpoint I discovered that the problem lies in p = p->next, but I don't understand why.
Thank you very much.
edit - I did not think the full code is necessary, but here it is:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include "List.h"
void merge(List *small_list, List *big_list)
{
List_node *x, *y;
y = small_list->head;
x = big_list->head;
t = x->prev;
// while (y < x) //If there are smaller numbers on the small list, insert them first
// {
// insert(y,t)
// t = t->next;
// y = y->next;
// }
while (y != NULL && x->next != NULL)
{
if (x <= y && x->next >= y)
{
insert(y, x);
y = y->next;
}
else
x = x->next;
}
while (y != NULL)
{
insert(y, x);
y = y->next;
}
}
void main()
{
List *L1, *L2, *big_list, *small_list;
int num1, num2;
int i;
int a, b;
create_list(5,&L1);
create_list(3,&L2);
printf("Insert first number into L1\n");
scanf("%d", &num1);
node = mk_node(0,5);
insert_first(node, &L1);
for (i = 0; i<5; i++)
{
printf("Now insert the rest of the numbers\n");
scanf("%d", &num1);
next = mk_node(&num1,5);
insert(next, node);
node = next;
}
printf("Insert first number into L2\n");
scanf("%d", &num2);
node = mk_node(0,3);
insert_first(node, &L2);
for (i = 0; i<3; i++)
{
printf("Now insert the rest of the numbers\n");
scanf("%d", &num2);
next = mk_node(&num2,3);
insert(next, node);
node = next;
}
//If lists are in descending order, reverse them to ascending order
//if (L1->head > L1->head->next)
// reverse(L1);
// if (L2->head > L2->head->next)
// reverse(L2);
int size_L1 = List_size(L1);
int size_L2 = List_size(L2);
if (size_L1 <= size_L2)
{
big_list = L2;
small_list = L1;
}
else
{
big_list = L1;
small_list = L2;
}
merge(small_list, big_list);
print_list(L3);
getchar(); getchar();
}
As you can see, I inserted the numbers using the function insert(). I hope it is okay.
The function reverse is: (I really hope it works, I translated it from pseudo-code)
List reverse(List *list)
{
List_node *x, *y, *z;
if (list->head == NULL || list->head->next == NULL)
{
return *list;
}
x = list->head;
y = list->head->next;
z = list->head->next->next;
x->next = NULL;
while (z != NULL)
{
y->next = x;
x = y;
y = z;
z = z->next;
}
y->next = x;
list->head = y;
}
Basically, this is an assignment that says I have two 2-directional sorted linked lists, and I'm supposed to merge them into one big sorted linked list.
As for the exception - Unhandled exception at 0x00E21766 in Lists.exe: 0xC0000005: Access violation reading location 0xCCCCCCD0.
Edit - the print_list function:
void print_list(List *list)
{
List_node *p;
p = list->head;
printf("The linked list consists of: ");
while (p != NULL)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
The problem is in code you did not show, because all the code you give is fine (*).
I could use your structs and functions to :
create a List
add a first node (with insert_first)
add other nodes (with insert)
get the size (using List_size)
display the data value of every node
free the nodes and the list
Here's the full code :
#include <stdio.h>
#include <malloc.h>
typedef struct List_node
{
int data;
struct List_node *next;
struct List_node *prev;
}List_node;
typedef struct List
{
List_node *head;
}List;
List *create_list()
{
List *list = (List*) malloc(sizeof(List));
list->head = NULL;
return list;
}
int List_size(List *list)
{
List_node *p;
int counter = 0;
p = list->head;
while (p != NULL)
{
p = p->next;
counter = counter + 1;
}
return counter;
}
void insert_first(List_node *x, List *list)
{
x->next = list->head;
list->head = x;
}
void insert(List_node *x, List_node *y)
{
x->next = y->next;
y->next = x;
}
/* my own additions */
List_node *mk_node(int data) {
List_node *node = (List_node *) malloc(sizeof(List_node));
node->data = data;
return node;
}
void delete_list(List *list) {
List_node *node = list->head;
while (node != NULL) {
List_node *next = node ->next;
free(node);
node = next;
}
free(list);
}
int main() {
List* list = create_list();
List_node *node, *next;
int i;
node = mk_node(0);
insert_first(node, list);
for (i=1; i<5; i++) {
next = mk_node(i);
insert(next, node);
node = next;
}
int n = List_size(list);
printf("size : %d\n", n);
node = list->head;
while (node != NULL) {
printf("node val : %d\n", node->data);
node = node->next;
}
delete_list(list);
return 0;
}
(*) Your code is not perfect because List_node struct contains a pointer prev that is never used, so you end with a single-linked list with every third value unused.
I added a comment above that I copied your code into my compiler and that it doesn't compile, so it won't run: the calls to create_list don't compile: they return a value as function return, not in a parameter; there are undeclared variables. Further, it is useless to give create_list and mk_node a parameter: they will allocate an array, not create a single list element. A call of calloc(1, sizeof(your_thing)) would suffice. After fixing these erors, several bugs became apparent:
in insert_first(node, &L2); you give it the address of the list, which is already a pointer. Remove the '&' (the compiler should have complained!).
same for List_size(&L1); L1 is already a pointer. Remove the '&'.
in: if (x <= y ...) you compare memory addresses. Change to: if (x->data <= y->data...)
in that statement the part "x->next >= y" also compares memory address, and I don't see why it is needed. I removed it.
The real problem seems to be in merge. You should either merge the lists into L1, or into L2, and preferably should create a result list. But you "randomly" insert an element into L1, then into L2, then again into L1, etcetera. In my test it ran indefinitly. The following merge works fine:
List *merge(List *small_list, List *big_list)
{
List_node *x, *y, *r;
List *result= create_list();
y = small_list->head;
x = big_list->head;
if (x->data < y->data)
{result->head= x; x= x->next;}
else {result->head= y; y= y->next;}
r= result->head;
while (y != NULL && x != NULL)
{
if (x->data < y->data)
{
r->next= x;
x = x->next;
}
else {
r->next= y;
y = y->next;
}
r= r->next;
}
while (y != NULL)
{
r->next= y;
y = y->next;
r= r->next;
}
while (x != NULL)
{
r->next= x;
x = x->next;
r= r->next;
}
r->next= 0;
return (result);
}
So the problem is that you allocate the list head, but never allocate memory for the list elements. Serge added mk_node which does the allocation (so Serge solved it).

Error while finding max and min in a circular linked list

I need to find the maximum number and the minimum number in a circular linked list and i should move the minimum number to the start of the list (before head) and the maximum number to the end of the list (before minimum)
why my code is giving me error in output?
Note: Using doubly linked list is disallowed ,we should do this only with circular linked list.
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int num;
struct node *next;
} NODE;
void init(NODE **h)
{
(*h) = (NODE*)malloc(sizeof(NODE));
(*h)->next = *h;
}
NODE* add(NODE* h,NODE* p,int x)
{
int i;
NODE *temp;
temp = (NODE*)malloc(sizeof(NODE));
temp->num = x;
temp->next = h;
if(h->next == h)
{
h->next = temp;
return h;
}
else
{
temp = p->next;
p = temp;
return h;
}
return h;
}
NODE* fin(NODE *h,NODE *p)
{
NODE* ptr,*pmin,*pmax,*temp,*temp2,*mnprev,*mxprev;
// temp: minimum
// temp2: maximum
// pmin: holds the minimum
// pmax: holds the maximum
// ptr: o(n) search
// mnprev: holds the previous node of the minimum
// mxprev: hold the previous node of the maximum
mnprev = mxprev = pmin = pmax = h;
ptr = h->next;
int mini, maxi;
mini = h->num;
maxi = h->num;
do
{
if(ptr->num < mini)
{
mini = ptr->num;
pmin = ptr;
mnprev->next = pmin;
}
if(ptr->num > maxi)
{
maxi = ptr->num;
pmax = ptr;
mxprev->next = pmax;
}
ptr = ptr->next;
} while(ptr != h);
temp = pmin;
temp2 = pmax;
mnprev->next = pmin->next;
mxprev->next = pmax->next;
free(pmin);
free(pmax);
temp->next = h;
temp2->next = temp;
ptr = temp;
do {
printf("%d ",ptr->num);
ptr = ptr->next;
} while(ptr != h);
}
int main()
{
int i,x;
NODE *lis,*p;
init(&lis);
p = lis;
for(i=0;i<7;i++)
{
scanf("%d",&x);
add(lis,p,x);
}
fin(lis,p);
}
rewrite your code
function init delete as it will create nodes that are not used.
Changed to the node between the maximum and minimum values ​​since it
is sufficient to simply replace the value.
like this
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int num;
struct node *next;
} NODE;
NODE* add(NODE **head, NODE **tail, int x){
NODE *temp;
temp = (NODE*)malloc(sizeof(NODE));
temp->num = x;
if(*head == NULL){
temp->next = temp;
*tail = *head = temp;
} else {
temp->next = *head;
(*tail)->next = temp;
*tail = temp;
}
return *head;
}
void print(NODE *p){
NODE *top =p;
do{
printf("%d ", p->num);
p=p->next;
}while(p != top);
printf("\n");
}
void drop(NODE *head, NODE *tail){
NODE *p = head;
tail->next = NULL;
while(p){
NODE *temp = p;
p = p->next;
free(temp);
}
}
void minmax(NODE *head, NODE *tail){
NODE *p, *maxp, *minp;
int temp;
maxp = minp = p = head;
do{
if(maxp->num < p->num){
maxp = p;
}
if(minp->num > p->num){
minp = p;
}
p = p->next;
}while(p != head);
temp = maxp->num; maxp->num = tail->num; tail->num = temp;
if(tail == minp)//exchanged minp
minp = maxp;//fixed
temp = minp->num; minp->num = head->num; head->num = temp;
}
int main(void){
int i, x;
NODE *head, *tail;
tail = head = NULL;
for(i=0;i<7;i++){
printf("%d>", i+1);
scanf("%d", &x);
add(&head, &tail, x);
}
//print(head);
minmax(head, tail);
print(head);
drop(head, tail);
return 0;
}

Resources