Compare individual values in two linked lists C Programme - c

I'm writing a programme that needs to transverse threw 64 linked lists. (each node having one integer variable named val) it needs to compare each node and if the val is equal to another val in any other node of any list it must record it.
i've written a function that transverse threw the lists but after it prints the results that they equal it crashes, my function looks like this (n = 64):
void scanlist(int n)
{
int i = 0;
int j = 0;
for(i=0; i < n; i++)
{
struct node *temp; //Declare temp
temp = heads[i]; //Assign Starting Address to temp
int x = i++;
struct node *temp2; //Declare temp2
temp2 = heads[x]; //Assign Starting Address to temp2
while(temp != NULL)
{
if(temp->val == temp2->val)
{
printf("theyre on the same line, %d = %d \n", temp->val, temp2->val);
temp2 = temp2->next;
continue;
}
else if(temp->val != temp2->val)
{
temp2 = temp2->next;
continue;
}
else if(temp2 == NULL)
{
temp = temp->next;
temp2 = heads[x];
continue;
}
}
}
}
my linked list code looks like this:
struct node
{
int val;
struct node *next;
} ;
struct node* heads[64]; // array with the roots of the lists
struct node* currs[64]; // array holding pointers to current positions in list
struct node* create_list(int val, int listNo){
struct node *ptr = (struct node*)malloc(sizeof(struct node));
ptr->val = val;
ptr->next = NULL;
heads[listNo] = currs[listNo] = ptr;
return ptr;
}
void setup_list_array(int n){
int i;
for(i=0; i<n; i++)
{
heads[i] = NULL;
currs[i] = heads[i];
}
}
thanks for any help in advance, hope i was clear.

First, a few small comments on the 'Question' code:
void scanlist(int n)
{
int i = 0;
int j = 0;
It appears that 'j' is unused.
for(i=0; i < n; i++)
Perhaps it would be more efficent to this to
for(i=0; i < (n-1); i++)
This will avoid referencing the last 'heads[]', due to it being already compared.
{
struct node *temp; //Declare temp
temp = heads[i]; //Assign Starting Address to temp
int x = i++;
Perhaps 'i' is incremented in order to initialize 'x' to 'i + 1'; however, this statement is equivelant to 'x=i; i=i+1;', which does not appear to me helpful.
struct node *temp2; //Declare temp2
temp2 = heads[x]; //Assign Starting Address to temp2
Due to the previously stated mis-initialization of 'x', 'temp' and 'temp2' now point to the same 'head[]' element.
while(temp != NULL)
{
if(temp->val == temp2->val)
{
printf("theyre on the same line, %d = %d \n", temp->val, temp2->val);
temp2 = temp2->next;
continue;
}
else if(temp->val != temp2->val)
The 'else' statement can be omitted here. if '(temp->val == temp2->val)' [above] evaluates to 'TRUE', the 'continue' statement will cause program flow back to the top of the loop.
In addition, the statement 'if(temp->val != temp2->val)' can be omitted due to it will always evaluate to 'TRUE'
{
temp2 = temp2->next;
continue;
}
else if(temp2 == NULL)
Due to this 'else' statement, if either of the above 'if' statements evaluate to 'TRUE', this code will not be executed. This appears to be a flaw.
{
temp = temp->next;
temp2 = heads[x];
continue;
}
}
}
}
Below, another way to implement this method (included comments describe what is going on).
void scanlist(
int n
)
{
int i;
/* Iterate the list heads. */
for(i=0; i < (n-1); ++i)
{
struct node *temp = heads[i]; // Declare temp and assign Starting Address
/* Iterate primary list nodes. */
while(temp)
{
int j;
/* Iterate list heads to compare */
for(j=i+1; j < n; ++j)
{
struct node *temp2 = heads[j]; //Declare temp2 and assign Starting Address
/* Iterate list nodes to compare */
while(temp2)
{
if(temp->val == temp2->val)
printf("theyre on the same line, %d = %d \n", temp->val, temp2->val);
temp2=temp2->next;
}
}
}
temp=temp->next;
}
return;
}

Related

A function to join two linked lists

