I need to segregate even and odd nodes in a Linked List in C.
Example:
Original list: 3,1,8,2,5,6
After change: 8,2,6,3,1,5
I have a problem when the head list data is an odd number, it is cutting out the even numbers.
Example:
Original list: 3,1,8,2,5,6
After change: 3,1,5
typedef struct Node {
int data; // store information
struct Node * next; //referance to the next node
}Node;
Node * create(Node * L, int value)
{
Node *current = L ,* new_node = (Node*)malloc(sizeof(Node)); // create and allocate a node
new_node->data = value;
new_node->next = NULL;
if (L == NULL)
{
L = new_node;
current = new_node;
}
else
{
while (current->next != NULL)
current = current->next;
current->next = new_node;
current = new_node;
}
return L;
}
Node * Change_Even_Odd(Node * L)
{
Node *oddhead = NULL, *evenhead = NULL, *lastodd = NULL, *lasteven = NULL, *current = L;
while (current != NULL)
{
// if current is even node
if (current->data % 2 == 0)
{
if (evenhead == NULL)
{
evenhead = current;
lasteven = current;
}
else
{
lasteven->next = current; // to connect the node to the list in the end
lasteven = current; // final list
}
}
else
{
// if current is odd node
if (oddhead == NULL)
{
oddhead = current;
lastodd = current;
}
else
{
lastodd->next = current;
lastodd = current;
}
}
current = current->next;
}
if (evenhead != NULL) // to put the even node in the head list
L = evenhead;
if (lasteven != NULL) // link the odd nodes to the even nodes
lasteven->next = oddhead;
if (lastodd != NULL) //end of list
lastodd->next = NULL;
return L;
}
void Print_List(Node * head)
{
while (head != NULL)
{
printf("%4d", head->data);
head = head->next;
}
}
int main()
{
Node * list = NULL; //empty linked list
srand(time(NULL));
int i, size = rand() % 10 + 1;
for (i = 0; i < size; i++)
list = create(list, rand() % 10 + 1);
printf("%d\n",size);
Print_List(list);
printf("\n");
Change_Even_Odd(list);
Print_List(list);
printf("\n");
}
Change_Even_Odd(list); should be list = Change_Even_Odd(list); (I already pointed out.)
– BLUEPIXY
Related
I have a problem with deleting elements with greatest values from doubly linked list. It seems that my program works fine with only one greatest number in the list. However, if the list contains two greatest numbers (as an example, last two list's elements are greatest numbers), the program crashes. I am sure my management of nodes' adresses is not correct.
EDIT: I was ment to say the "greatest" values just in case if the word "largest" mistakens.
Here's my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
struct node* prev;
int value;
struct node* next;
} node;
node* allocateNode(int value);
node* addToEnd(node* head, int value);
node* makeList(node* head, int n);
node* deleteMaxElement(node* head);
void freeMemory(node* head);
int main()
{
node* head = NULL;
int n = 0;
printf("Enter number of elements: ");
if (!(scanf("%d", &n) == 1))
return 0;
head = makeList(head, n);
head = deleteMaxElement(head);
if (n > 1)
{
node* element = head;
printf("%d ", element->value);
while(element->next != NULL)
{
element = element->next;
printf("%d ", element->value);
}
printf("\n");
freeMemory(head);
}
return 0;
}
node* makeList(node* head, int n)
{
int value = 0;
if (n == 0)
return head;
printf("Enter value of 1 node: ");
if (scanf("%d", &value) == 1)
{
head = allocateNode(value);
for (int i = 1; i < n; i++)
{
printf("Enter value of %d node: ", i + 1);
if(scanf("%d", &value) == 1)
head = addToEnd(head, value);
}
}
return head;
}
node* allocateNode(int value)
{
node* newNode = (node*)malloc(sizeof(node));
newNode->prev = NULL;
newNode->next = NULL;
newNode->value = value;
return newNode;
}
node* addToEnd(node* head, int value)
{
node* newNode = allocateNode(value);
node* element = head;
while (element->next != NULL)
element = element->next;
element->next = newNode;
newNode->prev = element;
return head;
}
node* deleteMaxElement(node* head)
{
int max = head->value;
node* element = head;
// finds max element in list
while (element->next != NULL)
{
element = element->next;
if (element->value > max)
max = element->value;
}
// max element is in the list head
int firstElementDeleted = 0;
if (head->value == max)
{
node* temp = head->next;
free(head);
head = temp;
firstElementDeleted = 1;
}
// max elements is not in the list head
element = head;
while (element->next != NULL)
{
node* temp = NULL;
if (element->value == max)
{
if (!firstElementDeleted)
(element->prev)->next = element->next;
else
head = element->next;
temp = element->next;
free(element);
element = temp;
continue;
}
element = element->next;
}
// max elements is in the last node
if (element->value == max)
{
(element->prev)->next = NULL;
free(element);
}
return head;
}
void freeMemory(node* head)
{
node* next;
while (head != NULL)
{
next = head->next;
free(head);
head = next;
}
}
Previous pointer points to nowhere
You do not set the previous node pointer of the next element when you delete the element in the deleteMaxElement function. Add this one line to your function and it should work as intended. ;)
while (element->next != NULL)
{
node* temp = NULL;
if (element->value == max)
{
if (!firstElementDeleted) {
(element->prev)->next = element->next;
(element->next)->prev = element->prev;
}
else
head = element->next;
temp = element->next;
free(element);
element = temp;
continue;
}
element = element->next;
}
I have this code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node
{
int x;
struct Node *next;
} Node;
void deallocate(Node **root)
{
Node *curr = *root;
while (curr != NULL)
{
Node *aux = curr;
curr = curr->next;
free(aux);
}
*root = NULL;
}
void insert_end(Node **root, int value)
{
Node *new_node = malloc(sizeof(Node));
if (new_node == NULL)
{
exit(1);
}
new_node->next = NULL;
new_node->x = value;
if (*root == NULL)
{
*root = new_node;
return;
}
Node *curr = *root;
while (curr->next != NULL)
{
curr = curr->next;
}
curr->next = new_node;
}
void deserialize(Node **root)
{
FILE *file = fopen("duom.txt", "r");
if (file == NULL)
{
exit(2);
}
int val;
while (fscanf(file, "%d, ", &val) > 0)
{
insert_end(root, val);
}
fclose(file);
}
int largestElement(struct Node *root)
{
int max = INT_MIN;
while (root != NULL)
{
if (max < root->x)
max = root->x;
root = root->next;
}
return max;
}
void deleteN(Node **head, int position)
{
Node *temp;
Node *prev;
temp = *head;
prev = *head;
for (int i = 0; i < position; i++)
{
if (i == 0 && position == 1)
{
*head = (*head)->next;
free(temp);
}
else
{
if (i == position - 1 && temp)
{
prev->next = temp->next;
free(temp);
}
else
{
prev = temp;
// Position was greater than
// number of nodes in the list
if (prev == NULL)
break;
temp = temp->next;
}
}
}
}
int main()
{
Node *root = NULL;
printf("MENU:\n");
printf("if you press 0 the list will be created \n");
printf("if you press 1 the list will be printed on a screen\n");
printf("if you press 2 it deletes the biggest element\n");
printf("if you press 3 the program ends\n\n");
int meniu;
printf("press:\n");
scanf("%d", &meniu);
while (meniu != 3)
{
if (meniu == 0)
{
deserialize(&root);
printf("sarasas sukurtas.\n");
}
if (meniu == 1)
{
for (Node *curr = root; curr != NULL; curr = curr->next)
printf("%d\n", curr->x);
}
if (meniu == 2)
{
int max_element = largestElement(root);
printf("%d max\n", max_element);
deleteN(&root, max_element);
}
printf("press:\n");
scanf("%d", &meniu);
}
deallocate(&root);
return 0;
}
When I compile and run the delete function it only deletes the biggest number first time and if I call it second time it deletes the last number of the list. Can someone help me fix that?
I edited it so all of the code can be seen because it was hard to understand it like I had it before
Your largestElement returns the largest data value in the list.
However, here:
int max_element = largestElement(root);
printf("%d max\n",max_element);
deleteN(&root, max_element);
you use the return value as if it is the position of the node with the largest element.
Instead of largestElement you need a function that returns the position of the element with the largest data value.
It would look something like:
int positionOfLargestElement(struct Node* root)
{
int pos = 0;
int maxpos = 0;
int max = INT_MIN;
while (root != NULL) {
++pos;
if (max < root->x)
{
max = root->x;
maxpos = pos;
}
root = root->next;
}
return maxpos;
}
note: The exact code depends a bit on whether the first node is considered to be position 0 or position 1 but the principle is the same.
How to add a new node at a specific index in doubly linked list. I wrote a function that is meant to add a new node at a specific index, but after i tested my function in the main program i got an infinite loop.
dlistint_t *insert_dnodeint_at_index(dlistint_t **h, unsigned int idx, int n)
{
dlistint_t *temp;
dlistint_t *new_node;
unsigned int count;
temp = *h;
new_node = malloc(sizeof(dlistint_t));
if (new_node == NULL)
return (NULL);
new_node->prev = NULL;
new_node->next = NULL;
new_node->n = n;
if (idx == 0)
{
*h = new_node;
return (new_node);
}
else
{
count = 0;
while (temp != NULL && count != idx - 1)
{
temp = temp->next;
count++;
}
if (count != idx - 1)
{
return (NULL);
}
temp->next = new_node;
new_node->next = temp;
new_node->prev = temp;
return (new_node);
}
}
Here I have a header file to include functions:
#ifndef driver_h
#define driver_h
#include <stdio.h>
#include <stdlib.h>
typedef struct node node;
typedef struct nodePtrs nodePtrs;
struct node {
node* next;
node* prev;
int data;
};
void sortedInsert(node** top, node* newNode, node** last) {
node* current;
if (*top == NULL) {
*top = newNode;
} else if ((*top)->data >= newNode->data) {
newNode->next = *top;
newNode->next->prev = newNode;
*top = newNode;
if ((*top)->next == NULL) {
*last = *top;
}
} else {
current = *top;
while (current->next != NULL &&
current->next->data < newNode->data) {
current = current->next;
}
newNode->next = current->next;
if (current->next != NULL) {
newNode->next->prev = newNode;
}
current->next = newNode;
newNode->prev = current;
}
if ((*top)->next == NULL) {
*last = *top;
}
}
void insertionSort(node** top, node** last) {
node* sorted = NULL;
node* current = *top;
while (current != NULL) {
node* next = current->next;
current->prev = current->next = NULL;
sortedInsert(&sorted, current, last);
current = next;
}
*top = sorted;
}
node* deleteByPos(node* list, node** last, int position) {
int c = 0;
node* temp;
node* prev;
temp=list;
if (temp==NULL) {
printf("No nodes available to delete\n\n");
return list;
} else {
while(temp!=NULL && c != position) {
prev=temp;
temp=temp->next;
c++;
}
if (temp==NULL) {
printf("Reached end of list, position not available\n\n");
return list;
} else if (temp->next == NULL) {
prev->next=temp->next;
*last = prev;
free(temp);
return list;
} else {
prev->next=temp->next;
temp->next->prev = prev;
free(temp);
return list;
}
}
}
node* makeNode(int n) {
node* np = malloc(sizeof (node));
np->data = n;
np->prev = NULL;
np->next = NULL;
return np;
}
void printList(node* np) {
while (np != NULL) {
printf("%d\n", np->data);
np = np->next;
}
}
void printListReverse(node* np) {
while (np != NULL) {
printf("%d\n", np->data);
np = np->prev;
}
}
#endif /* driver_h */
and a main file:
#include "driver.h"
int main() {
int n;
node* np;
node* top;
node* last;
printf("Enter integers to add to list\n");
do {
if (scanf("%d", &n) != 1) {
n = 0;
}
if (n != 0) {
np = makeNode(n);
if (top == NULL) {
top = np;
} else {
last->next = np;
np->prev = last;
}
last = np;
}
} while (n != 0);
printf("\n\n");
printf("You entered:\n");
printList(top);
printf("\n\n");
printf("In reverse:\n");
printListReverse(last);
printf("\n\n");
printf("Enter a position to delete:");
scanf("%d", &n);
top = deleteByPos(top, &last, n);
printf("\n\n");
printf("In reverse after delete:\n");
printListReverse(last);
insertionSort(&top, &last);
printf("From top after sort:\n");
printList(top);
printf("In reverse after Sort:\n");
printListReverse(last);
}
What this program does is take user input of integers, stores them in a doubly linked list, deletes a node at a user defined point and then performs an insertion sort. What I am trying to do is save a pointer to the last node in the sortedInsert function with the following code:
if ((*top)->next == NULL) {
*last = *top;
}
However, if you enter 6 5 3 1 9 8 4 2 7 4 2, then delete at position 2, when printing in reverse it prints out 6 5 4 4 2 2 1. For some reason it skips over 9 7 8. I cannot figure out why or how to fix this. How can I do this properly?
With lists, it helps to draw a diagram for all the cases. It's natural to use induction on lists to prove your code is correct.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h> /* Asserting is useful when it come to lists especially. */
struct node {
struct node* next;
struct node* prev;
int data;
};
/* Saves you from dealing with 'top' and 'tail' every time. */
struct list {
struct node *head, *tail;
};
/* https://en.wikipedia.org/wiki/Insertion_sort */
void insertionSort(struct list* list) {
struct node* i = list->head, *j0, *j1;
while(i) {
j1 = i, j0 = j1->prev;
while(j0 && j0->data > j1->data) {
/* Swap. */
int temp = j0->data;
j0->data = j1->data;
j1->data = temp;
/* Decrement. */
j1 = j0;
j0 = j0->prev;
}
i = i->next;
}
}
/* Returns whether the position was deleted. */
int deleteByPos(struct list* list, int position) {
struct node* n;
assert(list);
/* Node n is the position's in the list. */
for(n = list->head; n && position; n = n->next, position--);
if (n==NULL) {
printf("No nodes available to delete\n\n");
return 0;
}
/* Fixme: If I'm not mistaken, there are 9 cases for you to be
mathematically certain this works, and I haven't tried them all.
Eg, 1 node, 2 nodes x2, 3 nodes x3, where the internal node is the 2nd of
the 3 nodes. */
if(n->prev == NULL) {
/* The first one. */
assert(list->head == n);
list->head = n->next;
if(n->next) n->next->prev = NULL;
} else {
/* Skip over. */
n->prev->next = n->next;
}
if(n->next == NULL) {
/* The last one. */
assert(list->tail == n);
list->tail = n->prev;
if(n->prev) n->prev->next = NULL;
} else {
/* Skip over. */
n->next->prev = n->prev;
}
n->prev = n->next = NULL; /* Helps in debugging. */
free(n);
return 1;
}
struct node* makeNode(struct list *list, int n) {
struct node* np = malloc(sizeof *np);
if(!np) return 0;
np->data = n;
np->prev = list->tail;
np->next = NULL;
/* Push it in the list. */
if(list->tail) {
assert(list->head != NULL && list->tail->next == NULL);
list->tail->next = np;
} else {
/* The first one. */
assert(list->head == NULL && list->tail == NULL);
list->head = np;
}
list->tail = np;
return np;
}
void printList(const struct list*const list) {
const struct node *n = list->head;
while (n) {
printf("%d\n", n->data);
n = n->next;
}
}
void printListReverse(const struct list*const list) {
const struct node *n = list->tail;
while (n) {
printf("%d\n", n->data);
n = n->prev;
}
}
int main(void) {
int n;
struct list list = { 0, 0 };
printf("Enter integers to add to list\n");
while(scanf("%d", &n) == 1 && n)
if(!makeNode(&list, n)) return perror("node"), EXIT_FAILURE;
printf("\n\n");
printf("You entered:\n");
printList(&list);
printf("\n\n");
printf("In reverse:\n");
printListReverse(&list);
printf("\n\n");
printf("Enter a position to delete:");
scanf("%d", &n);
printf("You entered %d.\n", n);
deleteByPos(&list, n);
printf("\n\n");
printf("In reverse after delete:\n");
printListReverse(&list);
insertionSort(&list);
printf("From top after sort:\n");
printList(&list);
printf("In reverse after Sort:\n");
printListReverse(&list);
return EXIT_SUCCESS;
}
*One would ideally free memory on exit.
It is usually much simpler to use a sentinel node rather than NULL to indicate the end of a list. So an empty list consists of a node whose head and tail point to itself. Once you add elements, sentinel->next is the first in the list and sentinel->prev is the last in the list. This removes many of the cases you have to test for NULL in your code:
#ifndef driver_h
#define driver_h
#include <stdio.h>
#include <stdlib.h>
typedef struct node node;
typedef struct nodePtrs nodePtrs;
struct node {
node* next;
node* prev;
int data;
};
void sortedInsert(node* top, node* newNode) {
node* current = top;
while (current->next != top &&
current->next->data < newNode->data) {
current = current->next;
}
newNode->next = current->next;
newNode->next->prev = newNode;
current->next = newNode;
current->next->prev = current;
}
void insertionSort(node* top) {
node* current = top->next;
// make top an empty ring so can append to it
top->next = top->prev = top;
while (current != top) {
node* next = current->next;
sortedInsert(top, current);
current = next;
}
}
node* deleteByPos(node* top,int position) {
int c = 0;
node* temp = top->next;
while (true) {
if (temp == top) {
printf("Reached end of list, position not available\n\n");
return top;
}
if (c == position) {
temp->prev->next = temp->next;
temp->next->prev = temp->prev;
free(temp);
return top;
}
temp = temp->next;
c++;
}
}
node* makeNode(int n) {
node* np = malloc(sizeof(node));
np->data = n;
np->prev = np;
np->next = np;
return np;
}
void printList(node* top) {
for (node* np = top->next; np != top; np = np->next) {
printf("%d\n", np->data);
}
}
void printListReverse(node* top) {
for (node* np = top->prev; np != top; np = np->prev) {
printf("%d\n", np->data);
}
}
#endif /* driver_h */
main file :
#include "driver.h"
int main() {
int n;
node* np;
node* top;
top= makeNode(0);
printf("Enter integers to add to list\n");
do {
if (scanf_s("%d", &n) != 1) {
n = 0;
}
if (n != 0) {
np = makeNode(n);
np->prev = top->prev;
top->prev = np;
top->prev->next = top;
np->prev->next = np;
}
} while (n != 0);
I am trying to code very basic sorting method for linked lists. I am getting unhandled exception. What is the mistake i am making? Here is my code:-
struct LinkedNode// structure for linked list
{
int data;
struct LinkedNode *next;
}*start = NULL;
following function creates a linked list
void CreateLinkedList()
{
LinkedNode *newNode, *current;
printf("enter 5 numbers to create linked list\n");
for(int i=0; i<5; i++)
{
newNode = (struct LinkedNode *)malloc(sizeof(LinkedNode));
scanf("%d", &newNode->data);
newNode->next = NULL;
if(start == NULL)
{
start = newNode;
current = newNode;
}
else
{
current->next = newNode;
current = newNode;
}
}
}
following function is used for sorting the linked list nodes
void SortLinkedList()
{
struct LinkedNode *node=NULL, *temp = NULL;
int tempvar;//temp variable to store node data
node = start;
temp = node->next;//temp node to hold node data and next link
while(node != NULL && node->next != NULL)
{
for(int j=0; j<5; j++)//value 5 because I am taking only 5 nodes
{
if(node->data > temp->data)//swap node data
{
tempvar = node->data;
node->data = temp->data;
temp->data = tempvar;
}
temp = temp->next;
}
node = node->next;
}
}
Try This code
void SortLinkedList()
{
struct LinkedNode *node=NULL, *temp = NULL;
int tempvar;//temp variable to store node data
node = start;
//temp = node;//temp node to hold node data and next link
while(node != NULL)
{
temp=node;
while (temp->next !=NULL)//travel till the second last element
{
if(temp->data > temp->next->data)// compare the data of the nodes
{
tempvar = temp->data;
temp->data = temp->next->data;// swap the data
temp->next->data = tempvar;
}
temp = temp->next; // move to the next element
}
node = node->next; // move to the next node
}
}
1 - outer while loop is use for the total number of pass that will require to sort the linked list..
2- In second while loop we are actually comparing the data of the nodes that we want to sort
Instead of implementing your own sort, you can just use qsort. Of course, qsort requires an array, but that is easy enough to create.
In this case, you know that the list has 5 members. But, if you didn't know, you could just count them.
int size_of_list = 0;
struct LinkedNode *p;
for (p = start; p != NULL; p = p->next) ++size_of_list;
if (size_of_list == 0) {
// Nothing to do
return;
}
Now you can create your array;
struct LinkedNode *arr[size_of_list + 1], **arrp = arr;
for (p = start; p != NULL; p = p->next) *arrp++ = p;
*arrp = NULL;
Then, use qsort on arr. There are lots of examples, but the trick is writing an appropriate comparison function.
int cmp_LinkedNode(const void *a, const void *b) {
const struct LinkedNode * const *aa = a;
const struct LinkedNode * const *bb = b;
return ((*aa)->data > (*bb)->data) - ((*aa)->data < (*bb)->data);
}
//...
qsort(arr, size_of_list, sizeof(*arr), cmp_LinkedNode);
And then, rewire the list into the sorted order.
for (int i = 0; i < size_of_list; ++i) arr[i]->next = arr[i+1];
start = arr[0];
yeah sorting a linked list using nodes/links is a pretty hard job. Spend hours doing it myself but since i have done it why not help others..
What you need to do is simply find the minimum value in your list. Swap it with the head node and the recur for head->next.
The code for sort is only of 3 to 4 lines if you have FindMin() and Swap() functions made..
here is the complete code for sort(),swap()and findmin().
void sort(node **start)
{
if (((*start)->next == NULL) || (*start == NULL))
{
return;
}
node *min = findmin(*start);
swap(*start, min, start);
sort(&((*start)->next));
}
void swap(node *p1, node *p2, node **start)
{
node *p1pre = NULL;
node *p1curr = *start;
while (p1curr!=p1)
{
p1pre = p1curr;
p1curr = p1curr->next;
}
node *p2pre = NULL;
node *p2curr = *start;
while (p2curr != p2)
{
p2pre = p2curr;
p2curr = p2curr->next;
}
if (p1pre != NULL)
{
p1pre->next = p2curr;
}
else
{
*start = p2curr;
}
if (p2pre != NULL)
{
p2pre->next = p1curr;
}
else
{
*start = p1curr;
}
node *temp = p2curr->next;
p2curr->next = p1curr->next;
p1curr->next = temp;
}
node* findmin(node *start)
{
int flag = 0;
if (start == NULL)
{
cout << "list is empty" << endl;
}
else
{
node *curr = start->next;
node *min = start;
while (curr->next != NULL)
{
if (min->value > curr->value)
{
min = curr;
flag++;
}
curr = curr->next;
}
if ((curr->next == NULL) && (min->value > curr->value))
{
min = curr;
flag++;
}
if (flag > 0)
{
return min;
}
}
}