I implemented the list using
typedef int type;
typedef struct node{
int val;
struct node *next;
} node;
typedef struct list{
node *head;
}listtype ;
(The typedef type is just there so I can change the datatype of the list by just changing that one line)
And I implemented an insert function using
void insert(listtype *l, type elem, int pos) {
node *p = (node*)malloc(sizeof(node));
p->val = elem;
if (pos == 0) {
p->next = l->head;
l->head = p;
}
else {
node *q;
int i;
for (q = l->head, i = 0; i < pos - 1; i++) {
q = q->next;
}
p->next = q->next;
q->next = p;
}
}
The join function I came up with looks like this
void list_join(listtype *l,listtype *c) {
if (list_empty(*l)) {
printf("List empty");
}
else {
node *q;
int i = 0;
q = l->head;
while (q->next != NULL) {
insert(&c ,q->val, i + list_size(*c));
q = q->next;
i++;
}
}
}
But it doesn't work, or more accurately when I put it through my list view function it doesn't print out the correct contents (or anything at all really).
My function that prints the contents of the list:
void list_view(listtype l) {
if (list_empty(l))
printf("List empty");
else {
node *q;
q = l.head;
int i = 0;
while (q->next != NULL) {
printf("%d \t %d \n", i, q->val);
q = q->next;
i++;
}
printf("%d \t %d \n", i, list_tail(l));
}
}
I'm want to assume this function works properly and the issue is in the join function, but that's giving it a lot of credit.
The logic in the else block of the list_join function has a few issues:
The while condition should not test the ->next member, but the node itself, otherwise you'll not insert the tail value of the first list.
The insert function expects a listype* argument, not listype**, so you shouldn't pass &c, but c as first argument.
As in each iteration of the loop the c list will get longer, it is wrong to do i + list_size(*c), since both i and the size of the list will have increased. You'll want to calculate the length of the c list only once, and treat that as a constant that applies to all iterations equally. You could even initialise i with that list size instead of 0.
Here is a correction:
node *q;
int i = list_size(*c); // <-- get the list size only once
q = l->head;
while (q != NULL) { // No ->next
// Not &c; no list_size call
insert(c, q->val, i);
q = q->next;
i++;
}
This will fix the issue. But please note that there is lot of inefficiency in your approach which could be avoided if you would maintain a reference to the tail node of a list, and keep it updated. Then if you also create a separate method for appending a value at the end of a list (instead of providing a position), you can avoid some of the loops you currently have.

Skip list getting lost when either inserting with a new level or adding a new node to lower level

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <limits.h>
#define Malloc(n, type) (type *)malloc((unsigned)((n) * sizeof(type)))
#define Realloc(ptr, n, type) (type *)realloc(ptr, (n) * sizeof(type))
typedef struct Node
{
int key;
struct Node *next;
struct Node *down;
} Node;
typedef struct
{
int level;
struct Node *header;
} skiplist;
int level()
{
/*
This function takes the coin flip and decides the level of the node with each
level having a probability of 0.25.
arg: void
return: a number from the set {1,2,3, 4}
*/
int level = 1;
for (int i = 0; i < 3; i++)
{
unsigned int coin = (unsigned int)rand();
coin = coin % 2;
if (coin)
{
level++;
}
else
break;
}
return level;
}
skiplist skip_list_init();
Node *Traverse_Express(Node *, int);
Node *skip_list_search(skiplist, int);
Node *insert_level(Node *, int, int, int);
void skip_list_insert(skiplist *, int);
void skip_print(skiplist);
int main()
{
srand(time(0));
int arr[10000];
for (int i = 0; i < 10; i++)
{
arr[i] = (int)rand();
}
printf("The array is initialised\n");
skiplist list;
list = skip_list_init();
printf("The Skip list is initialised\n");
if (list.header == NULL)
{
printf("List is null\n");
}
for (int i = 0; i < 10; i++)
{
skip_list_insert(&list, arr[i]);
printf("The %d element is initialised with key: %d\n", i, arr[i]);
}
printf("The skip list is:\n");
skip_print(list);
return 0;
}
void skip_print(skiplist list)
{
/*
The function prints the skip list level-wise.
arg: list
return: none
*/
Node *temp = list.header;
int count = 0;
for (int i = list.level; i > 0; i--)
{
printf("The Keys at level %d:\n", i);
while (NULL != temp->next)
{
printf("%d ->", temp->key);
temp = temp->next;
}
printf("%d\n", temp->key);
int dummy = count;
temp = list.header;
while (dummy)
{
temp = temp->down;
dummy--;
}
count++;
}
}
skiplist skip_list_init()
{
/*
This function creates the first node in the skip list with key value
to be negative infinity and level of the list =1.
arg: None
return: Skiplist initialised with a Node having key as INT_MIN.
*/
skiplist list;
Node *head;
if (NULL == (head = Malloc(1, Node)))
{
exit(1);
}
list.header = head;
list.level = 1;
head->key = INT_MIN;
head->next = NULL;
head->down = NULL;
return list;
}
Node *skip_list_search(skiplist list, int key)
{
/*
The function returns a pointer to the either the key itself if present
or the key immediatedly smaller than the searched key.
arg:
list:The skiplist to be searched. Type: skiplist
key: A key to be searched. Type: int.
return: Type: Node pointer
A pointer to the searched key or immediately smaller it.
*/
if (list.header == NULL)
exit(1);
else
skip_print(list);
int level = list.level; // Number of levels already present in the list
Node *curr = list.header;
printf("Inside Skip search\n");
printf("The value of level %d\n", level);
for (; level > 0; level--)
{
curr = Traverse_Express(curr, key);
if ((curr->key == key) && (INT_MIN != curr->key))
{
return curr;
}
if (NULL != curr->down)
curr = curr->down;
}
printf("The value at current node %d\n", curr->key);
printf("Leaving Skip_search\n");
return curr;
}
Node *Traverse_Express(Node *temp, int key)
{
printf("On the express way\n");
printf("We are searching the key: %d\n", key);
while (key > temp->key && NULL != temp->next)
{
printf("Loop of expressway\n");
printf("The current key : %d\n", temp->key);
if (key >= temp->next->key)
temp = temp->next;
else
break;
}
printf("Left the express way\n");
return temp;
}
Node *insert_level(Node *nod, int key, int lev, int list_lev)
{
/*
Inserting the key till the required level
arg:
nod: a pointer to the exsiting skip list
key: key to be inserted
lev: the level of the key
list_lev: the number of levels in the given skiplist
return: A Node pointer to the head of the skiplist with the key
inserted to the existing list.
*/
Node *temp1 = nod, *temp3 = NULL;
printf("\nStarting of insert at level procedure\n");
// Procedure to cut-off the extra levels in the list if any
if (lev < list_lev)
{
for (int i = list_lev - lev; i > 0; i--)
{
printf("Searching on the level: %d\n", i + lev);
temp1 = Traverse_Express(temp1, key);
temp1 = temp1->down;
}
}
printf("The value of first node: %d\n", temp1->key);
// Procedure to insert from the required level till level 1
for (int i = 0; i < lev; i++)
{
Node *temp2 = Malloc(1, Node);
temp2->key = key;
temp2->next = NULL;
temp2->down = NULL;
temp1 = Traverse_Express(temp1, key);
printf("Temp1 current key:%d\n", temp1->key);
if (NULL == temp1->next)
{
temp1->next = temp2;
printf("Node inserted at level: %d\n", lev - i);
}
else
{
printf("Entered the else procedure\n");
temp2->next = temp1->next;
temp1->next = temp2;
printf("%d\n", temp1->next->key);
}
if (i > 0)
{
temp3->down = temp2;
}
temp1 = temp1->down;
temp3 = temp2;
/*
free(temp2);
if(temp3==NULL)
{
printf("did a fuck up\n");
exit(1);
}*/
}
skiplist list;
// list = skip_list_init(list);
list.header = nod;
list.level = list_lev;
printf("Printing skip list from insert level\n");
skip_print(list);
printf("End insert level procedure\n\n\n");
temp1 = temp3 = NULL;
return nod;
free(temp1);
free(temp3);
}
void skip_list_insert(skiplist *list, int key)
{
/*
This function finds the key value and if already present, then returns back
else it inserts the key at its right place.
arg: a skilplist by reference and a key
return: None
*/
printf("Inside skip_list_insert\n");
Node *req = skip_list_search(*list, key);
printf("The value returned by skip search %d\n", req->key);
if (key == req->key)
{
printf("Key %d is already present in skip list\n", key);
}
Node *temp1 = list->header;
int list_lev = list->level;
printf("The list level = %d\n", list_lev);
int lev = level();
printf("The prob level %d\n", lev);
Node *hold_prev = NULL;
// creating a skip list if level returned is greater than existing one.
if (lev > list_lev)
{
for (int i = lev - list_lev; i > 0; i--)
{
skiplist l = skip_list_init();
Node *inser = Malloc(1, Node);
printf("The value of i in loop %d\n", i);
inser->key = key;
inser->down = NULL;
inser->next = NULL;
l.header->next = inser;
Node *trans = l.header;
// Zipping the previous levels with new level
while (NULL != hold_prev)
{
trans->down = hold_prev;
trans = trans->next;
hold_prev = hold_prev->next;
}
hold_prev = l.header;
l.header = NULL;
if (hold_prev == NULL)
{
printf("Big Mistake");
exit(1);
}
else
{
printf("You are doing it correct way\n");
}
}
list->header = hold_prev;
list->level = lev - list_lev;
skip_print(*list);
// Returning a pointer to the zeroth element of last level in this list.
while (NULL != hold_prev->down)
{
hold_prev = hold_prev->down;
}
}
// Inserting the node till the min(list_lev, level())
if (list_lev > lev)
{
temp1 = insert_level(temp1, key, lev, list_lev);
}
else
{
temp1 = insert_level(temp1, key, list_lev, list_lev);
}
skiplist l1 = skip_list_init();
l1.header = temp1;
l1.level = list_lev;
skip_print(l1);
printf("\n Now the Zipping procedure with level()>list_lev starts\n");
// Zipping Procedure only if level()>list_lev
if (lev > list_lev)
{
hold_prev->down = temp1;
skiplist l1 = skip_list_init();
l1.header = list->header;
l1.level = lev;
skip_print(l1);
printf("the key at the first node:%d\n", temp1->key);
hold_prev = hold_prev->next;
while (temp1->key != key)
{
temp1 = temp1->next;
printf("Zipping over keys:\n");
printf("Current key: %d\n", temp1->key);
}
hold_prev->down = temp1;
list->level = lev;
}
if (list_lev > lev)
{
list->level = list_lev;
}
printf("\n\n\n");
}
The above is my implementation. I have tried with all my might to debug the code but I am falling to implement a skip list for past 1 month. I genuinely request with pleading hands 🙏🙏🙏 to look into the implementation and please do let me know the fixes, I can do.
It would be a great help. Thank you.
I have tried with all my might to debug the code but I am falling to implement a skip list for past 1 month.
You will have much easier time debugging if you fill the list with some non-random values (you can switch back to random values once the program is working for all hand-coded combinations).
Also fix your comments so they match the code. E.g. here the comments are clearly wrong:
skiplist skip_list_init()
{
/*
This function creates the first node in the skip list with key value
to be negative infinity and level of the list =1.
arg: It takes a list by reference
return: None
*/
There is no arg and the return is not None.
You should avoid making a copy of the list when calling skip_list_search (pass a pointer to the list).
You should avoid this construct:
if (hold_prev == NULL)
{
printf("Big Mistake");
exit(1);
}
else
{
printf("You are doing it correct way\n");
}
It make your code way too long. Instead, do this:
assert(hold_prev != NULL);
Giving your variables meaningful names will also go a long way helping you and others understand the code.
With the value inputs by Gene and Employed Russian, the skip list implementation has a mistake in the function skip_print which unfortunately didn't transverse all the levels of the skip-list.
See here:
int count=0;
and
int dummy = count;
temp = list.header;
while (dummy)
{
temp = temp->down;
dummy--;
}
count++;
When count=0 implies dummy=0. This doesn't let your pointer temp transverse to the bottom level till the next iteration when count=1. Thus, effectively only transversing and printing till list.level-1.
Hence, the implementation doesn't work correctly.
Please incorporate the following code for skip_print:
void skip_print(skiplist list)
{
/*
The function prints the skip list level-wise.
arg: list
return: none
*/
Node *temp = list.header;
int count = 1;
while (temp)
{
Node *n1 = temp;
printf("Printing the keys at level: %d\n", count);
while (NULL != n1->next)
{
printf("%d ->", n1->key);
n1 = n1->next;
}
printf("%d\n", n1->key);
temp = temp->down;
count++;
}
}
The rest of the code seems to be working fine for me.

Linked list — deletion of nodes which contain prime numbers [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I have written a code in the C language which will create a linked list. The linked list structre has two fields, namely data and next; data contains integer data, next is a structure pointer.
The program asks the user to input data into the list. Once the data has been entered, the program will go through the list and check which data in the node contains a prime number. If it finds one such node, it will delete it and link the next node to the previous node, but I am getting a segmentation fault error and I am unable to solve.
I am putting below the code. Can you please be kind enough to help me solve it as I do not know how to find the problem?
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
typedef struct node *nptr;
nptr H, h, n;
void deletetheprime(struct node**);
void display();
int prime(int);
int main() {
nptr temp1, temp;
int i, N, p;
printf("\n if list is completed enter 999\n");
for (;;) {
printf("\n enter the data \n");
scanf("%d", &i);
if (i == 999)
break;
else
if (H == NULL) {
H = h = (nptr)malloc(sizeof(struct node));
H->data = i;
H->next = NULL;
} else {
n = (nptr)malloc(sizeof(struct node));
n->data = i;
n->next = NULL;
h->next = n;
h = n;
}
}
printf("\n data before deletion\n");
display();
temp = H;
while (temp != NULL) {
N = temp->next->data;
p = prime(N);
if (p == 1) {
deletetheprime(&temp);
} else {
temp = temp->next;
}
}
printf("\n the data after deletion is\n");
display();
return 0;
}
void deletetheprime(struct node **temp2) {
nptr temp, temp1;
temp = *temp2;
temp1 = temp->next;
temp->next = temp->next->next;
free(temp1);
temp = temp->next;
}
int prime(int i) {
int j, p = 0;
for (j = 2; j <= i / 2; i++) {
if (i % j == 0) {
break;
}
}
if (j > i / 2) {
p = 1;
}
return p;
}
void display() {
nptr temp;
temp = H;
while (temp != NULL) {
printf("\n %d", temp->data);
temp = temp->next;
}
}
The problem is here:
while (temp != NULL) {
N = temp->next->data;
When you reach the last element of the list, temp is not NULL, but temp->next is so temp->next->data has undefined behavior.
There are other problems:
your prime() function is inefficient and will return 1 for 0 and 1.
you deletetheprime() function deletes the node and updates the pointer in the callers scope, but the caller does not update the link in the previous node nor the H pointer if the deleted node is the first.
you use global variables for no good reason, you should pass H to display() and make all variables local in main().
you never free the allocated objects, it is good style to free everything you allocate.
you should not hide pointers behind typedefs, make node a typedef for struct node but keep pointers visible, it is a good habit to avoid confusing both the reader and the programmer.
To delete the node, you should use the pointer to link trick:
for (struct node **p = &H; *p;) {
if (prime((*p)->data) {
nptr np = *p;
*p = np->next;
free(np);
} else {
p = &(*p)->next;
}
}
p initially points to the head pointer H and subsequently points to the next member of the previous node. It can be used to update the head pointer or the link in the previous node when a node to be deleted is found.
Here is a corrected and simplified version:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} node;
int isprime(int n) {
if (n < 2)
return 0;
if (n % 2 == 0)
return n == 2;
for (int i = 3; i * i <= n; i += 2) {
if (n % i == 0) {
return 0;
}
}
return 1;
}
void display(const node *temp) {
while (temp != NULL) {
printf(" %d", temp->data);
temp = temp->next;
}
printf("\n");
}
int main(void) {
node *H = NULL;
node **lastp = &H;
node *n;
int i;
printf("Enter values, when list is completed enter 999\n");
for (;;) {
printf("\n enter the data: ");
if (scanf("%d", &i) != 1 || i == 999)
break;
n = malloc(sizeof(*n));
if (n == NULL)
break;
n->data = i;
n->next = NULL;
*lastp = n;
lastp = &n->next;
}
printf("\n data before deletion: ");
display(H);
for (node **p = &H; *p;) {
if (isprime((*p)->data)) {
n = *p;
*p = n->next;
free(n);
} else {
p = &(*p)->next;
}
}
printf("\n the data after deletion is: ");
display(H);
/* free the list */
while (H != NULL) {
n = H;
H = n->next;
free(n);
}
return 0;
}
I shall attribute your please solve it! stance to your poor command of the English language. Please learn to improve both your communications and your programming skills by carefully studying answers on this site.
The problem occurs here, in main
while(temp!=NULL)
{
N=temp->next->data;
...
You are checking if temp is not NULL, which is correct, but accessing data of next node, which can be NULL, and has to be NULL near the end of the list, which leads to undefined behavior.
Simply modify it to
while(temp!=NULL)
{
N=temp->data;
...
Where you are sure that temp isn't NULL and you won't get segmentation error here. And it'll work.
Or if you need to access data of temp->next->next node, you've got to check if next->next isn't NULL as well.
while(temp!=NULL)
{
if (temp->next->next != NULL)
{
N=temp->next->data;
}
else // temp->next->next is NULL so you can't access the data
...

How do I Bubble Sort a linked list?

I am trying to create a linked list and sort it by Bubble Sort. I succeeded to create the linked list, but when I am trying to Bubble Sort it, some accidents occur and I do not know the problem. What is the problem?
#include <stdio.h>
#include <stdlib.h>
//the struct of LinkedList
typedef struct Node
{
int data;
struct Node * pNext;
}NODE,*PNODE;
PNODE createList();//Creat one LinkedList
int lengthList(PNODE pHead);//get the length of LinkedList
void sortList(PNODE);//bubble sort
int main()
{
int length;
PNODE pHead=NULL;
pHead=createList();
sortList(pHead);
return 0;
}
//Create LinkedList
PNODE createList()
{
int i,n;
int val;
PNODE pHead=(PNODE)malloc(sizeof(NODE));
if(pHead==NULL)
{
printf("failed to create!\n");
exit(-1);
}
pHead->pNext=NULL;
PNODE pTail=pHead;
printf("please input the length of the LinkedList:");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("number %d is:\n",i+1);
scanf("%d",&val);
PNODE pNew=(PNODE)malloc(sizeof(NODE));
if(pNew==NULL)
{
printf("failed to create\n");
exit(-1);
}
pNew->data=val;
pTail->pNext=pNew;
pNew->pNext=NULL;
pTail=pNew;
}
return pHead;
}
//get the length of LinkedList
int lengthList(PNODE pHead)
{
int i=0;
PNODE p=pHead->pNext;
while(p!=NULL)
{
i++;
p=p->pNext;
}
return i;
}
//bubble sort
void sortList(PNODE pHead)
{
int i,j,t,len;
PNODE p,q;
len=lengthList(pHead);
p=pHead->pNext;
for(i=0;i<len-1;i++)
{
for(j=0;j<len-i;j++)
{
q=p->pNext;
if( p->data > q->data)
{
t=p->data;
p->data=q->data;
q->data=t;
}
p=q;//here may be the error
}
}
return;
}
You are running off the end of your list in sortList
p=pHead->pNext;
for(i=0;i<len-1;i++)
{
for(j=0;j<len-i;j++)
{
q=p->pNext;
....
p=q;//here may be the error
}
}
Bug 1) Your list is only len long but you are attempting to advance p to p->pNext far more then len times.
Bug 2) pHead does not need to be a full NODE - it's just a PNODE pointer. You never use its data field. You should have pHead point to the first node in the list, and then start your iteration at pHead rather than pHead->pNext.
Bug 3) You never clean up your memory allocations.
As #Airsource pointed out the bugs, keep in mind most of them are caused because of poor designing choice of your program. Try to do it like below & you will run into less errors
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct _Node{
int data;
struct _Node* next;
}Node;
typedef struct {
Node* headPtr;
Node* tailPtr;
unsigned size;
}List;
static void create_node(List* list, int element) {
if (list->headPtr == NULL) {
// List is empty
list->headPtr = (Node* )malloc(sizeof(Node));
list->headPtr->data = element;
list->headPtr->next = 0;
list->tailPtr = list->headPtr;
list->size++;
}else{
// List was already populated
Node* temp = (Node* )malloc(sizeof(Node));
temp->data = element;
temp->next = 0;
list->tailPtr->next = temp;
list->tailPtr = temp;
list->size++;
}
}
void create_list(List* list, int length){
int ele;
int i;
list->headPtr = list->tailPtr = 0;
list->size = 0;
for (i = 0; i < length; i++) {
scanf("%d", &ele);
create_node(list, ele);
}
}
void print_list(List* list){
Node* loop = list->headPtr;
while(loop){
printf("%d ", loop->data);
loop = loop->next;
}
printf("\n");
}
int main(){
List* list;
int n;
printf("Enter the length of the list: ");
scanf("%d", &n);
create_list(list, n);
print_list(list);
bubble_sort(list);
print_list(list);
if (cleanup(list))
printf("Memory rescued!!\n");
else
printf("OOPS!! Error\n");
return 0;
}
Moreover, you can get the size anytime just by list->size. No need for separate function to do that.
Finally to sort it using bubble sort you could do something like this below
void bubble_sort(List* list) {
int i, j;
Node* first, *second;
int temp;
first = list->headPtr;
second = list->headPtr->next;
for (i = 0; i < list->size - 1; i++) {
for (j = 0; j < list->size - i - 1; j++) {
if (first->data > second->data){
temp = first->data;
first->data = second->data;
second->data = temp;
}
first = second;
second = second->next;
}
first = list->headPtr;
second = list->headPtr->next;
}
}
and for cleanup you do this
bool cleanup(List* list) {
Node* curr = list->headPtr;
Node* nxt = list->headPtr->next;
while(nxt){
free(curr);
curr = nxt;
nxt = curr->next;
}
list->headPtr = list->tailPtr = 0;
list->size = 0;
return !nxt ? true: false;
}
There are couple of bugs in your program. I will address them one by one:
Line 28 PNODE pHead=(PNODE)malloc(sizeof(NODE));
Here you are allocating a memory and creating a node before checking if n>0 or not.
Line 36 printf("please input the length of the LinkedList:");
Now up to this point you have created a one node, head node which has no value in it (so contains garbage)
In effect your createList() creates a linked list with n+1 nodes instead of n and the head->value contains garbage.
Solution:
printf("please input the length of the LinkedList:");
scanf("%d", &n);
for(i=0; i<n; i++)
{
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if(pNew == NULL)
{
printf("failed to create!\n");
exit(-1);
}
scanf("%d", &val);
pNew->data = val;
pNew->pNext = NULL;
if (!i)
pHead = pNew;
else
pTail->pNext = pNew;
pTail = pNew;
}
return pHead;
Line 59 PNODE p=pHead->pNext;
Here you are counting nodes starting from the second node (leaving out head). No wonder you will get length as n as you have created a linked list of length n+1 in your createList()
Imagine what if n = 0 and thus pHead = NULL?
Then this line will result in SegFault.
Solution:
change PNODE p=pHead->pNext; to PNODE p = pHead;
Line 73 p=pHead->pNext;
Here you will start sorting excluding the first node, head node.
Also this should be inside the outter for and outside of the inner for to reset the p to first node for each pass.
Line 76 for(j=0;j<len-i;j++)
Here j must be less than len - 1 - i as in pass 1 (i = 0) in the worst case j will be equal to len-1 for j < len-i, where p will point to the last node of linked list and q will be NULL as q = p -> pNext. Which will make q->data to result in SegFault.
To summarise, your sort routine is producing SegFault in the very first Pass and even if it didn't (by properly adjusting the loop-terminating expression in inner for) the outer for loop is contributing nothing towards the sorting except increasing the time complexity.
Solution:
for(i = 0; i < len - 1; i++)
{
p = pHead;
for(j = 0; j < len - 1 - i; j++)
{
q = p -> pNext;
if(p->data > q->data)
{
t = p -> data;
p -> data = q -> data;
q -> data = t;
}
p = q;
}
}
A question:
How are you checking whether element have been sorted or not?
A printList() routine would have been helpful in spotting the above bugs.
"Always verify whether you correctly stored the input or not by explicitly printing the same before processing it!"

Circular linked list going in infinite loop

I am supposed to do a program which can do polynomial addition/subtraction/multiplication/evaluation using circular linked list.
My multiplication code is going in infinite loop, and I have marked a comment where it is happening (detected with printf statements, removed).
list* poly_mul(list *p1, list *p2) {
term tmp;
list *result = malloc(sizeof(list));
memcpy(result, p1, sizeof(list));
node *b = p2->head;
node *r = result->head;
do {
do {
tmp.exp = r->data.exp + b->data.exp;
tmp.coeff = r->data.coeff * b->data.coeff;
unsigned int add_term = 1;
node *c = result->head;
do {
if(c->data.exp == tmp.exp) {
c->data.coeff += tmp.coeff;
add_term = 0;
break;
}
c = c->next;
//Here it goes in infinite loop
} while(c != result->head);
if(add_term)
node_add(result, &tmp);
b = b->next;
} while(b != p2->head);
r = r->next;
} while(r != result->head);
return result;
}
The structures used are here:
typedef struct {
int exp;
int coeff;
} term;
typedef struct node {
term data;
struct node *next;
} node;
typedef struct {
node *head;
node *tail;
unsigned int count;
} list;
And this is the code in main:
void main() {
list p1, p2, *p3;
p1.count = p2.count = 0;
poly_create(&p1);
p3 = poly_mul(&p1, &p2);
poly_print(p3);
}
void poly_create(list *l) {
int i, n;
printf("\nEnter number of terms in the polynomial: ");
scanf("%d", &n);
for(i = 1; i <= n; i++) {
printf("\nEnter details for term %d: ", i);
term_append(l);
}
void node_add(list *l, term *t) {
node *tmp = malloc(sizeof(node));
memcpy(&tmp->data, t, sizeof(term));
if(l->count == 0) {
l->head = tmp;
l->tail = tmp;
tmp->next = tmp;
}
else {
l->tail->next = tmp;
tmp->next = l->head;
l->tail = tmp;
}
l->count++;
}
void term_append(list *l) {
term t;
enter:
printf("\nEnter term as <coefficient>,<exponent>: ");
scanf("%d,%d", &t.coeff, &t.exp);
if(!t.coeff) {
printf("\nCoefficient is zero, reenter term");
goto enter;
}
if(l->count >= 1) {
node *i = l->head;
do {
if(i->data.exp == t.exp) {
printf("\nExponent %d was already entered, reenter term", t.exp);
goto enter;
}
i = i->next;
} while(i != l->head);
node_add(l, &t);
}
else
node_add(l, &t);
}
Please get me a solution for this problem, I've been trying to solve this for the past three hours.
Why is it going into an infinite loop? You can find out by using a debugger and stepping through the code. Just put a breakpoint at the appropriate place and you should be able to find it yourself. In all likelihood, you have a loop in your linked list.
You can check for loops in your linked list with two pointers. The first one (tail) point to the start of your list. The second (head) points to the second element of your list. Loop till head is past the last element (I have those pointed to NULL, not head) by incrementing both head and tail by one. If at any point tail > head, you have a loop.
What happens if you printf("%d",(int) c); at each iteration? I suspect that result->head is pointing to a node which is pointing to a member of the linked list, but is not in the linked list itself.
Potential test: Add a int seen to each member of the list and increment it on each member as you loop for a given number of nodes (something excessively high such as INT_MAX) and, when the loop stops, see if result->head->seen > 0:
typedef struct node {
term data;
struct node *next;
// to be removed later
int seen;
} node;
// place this before you get the infinite loop
unsigned int i = 1;
c->seen = 0;
do
{
c = c->next;
c->seen = i;
// replace INT_MAX with some number which is greater than the maximum list length
} while(++i <= INT_MAX);
// this should be roughly equal to i (might be off by 1).
// I'll bet it isn't though!
printf("result->head->seen = %d", result->head->seen);
One possible cause: you're never creating p2. Are you missing a line like this in your main function:
poly_create(&p2);
?

Resources